One minute mvs: catalogs and datasets.

In days of old, when 64KB was a lot of real storage, to reference a data set you had to specify the data set name and the DASD volume the data set was on. DSN=MY.JCL,VOL=SER=USER00

After this, the idea of a catalog was developed. Just like the catalog in a library, it told you where things were stored. When you created a data set, and specified DISP=(NEW,CATLG), the data set name and volume were stored in the catalog. When you wanted to use a data set, and did not specify the volume, then the catalog was used to find the volume for the data set.

As systems grew and the number of data sets grew, the catalog grew and quickly became difficult to manage. For example if you deleted data sets, the entry was logically removed from the catalog, resulting in gaps in the catalog.

After this a multi level catalog was developed. You have one master catalog. You can have many user catalogs. You define an alias in the master catalog saying for data sets starting with a specific high level qualifier, use that user catalog.

When a userid was created, most system programmers would also create an alias pointing to a user catalog. They may define a user catalog for each user, or a user catalog could be shared by many aliases.

The catalogs are managed by the VSAM component of z/OS.

Entity naming

PDS and sequential files are referred to as datasets. VSAM provides simple database objects,

  • Relative Record ( where you say get me the n’th record)
  • Key sequence. You define a primary index, and you can an index on different columns using an ALTERNATIVE INDEX. 

VSAM uses the term cluster to what you use in you JCL or application. A cluster has a data component, and zero or more index components.

Moving systems.

I have been running on a self contained ADCD system at z/OS level 2.4. I have recently installed a self contained system at z/OS 2.5. How do I get my data sets into the new system?
You can import connect a user catalog into a new (master) catalog, and define an alias in the new master catalog pointing to the user catalog.

When I did this I could then see my COLIN.* data sets. To be able to use the data sets, I need the volumes to be attached to the z/OS system.

Useful IDCAMS commands

In batch you use the IDCAMS program (IDC = prefix for VSAM, AMS is for Access Management Services!)

If you do not specify a catalog, it defaults to the master catalog.

Create a user catalog

//IBMDF  JOB 1,MSGCLASS=H                                   
//S1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE USERCATALOG -
( NAME('A4USR1.ICFCAT') -
MEGABYTES(15 15) -
VOLUME(A4USR1) -
ICFCATALOG -
FREESPACE(10 10) -
STRNO(3 ) ) -
DATA( CONTROLINTERVALSIZE(4096) -
BUFND(4) ) -
INDEX(BUFNI(4) )
/*

List an entry

You can list information about an entry, such as a data set, or a catalog using the LISTCAT command

LISTCAT ENT(COLIN.USERS) ALL

Listing aliases

You can use the IDCAMS command LISTCAT with alias

LISTCAT ALIAS

which gives a one line per entry list of all of the aliases

ALIAS --------- ADCDA       
ALIAS --------- ADCDB
ALIAS --------- ADCDC
ALIAS --------- ADCDD
...

LISTCAT ALIAS ALL

gives

ALIAS --------- ADCDA                                                       
...
ENCRYPTIONDATA
DATA SET ENCRYPTION-----(NO)
ASSOCIATIONS
USERCAT--USERCAT.Z24C.USER
ALIAS --------- ADCDB
...
ENCRYPTIONDATA
DATA SET ENCRYPTION-----(NO)
ASSOCIATIONS
USERCAT--USERCAT.Z24C.USER

So we can see that the the alias ADCDA maps to user catalog USERCAT.Z24C.USER

Listing a catalog

The command

LISTCAT CATALOG(USERCAT.Z24C.USER)

gives

CLUSTER ------- 00000000000000000000000000000000000000000000       
DATA ------- USERCAT.Z24C.USER
INDEX ------ USERCAT.Z24C.USER.CATINDEX
NONVSAM ------- ADCDA.S0W1.ISPF.ISPPROF
NONVSAM ------- ADCDA.S0W1.SPFLOG1.LIST
NONVSAM ------- ADCDB.S0W1.ISPF.ISPPROF
...
CLUSTER ------- SYS1.VVDS.VC4CFG1
DATA ------- SYS1.VVDS.VC4CFG1

Which shows there is a data component of the catalog called USERCAT.Z24C.USER, and there is index component called USERCAT.Z24C.USER.CATINDEX.

The catalog has a data component (USERCAT.Z24C.USER) and an index component USERCAT.Z24C.USER.CATINDEX.

Within the catalog are entries for data sets such as ADCDA.S0W1.ISPF.ISPPROF, and system (DFDSS) dataset SYS1.VVDS.VC4CFG1 - which contains information what is on the SMS DASD volume C4CFG1.

One minute MVS: Networking subnets.

I’ve understood and used subnets, (in a hand waving way), but found it hard to write down what they are good for, and why we have them. There are many explanations on the web but they all seemed to describe how to use subnets, and not why we need them. Some of what I say below, may be strictly not true, but I hope it gives the right concepts.

  • You can use an Ethernet cable to join two machines. This is not very interesting.
  • You can have an Ethernet router. You plug the Ethernet cable from your machine to one of the ports on the Ethernet router.
  • The Ethernet router has devices attached to it with addresses such as 192.168.1.160, 192.168.1.24, 192.168.1.74. The router handles traffic for 192.168.1.* The IP address is 32 bits long, and the router is configured so that if the top 24 bits of an address are 192.168.1, then pass the traffic to the router. This is written as 192.168.1.0/24. The remaining 8 bits can be used for devices attached to the router, so almost 256 devices. (192.168.1.0 and 192.168.1.255 are reserved).
  • If you had a large building you could configure a router with address 192.169/16 and have 65,000+ devices attached to it. This may not be a good idea.
    • The router sends out management packets to all devices in the subnet saying, for example “does anyone have this IP address”. With many devices the router could spend all its time processing these management packets, and not handling user data
    • You may want to segregate different areas, so addresses 192.168.1.* is for the first floor, and 192.168.2.* is for the second floor. If you want to have a firewall for the first floor it is much easier configuring all traffic going to 192.168.1.* rather than for some machines within 192.168.* and so all users are using the firewall – which may not be what you want.
    • Each floor has a confidential printer. It is easier to configure the printer so that only machines with the same subnet address, IP address 192.168.1.* can send print files to the printer on 192.168.1.22, rather than filter out users on the second floor.
  • With IP V6 there are 128 bits available for subnetting. Mostly a subnet of /64 is used. I have an address 2a00:9999:8888:7777:a0cd:ec92:bceb:91ab/64 so 2a00:9999:8888:7777 is the address of my router (64 bits), and the device on the router is currently a0cd:ec92:bceb:91ab (64 bits).

Basic connectivity

Single point to point cable

My laptop is connected to my server by an Ethernet cable.

I’ve defined the address at each end 10.1.0.2/24 at the laptop and 10.1.0.3/24 at the server. I can ping between the two machines. When I changed the server to have 12.1.0.3/24 there was no connectivity – because they were in different subnets.

Wireless connection – IPV4

My system was configured automatically to have the laptop 192.168.1.222/24 and the server 192.168.1.222/24. These are the same subnet, so traffic goes from my laptop up the wireless connection to the wireless router, and to the server over the wireless connection.

Wireless connection – IPV6

My system was configured automatically to have the laptop a prefix (subnet) of fe80 and specific address c82d:b94c:21fa:3d1c with this this subnet. The server had prefix (subnet) fe80 and specific address c82d:b94c:21fa:3d1c.

The default routing is via device (the wireless router) with prefix (subnet) fe80 and address c82d:b94c:21fa:3d1. These are both “internal to the router” addresses.

Today my laptop also has IP address 2a00:9999:8888:7777:a0cd:ec92:bceb:91ab/64 and my server has address2a00:9999:8888:7777:605a:2d22:5daf:53d7/64. These can be used to contact sites on the internet, because they are external addresses.

Getting out of the subnet.

My server has a connection over virtual Ethernet to z/OS. The server end of this link has address 10.1.3.1/24. If I use wireless connection from my laptop to the server, I cannot easily access this link, because the wireless router does not know about 10.1.3.1 – and I have no way of configuring it.

On Linux I can configure the server to be a software router (radvd), and have a physical Ethernet cable to the it from my laptop. This way I can control the IP routing to and from the server.

You can also use a bridge … but that is an advanced topic.

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.
...

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.

One minute MVS – Using individual data set encryption on z/OS.

Overview

You can have full disk encryption. This prevents the disk from being read if it is removed from the environment. The disk subsystem requests the keys from a key manager, not z/OS, as the disk subsystem is doing the encryption and decryption. The keys are requested at power on of the disk subsystem.

On z/OS you can have data set encryption. The data set contents are encrypted on disk. Each data set could have a unique encryption key. Users on the system need permission to read the data set, and need access to the encrypt key.

If a userid is permitted to the data set, and to the encryption key, the userid has access to the data and can read and write it the same was as if the data set was not encrypted.

Once you have set up the definitions, they are used when the data set is created. To encrypt a data set, you can…

  • Create a new (encrypted) dataset
  • Copy the old to the new.
  • Delete the old, and rename the new to old.

If you delete the key, then the data is not accessible unless you have a backup of the key – or you have a copy of the key on another system.

This encryption does not apply to files in Unix System Services, because these are not RACF protected.

MQ 9.2 and later supports encryption, including for page sets and log data sets. See here. DB2 can use data set encryption for its page sets and logs, see here.

Topics

Implementation

You create an encryption key using the ICSF component on z/OS.

ISPF interface

If you are using the ICSF ISPF interface use options use : 5 Utility, 5 CKDS Keys, 7 Generate AES DATA keys. In the field Enter the CKDS record label for the new AES DATA key enter a memorable name. In the Red book, it uses a prefix of DATASET.name , I used COLINAES.

In AES key bit length: select 256 – other values give errors.

Batch interface

Use the operator command d icsf,kds to display the current datasets being used by ICSF. It gave me CSF.CSFCKDS.NEW .

The JCL below deletes the key, and creates a new key. It then refreshes the in memory data. (Once you delete the key, any data sets which used it cannot be read).

//IBMICSF  JOB 1,MSGCLASS=H 
//STEP10 EXEC PGM=CSFKGUP 
//  SET CKDS=CSF.CSFCKDS.NEW 
//CSFCKDS DD DISP=OLD,DSN=&CKDS 
//* LENGTH(32) GENERATES A 256 BIT KEY 
//CSFIN DD *,LRECL=80 
DELETE TYPE(DATA) LABEL(COLINBATCHAES ) 
ADD TYPE(DATA) ALGORITHM(AES), 
LABEL(COLINBATCHAES          ) LENGTH(32) 
/* 
//CSFDIAG DD SYSOUT=*,LRECL=133 
//CSFKEYS DD SYSOUT=*,LRECL=1044 
//CSFSTMNT DD SYSOUT=*,LRECL=80 
//* Refresh the in memory data
//REFRESH  EXEC PGM=CSFEUTIL,PARM='&CKDS,REFRESH' 

This gave

CSFG0321 STATEMENT SUCCESSFULLY PROCESSED.
CSFG0780 A REFRESH OF THE IN-STORAGE CKDS IS NECESSARY TO ACTIVATE CHANGES MADE BY KGUP.

and the refresh gave

CSFU002I CSFEUTIL COMPLETED, RETURN CODE = 0, REASON CODE = 0

Security profiles

The encryption information is used when the data set is created. This can be specified in JCL, VSAM DEFINE, or in the DFP extension of a dataset RACF profile.

Create and use the encryption key profiles

Use batch TSO. The statements below:

  • Uses SET to define the variable, as it is used in several places
  • Delete the old profile (there is no define replace)
  • Create the profile
  • Give userid IBMUSER read access to the profile
  • Refreshes the RACLIST information
  • Alters the data sets profile to set the DFP segment to use the key just defined
//IBMRACF2 JOB 1,MSGCLASS=H 
// SET KEY=COLINAES
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *,SYMBOLS=JCLONLY
RDELETE CSFKEYS &KEY
RDEFINE CSFKEYS &KEY +
ICSF(SYMCPACFWRAP(YES) SYMCPACFRET(YES)) +
UACC(NONE)
PERMIT &KEY +
CLASS(CSFKEYS) ID(IBMUSER ) +
ACCESS(READ)
SETROPTS RACLIST(CSFKEYS) REFRESH

RLIST CSFKEYS &KEY AUTHUSER ICSF


ALTDSD 'COLIN.ENCR.*' UACC(NONE) +
DFP(DATAKEY(&KEY))

/*
//* LISTCAT ENTRIES('COLIN.ENCR.DSN') ALL

This encryption information is only used when a data is created.

If you use LISTCAT, it will show old information, until the data set is recreated.

Use the definitions with a dataset

You can specify the encryption key reference in

  • JCL using DSKEYLBL
  • Via a RACF data set profile and the DFP extension
  • DEFINE IDCAMS, with KEYLABEL(MYLABEL)
  • SMS definitions

If there is no DFP segment to the RACF profile you can use

//SYSUT2 DD   DSN=COLIN.ENCR.DSN,SPACE=(CYL,(1,1)), 
//       DSKEYLBL=COLINBATCHAES, 
//       DISP=(MOD,CATLG), 
//       DCB=(RECFM=FB,LRECL=80,BLKSIZE=800) 

In the JCL output it has

IGD17150I DATA SET COLIN.ENCR.DSN IS ELIGIBLE FOR ACCESS METHOD ENCRYPTION. KEY LABEL IS (COLINBATCHAES)

LISTCAT output gave

LISTCAT ENTRIES('COLIN.ENCR.DSN') ALL                           
NONVSAM ------- COLIN.ENCR.DSN                                  
     IN-CAT --- A4USR1.ICFCAT                                   
     HISTORY                                                    
       ...  
     SMSDATA                                                    
      ... 
     ENCRYPTIONDATA                                             
       DATA SET ENCRYPTION----(YES)
       DATA SET KEY LABEL-----COLINBATCHAES                              

Doing interesting things with encrypted data sets

You can use DFDSS to copy the encrypted dataset, without decrypting it. Any encryption parameters are copied to the new data set.

You need access to the CSFKEYS profile.

The JCL below

  • Deletes the old data set
  • Copies from COLIN.ENCR.DSN creating the output renaming COLIN to ADCD
  • List the catalog for the output data set
//IBMDFDSS JOB 1,MSGCLASS=H                                       
//S1 EXEC PGM=IEFBR14,REGION=0M                                  
//SYSPRINT DD SYSOUT=*                                            
//DDOLD DD DSN=ADCD.ENCR.DSN,SPACE=(CYL,(1,1)),DISP=(MOD,DELETE) 
//* 
//S1  EXEC PGM=ADRDSSU,REGION=0M PARM='TYPRUN=NORUN'              
//SYSPRINT DD SYSOUT=*                                            
//SYSIN DD *                                                      
 COPY  -                                                          
    DATASET(INCLUDE(COLIN.ENCR.DSN))       -               
    REPLACE  -                                                    
    RENUNC(ADCD )                                                 
/*                                                                
//S1  EXEC PGM=IKJEFT01,REGION=0M                                 
//SYSPRINT DD SYSOUT=*                                            
//SYSTSPRT DD SYSOUT=*                                            
//SYSTSIN DD *                                                    
LISTCAT ENTRIES('ADCD.ENCR.DSN') ALL                              
/*                                                                

The userid(COLIN) that ran this job had permission to read the data set, and has access to the key.

The output data set has

ENCRYPTIONDATA                      
  DATA SET ENCRYPTION----(YES)      
  DATA SET KEY LABEL-----COLINBATCHAES   

The data set has been copied encrypted with the same key as the original data set.

You can print the encrypted data in the file using DFDSS (ADRDSSU) PRINT DATASET(..) command.

Other questions

Does the size of the data set change?

It looks like the encrypted dataset is the same size as the unencrypted data set.

What happens if I delete and recreate the encryption key?

DFDDSS COPY worked (RC 0) – but gave a message IEC143I 213-91 which means the label points to a different key.

If I try to read the copied data set, I get the same message. The data set can be copied, but cannot be decrypted.

The key has been thrown away, and the contents are unreadable unless you have a backup of the key, or have a copy of the key on another system.

One minute MVS: DLLs and load modules

This is one of a series of short blog posts on z/OS topics. This post is about using Dynamic Link Library. It follows on from One minute MVS: Binder and loader which explains some of the concepts used.

Self contained load modules are good but…

An application may have a main program and use external functions bound to the main program. This is fine for the simple case. In more complex environments where a program loads external modules this may be less effective.

If MOD1 and MOD2 are modules and they both have common subroutines MYSUBS, then when MOD1 and MOD2 are loaded, they each have a copy of MYSUBS. This can lead to inefficient use of storage (and not as fast as one copy which every thing uses).

You may not be responsible for MYSUBS, you just use the code. If they are bound to your load module, then in order to use a later version you will have to rebind your load modules. This is not very usable.

Stubs are better

There are several techniques to get round these problems.

In your program you can use a stub module. This sits between your application and the code which does all of the work.

  • For example for many of the z/OS provided facilities, the stub modules chain through z/OS control blocks to find the address of the routine to use.
  • You can have the subroutine code in a self-contained load module. Your stub can load the module then branch to it. This way you can use the latest available version of code. For example MQCONN loads a module, other MQ verbs use the module, MQDISC releases the load module.

If the stub loads a module, then other threads using the stub just increment the in-use count and do not have to reload the module (from disk). This means you do not have multiple copies of the load module in memory.

The Dynamic Link Library support does this load of the module for you, is it a build option rather than change your code.

Creating a DLL Object

When you compile the C source you need to have options DLL and EXPORTALL. (The documentation says it is better to use #PRAGMA EXPORT(name) for each entry, rather than use the EXPORTALL option – but this means making a small change to your program).

When you bind the module you need parameter DYNAM=DLL, and specify //BIND.SYSDEFSD DD… pointing to a member, for example COLIN.SIDE(CERT)

The member will have information (known as a side deck) with information about the functions your program has exposed. For example

 IMPORT DATA,'CERT','ascii_tab' 
 IMPORT DATA,'CERT','other_tab'  
 IMPORT CODE,'CERT','isbase64'                       
 IMPORT CODE,'CERT','printHex'                    
 IMPORT CODE,'CERT','UnBase64'                    f

Where

  • IMPORT …. ‘CERT’ says these are for load module CERT
  • IMPORT DATA – these labels are data constants
  • IMPORT CODE – these are functions within CERT

If this was a 64 bit program, it would have IMPORT CODE64, and IMPORT DATA64.

If you compile in Unix Services you get a side-deck file like /u/tmp/console/cert.x containing

IMPORT DATA64,'cert.so','ascii_tab'                                         IMPORT CODE64,'cert.so','isbase64'
...

and the load module /u/tmp/console/cert.so.

The .x file is only used by the binder. The .so file is loaded and used by programs.

When your program tries to use one of these functions, for example isbase64, module CERT(cert.so) is loaded and used. This means you need the library containing this module to be available to the job.

Binding with the DLL

Instead of binding your program with the CERT object. You bind it with the side deck and use the equivalent to INCLUDE COLIN.SIDE(CERT).
The binder associates the external reference isbase64 with the code in load module CERT.

Conceptually the isbase64 reference, points to some stub code which does

  • Load module CERT
  • Find entry point isbase64 within this module
  • Replace the address of the isbase64 external reference, so it now points to the real isbase64 entry point in module CERT.
  • Branch to the real isbase64 code.

The next time isbase64 is used – it goes directly to the isbase64 function in the CERT module.

Using DLLs

You can use DLLs in Unix, or normal address spaces.

For a program running in Unix services you can use the C run time functions

  • dlopen(modules_name)
  • dlclose(dlHandle) release the module
  • dlsym(dlHandle,function_name|variable_name) to get information about a function name or variable
  • dlerror() to get diagnostic information about the last dynamic link error

One minute MVS: Binder and loader

This topic is in the series of “One minute MVS” giving the essentials of a topic.

Your program

The use of functions or subroutines are very common in programming. For a simple call

x = mysub()

which calls an external function mysub has generated code like

MYPROG  CSECT     
     L 15,mysub the function 
     LA 1,PARMLIB
     BASR  14,15 or BALR in older programs 
...
mysub  DC  V(MYSUB)

where

  • MYPROG is an entry point to the program
  • the mysub variable defines some storage for the external reference(ER) to MYSUB.

The output of the assembler or compiler is a file or dataset member, known as an an “object deck” or “object file”. It cannot be executed, as it does not have the external functions or subroutines.

The binder (or linkage editor)

The binder program takes object decks, includes any subroutines and external code and creates a load module or program object.

In early days load modules were stored in PDS datasets. In the directory of a member was information about the size of the load module, and the entry point. As the binder got more sophisticated, the directory did not have enough space for all of the data that was created. As a result PDSE (Extended PDSs) were created, which have an extendable directory entry. For files in Unix Services Load modules are stored in the the Unix file system.

The term Program Object is used to cover load modules and files in the Unix file system. I still think of them both as Load Modules.

The binder takes the parts needed to create the program object, for example functions you created and are stored in a PDS or Unix, and includes code, for example for the prinf() function. These are merged into one file.

Pictorially the merged files look like

  • Offset 0 some C code.
  • Offset 200 MYPROG Object
    • Offset 10 within MYPROG, MYPROG entry point (so offset 210 from the start of the merged files)
    • Offset 200 within MYPROG, mysub:V(MYSUB)
    • Offset 310 within MYPROG end of MYPROG
  • Offset 512 FUNCTION1 object
  • Offset 800 MYSUB1 Object
    • Offset 28 within MYSUB1, MYSUB entry point
    • Offset 320 within MYSUB1, end of MYSUB

The binder can now resolve references. It knows that MYSUB entry point is at offset 28 within MYSUB1 object, and MYSUB1 Object is 800 from the start of the combined files. It can now replace the mysub:V(MYSUB) in MYPROG with the offset value 828.

The entire files is stored as a load module(program object) as one object, with a name that you give it, for example COLIN.

The loader

When load module COLIN is loaded. The loader loads the load module from disk into memory. For example at address 200,000. As part of the loading, it looks at the external references and calculates the address in memory from the offset value. So 200,000 + offset 828 is address 200828. This value is stored in the mysub variable.

When the function is about to be called via L 15,mysub, register 15 has the address of the code in memory and the program can branch to execute the code.

It gets more complex than this

Consider two source programs

int value = 0;
int total = 0;
void main()
{
  value =1;
  total = total + value; 
  printTotal();
  
}
int total;
int done;
void printotal()
{
  printf("Total = %d\n",total);
  done = 1; 
}

There are some global static variables. The variable “total” is used in each one – it is the same variable.

These programs are defined as being re-entrant, and could be loaded into read only storage.

The variables “value” and “total”, cannot go into read only storage as they change during the execution of the program.

There are three global variables: “value”, “total” and “done”; total is common to both programs.

These variables go into a storage area called Writeable Static Area (WSA).

If there are multiple threads running the program, each gets its own copy of the WSA, but they can all shared instructions.

A program can also have 31 bit resident code, and 64 bit resident code. The binder takes all of these parts and creates “classes” of data

  • The WSA class. This contains the merged list of static variables.
  • 64-bit re-entrant code – class. It takes the 64-bit resident code from all of the programs, and included subroutines and creates a “64-bit re-entrant” blob.
  • 31- bit re-entrant code -class. It takes the 31-bit resident code from all of the programs, and included subroutines and creates a “31-bit re-entrant” blob.
  • 64-bit data – class, from all objects
  • 31-bit data – class, from all objects

When the loader loads the modules

  • It creates a new copy of the WSA for each thread
  • It loads the 64 bit re-entrant code (or reuses any existing copy of the code) into 64 bit storage
  • It loads the 31 bit re-entrant code (or reuses any existing copy of the code) into 31 bit storage.

How can I see what is in the load module?

If you look at the output from the binder you get output which includes content like

CLASS  B_TEXT            LENGTH =      4F4  ATTRIBUTES = CAT,   LOAD, RMODE=ANY 
CLASS  C_DATA64          LENGTH =        0  ATTRIBUTES = CAT,   LOAD, RMODE=ANY 
CLASS  C_CODE64          LENGTH =     1A38  ATTRIBUTES = CAT,   LOAD, RMODE= 64 
CLASS  C_@@QPPA2         LENGTH =        8  ATTRIBUTES = MRG,   LOAD, RMODE= 64 
CLASS  C_CDA             LENGTH =     3B50  ATTRIBUTES = MRG,   LOAD, RMODE= 64 
CLASS  B_LIT             LENGTH =      140  ATTRIBUTES = CAT,   LOAD, RMODE=ANY 
CLASS  B_IMPEXP          LENGTH =      A6B  ATTRIBUTES = CAT,   LOAD, RMODE=ANY 
CLASS  C_WSA64           LENGTH =      6B8  ATTRIBUTES = MRG, DEFER , RMODE= 64 
CLASS  C_COPTIONS        LENGTH =      304  ATTRIBUTES = CAT, NOLOAD 
CLASS  B_PRV             LENGTH =        0  ATTRIBUTES = MRG, NOLOAD 

Where

  • B_TEXT is from HLASM (assembler program). Any sections are conCATenated together (Attributes =CAT)
  • C_WSA64 is the 64 bit WSA. Any data in these sections have been MeRGed (see the “total” variable above) (Attributes = MRG)
  • C_OPTIONS contains the list of C options used at compile time. The loader ignores this section (NOLOAD), but it is available for advanced programs such as debuggers to extract this information from the load module.

To introduce even more complexity. You can have class segments. These are an advanced topic where you want groups of classes to be independently loaded. Most people use the default of 1 segment.

Layout of the load module

Class layout

You can see the layout of the classes in the segment.

  • Class B_TEXT starts at offset 0 and is length 4F4.
  • Class C_CODE64 is offset 4F8 (4F4 rounded up to the nearest doubleword) and of length 1A38.
CLASS  B_TEXT            LENGTH =      4F4  ATTRIBUTES = CAT,   LOAD, RMODE=ANY 
                         OFFSET =        0 IN SEGMENT 001     ALIGN = DBLWORD 
  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
CLASS  C_CODE64          LENGTH =     1A38  ATTRIBUTES = CAT,   LOAD, RMODE= 64 
                         OFFSET =      4F8 IN SEGMENT 001     ALIGN = DBLWORD ff

Within each class

CLASS  C_CODE64          LENGTH =     1A38  ATTRIBUTES = CAT,   LOAD, RMODE= 64 
                         OFFSET =      4F8 IN SEGMENT 001     ALIGN = DBLWORD 
--------------- 
                                                                                                  
 SECTION    CLASS                                      ------- SOURCE -------- 
  OFFSET   OFFSET  NAME                TYPE    LENGTH  DDNAME   SEQ  MEMBER 
                                                                                                  
                0  $PRIV000010        CSECT      1A38  /0000001  01 
       0        0     $PRIV000011        LABEL 
      B8       B8     PyInit_zconsole    LABEL 
     8B8      8B8     or_bit             LABEL 
     C30      C30     cthread            LABEL 
    1158     1158     cleanup            LABEL 
    11B8     11B8     printHex           LABEL 
  • The label $PRIV000010 CSECT is generated because I did not have a #pragma CSECT(CODE,”….”) statement in my source. If you use #pragma CSECT(STATIC,”….”) you get the name in the CLASS C_WSA64 section (see the following section)
  • The C function “or_bit” is at offset B8 in the class C_CODE64.

The static area

For the example below, the C module had #pragma CSECT(STATIC,”SZCONSOLE”)

CLASS  C_WSA64           LENGTH =      6B8  ATTRIBUTES = MRG, DEFER , RMODE= 64 
                         OFFSET =        0 IN SEGMENT 002     ALIGN = QDWORD 
--------------- 
                                                                                     
            CLASS 
           OFFSET  NAME                TYPE    LENGTH   SECTION 
                0  $PRIV000012      PART            10 
               10  SZCONSOLE        PART           5A0  ZCONSOLE 
              5B0  ascii_tab        PART           100  ascii_tab 
              6B0  gstate           PART             4  gstate 

There are two global static variables, common to all routines, ascii_tab, and gstate. They each have an entry defined in the class.

All of the static variables internal to routines are in the SZCONSOLE section. They do not have a explicit name because they are internal.

One minute SMS

For many people SMS is something on z/OS that gets in the way of doing real work, and you find you are trying to work around it. A bit like Clippy on Window.

SMS is System Managed Storage. Before SMS, the systems programmer would be responsible for which data sets go on which volume; how often to backup these data sets, and get annoyed when the z/OS users allocated data sets inefficiently, wasting space and using the wrong data set attributes.

SMS has made the systems programmers job much easier. Instead of having a list of disk volumes which can be used by developers, and a list of volumes reserved for systems people, then telling people which disk to use; SMS allows you to say group these volumes as SYSPROGS, and these volumes as OTHER, and when you allocate a data set the system says “COLIN.*” maps to OTHER; SYS1.* map to SYSPROGS.

You can disks have which are not SMS managed, but these days, most of the disks are SMS managed.

You can also specify rules such as all SYS1.*.PARMLIB get backed up daily – and keep the last 10 copies; and do not backup these temporary files.

The system can also do house keeping and say if these user data sets have not been used for a long period, backup them and move them to slower volumes or tape.

SMS topics

SMS has different “topics”.

A data class is used when creating a data set. It influences the space and data set attributes. You could set up a data class of USERFB80 for user data sets which are Fixed block 80 records. This data class can specify optimum block size to be used, and override any value the user has specified.

A management class provides information about how often it is to be backed up, how long it is to be kept for before automatic deletion, and if it can be compressed or moved out to tape if it has not been used for a period.

A Storage class provides information about which disk volumes to use. You may have some high performing disks, which you want databases to use, and some old spinning disks, for the end users to use.

A storage group is where data sets get created. For example storage group Pool SGCICS has volumes CICS00 through to CICS1F, storage group SGMQ has volumes SGMQS – MQ0000 through MQ004, and OLD001.

You can define a storage group which uses Virtual IO (paging), instead of disk. This is Storage Group VIO.

The Automatic Class Selection (ACS) is the magic which says “my datasets get fast disks”; “your data sets get slow disks, and the data sets are migrated out to tape if they haven’t been used for a week”. At a conceptual level it is like

if DSN in “SYS1.**” then STORCLAS = “SGSYS1”
if SIZE > 4052MB then DATACLAS= BIGFILE
Select
When(STORCLAS=”IMS”) then STORGRP = “SGIMS”
When(STORCLAS=”MQ”) then STORGRP=”SGMQ”
end

When are these visible?

I compiled a C program job. In the JCL output it had

IGD101I SMS ALLOCATED TO DDNAME (SYSLIN )
DSN (SYS22013.T150656.RA000.COLINC3.LOADSET.H01 )
STORCLAS (SCBASE) MGMTCLAS ( ) DATACLAS ( )
VOL SER NOS= VIO

So we can see the storage class used (SGBASE), and the data class, and management class (both not specified).

I’ve run out of space – but there is plenty of space.

I got the following message, and struggled to resolve the problem.

IGD17272I VOLUME SELECTION HAS FAILED FOR INSUFFICIENT SPACE FOR
DATA SET SYS21355.T163955.RA000.COLINMQ.TEMP.H01
JOBNAME (COLINMQ ) STEPNAME (S1 )
PROGNAME (AMATERSE) DDNAME (SYSUT2 )
REQUESTED SPACE QUANTITY = 415019 KB
STORCLAS (SCBASE) MGMTCLAS ( ) DATACLAS ( )
STORGRPS (SGBASE SGEXTEAV SGVIO )

SMS is clearly involved – but how to display more information? You can use ISPF ISMF panels to display information, but sometimes it is easier to use the DISPLAY SMS operator command. For example

What is the status of a volume

d sms,vol(C4USR1)
IGD002I DISPLAY SMS
VOLUME UNIT MVS   SYSTEM= 1   STORGRP NAME
C4USR1 0A9B ONRW          +   SGBASE
* LEGEND *
. THE STORAGE GROUP OR VOLUME IS NOT DEFINED TO THE SYSTEM
+ THE STORAGE GROUP OR VOLUME IS ENABLED
* - THE STORAGE GROUP OR VOLUME IS DISABLED
D THE STORAGE GROUP OR VOLUME IS QUIESCED
Q THE STORAGE GROUP OR VOLUME IS DISABLED FOR NEW ALLOCATIONS ONLY

Where the + in the line with the volume is described in the following lines. So the C4USR1 means the volume is enabled for SMS.

ONRW is ONline ReadWrite

What storage groups are defined?

D SMS,STORGRP(ALL)
D SMS,SG(SGBASE)

Gave

SGBASE POOL +
SPACE INFORMATION:
TOTAL SPACE = 16240MB USAGE% = 91 ALERT% = 0
TRACK-MANAGED SPACE = 16240MB USAGE% = 91 ALERT% = 0

if you want more information

D SMS,SG(SGBASE),LISTVOL

Gave

STORGRP TYPE SYSTEM= 1
SGBASE POOL +
SPACE INFORMATION:
TOTAL SPACE = 16240MB USAGE% = 91 ALERT% = 0
TRACK-MANAGED SPACE = 16240MB USAGE% = 91 ALERT% = 0 

VOLUME UNIT MVS SYSTEM= 1 STORGRP NAME
C4USR1 0A9B ONRW        + SGBASE
USER00 0A9C ONRW        + SGBASE
USER01                  + SGBASE
USER0A                  + SGBASE
...

There were lots of volumes defined … but only two were online and available.

Using ISMF with Storage groups

If you use

  • ISMF option 6 (Storage group)
  • Storage Group Name *
  • Option 1 (List)

This gave me

 LINE       STORGRP  SG                VIO      VIO  
 OPERATOR   NAME     TYPE              MAXSIZE  UNIT 
---(1)----  --(2)--- -------(3)------  --(4)--  (5)- 
            SGDB2    POOL              -------  ---- 
            SGEXTEAV POOL              -------  ---- 
            SGIMS    POOL              -------  ---- 
            SGMQS    POOL              -------  ---- 
            SGVIO    VIO               2000000  3390 
----------  -------- --------  ----------  ----------

We can see that the Storage Group SGVIO is of type VIO. The maximum dataset size that can be allocated in this is Storage Group. 2000000 is 2,000,000 KB.

SMS Enable/disable volumes

You can disable a volume from SMS using

V SMS,VOL(C4USR1),DISABLE

The command
D SMS,VOL(C4USR1)

now gives

VOLUME UNIT MVS    SYSTEM= 1 STORGRP NAME
C4USR1 0A9B ONRW           - SGBASE
+ THE STORAGE GROUP OR VOLUME IS ENABLED
- THE STORAGE GROUP OR VOLUME IS DISABLED

The JCL below will allocate a (temporary) data set on volume C4CFG1, and then delete it.

//IBMUSER1 JOB 1,MSGCLASS=H
//S1 EXEC PGM=IEFBR14
//DD1 DD DSN=&TEMP,DISP=(NEW,PASS),
// SPACE=(CYL,(1,1)),DCB=(LRECL=80,RECFM=FB),
// VOL=SER=(C4CFG1),
// STORCLAS=SCNOSMS
//S2 EXEC PGM=IEFBR14
//DD1 DD DSN=*.S1.DD1,DISP=(OLD,DELETE)

If I removed the STORCLAS=SCNOSMS, the data set was allocated on a different volume C4USR1 with STORCLAS (SCBASE).

Where are the definitions stored?
On my zD&T system, the ACS routines etc are defined in SYS1.S0W1.DFSMS.CNTL. I do not think SMS uses this directly. When creating definitions you may point the ISMF panels to members in this data set.

One minute MVS: LDAP defining resources

Having set up an LDAP server, you need to add information to the directory. This is not very well described in the TDS documentation.

Basic overview of data

To add information about a user use a file in USS like colin.ldif

dn: cn=colin, o=Your Company
objectclass: top
objectclass: person
objectclass: organizationalPerson
cn: LDAP Administrator
sn: Administrator

Where

  • the “key” to identify an entry is the dn ..
  • objectclass is the sort of object, and what attributes it can have. It can have many object classes
  • cn: and sn: are attribute values
  • There is a blank line following to indicate end of definition. You can have many of these in a file, to allow you to do a bulk update.

How do I display the contents?

You need to issue a query. This comes in two parts, identifying the user, and the request.

To identify requestor you need something like

ldapsearch -h 127.0.0.1 -D “cn=ibmuser, o=Your Company” -w ? …

and the query for example, to list all the information about cn=ibmuser, o=Your Company add the following to the ldapsearch request above

-b “cn=ibmuser, o=Your Company” “(objectclass=*)”

This gives

cn=ibmuser, o=Your Company
objectclass=top
objectclass=person
objectclass=organizationalPerson
objectclass=ibm-nativeAuthentication
cn=ibmuser
sn=Administrator
ibm-nativeid=IBMUSER

For all information under o=Your Company

-b “o=Your Company” “(objectclass=*)”

For only the list of sn for all users

-b “o=Your Company” “(objectclass=*)” sn

This gives

o=Your Company

cn=colinw, o=Your Company
sn=Administrator

cn=colin, o=Your Company
sn=Administrator

cn=LDAP Administrator, o=Your Company
sn=Administrator

cn=ibmuser, o=Your Company
sn=Administrator

What authority do I need?

Typically you need to be an LDAP administrator, or have the appropriate access to Access Control lists. See here for managing ACLs.

How do I add information?

If I want to add a userid definition for ibmuser (above) so I can login with RACF, I need to add attribute

ibm-nativeId: COLIN

This attribute is in object type

objectclass: ibm-nativeAuthentication

So to be able to specify the ibm-native-ID: attribute, you need to tell specify the object class as well.

My definition is now

dn: cn=colin, o=Your Company
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: ibm-nativeAuthentication
cn: LDAP Administrator
sn: Administrator
ibm-nativeId: COLIN

Add it to the directory

You can add this to the directory using

ldapmodify -a -h … -p … -D “…” -w … -f colin.ldif

Where

  • -a says add (instead of modify)
  • -f colin.ldif is the name of the file with the statements in it.

Modifying an entry

If you want to modify an existing entry, you can change the whole entry, or parts of it.

To add an entry

dn: cn=colin, o=Your Company
changetype: add
objectclass: top

To delete a whole entry

dn: cn=colin, o=Your Company
changetype: delete

To add an attribute to an entry

dn: cn=colin, o=Your Company
changetype: modify
add: attrccp
attrccp: value1
attrccp: value2…

This adds two attrccp values to the definition

To modify an existing attribute

dn: cn=colin, o=Your Company
changetype: modify
modify: ibm-nativeId
ibm-nativeId: PAICE

To delete an attribute

dn: cn=colin, o=Your Company
changetype: delete
delete: ibm-nativeId

This deletes all ibm-nativeID attributes.

If you want to delete a specific attribute specify it after the delete: line

dn: cn=colin, o=Your Company
changetype: delete
delete: attrccp
attrccp: value2

One minute MVS. Getting started with LDAP on ADCD.

LDAP is a standard protocol for accessing directory information over TCP/IP. For example the command

ldapsearch -h 127.0.0.1 -D “cn=Admin, o=Your Company” -w secret -b “o=Your Company” “(objectclass=*)” aclEntry

This sends a request to IP address 127.0.0.1 with userid cn=… and password “secret”, for information under the subtree of “o=Your Company” and requests is sends back information on any ACL entries.

z/OS implementation

LDAP on z/OS is also know as Tivoli Directory Server.

It can run with different backend databased from DB2 to a files in a USS directory. It can interface to RACF so you can use query userid and group information from RACF through LDAP.

Schemas.

You need to configure a schema of what fields there are, and the relationship. For example, for an organisation telephone directory you might have

dn: cn=LDAP Administrator, o=Your Company
objectclass: organizationalPerson
cn: LDAP Administrator
sn: Administrator
userPassword: ********
phoneNumber:1234567

Where

  • dn: cn=LDAP Administrator, o=Your Company This is the internal name of the object, and what part of the data tree it belongs to “o=Your Company
  • objectclass: organizationalPerson defines the object type
  • cn: LDAP Administrator This is the common name ( nick name) of the object
  • sn: Administrator This is the surname of the person
  • userPassword: ******** This is the user’s password. It has been defined that the value is not displayed
  • phoneNumber:1234567 This has been defined so that is can only take numbers and ‘-‘.

You can define your own attributes and properties. You just need to update the schema.

Which database is used?

A sample LDAP configuration might contain

database LDBM GLDBLD31/GLDBLD64
suffix “o=Your Company”
databaseDirectory /var/ldap/ldbm

  • database LDBM says there is a database in a USS directory
  • GLDBLD31/GLDBLD64 are the names of the interface routines to use.
  • suffix “o=Your Company” is the root of the subtree in this database
  • databaseDirectory /var/ldap/ldbm is the name of the USS directory

You can configure LDAP to say for these names(o=someoneElsesCompany) go to another LDAP with at this address.

If I use a query like ldapsearch -h 127.0.0.1 -D “cn=LDAP Administrator, o=Your Company” -w secret -b “o=Your Company” “(objectclass=*)” aclEntry…. the -D cn=LDAP Administrator, o=Your Company” says look for a userid with the given data in the o=Your Company subtree. With the above definitions it would look in the the USS file system under /var/ldap/ldbm, for a userid cn=LDAP Administrator, o=Your Company.

Configuring an LDAP server on ADCD.

ADCD is a preconfigured system which can on on zPDT and ZD&T. These provide a system 390 emulator. This system comes with a lot of software installed, and some subsystems such as z/OS, MQ, DB2, IMS, CICS and z/OSMF pre configured.

The software for LDAP(Tivoli Directory Server) is installed but not configured. The documentation is extensive, and the configuration file is very large (with lots of comments). You run a configuration script which produces some files.

However for a simple configuration you only need a few files to run.

Some of these files do not work – for example they try to define a userid with an existing Unix uid.

I’ve taken the updated files and put them on git hub.

The TDS documentation is here.

If you get into a mess you can just delete the /var/ldap/ldbm directory and start again!