Java Security
Java Security
Java Security
Patrick Kappeler Jonathan Barney Pierre Bda Michael Buzzetti Saheem Granados Ebbe Mlgaard Pedersen Kin Ng Michael Onghena Eysha Powers Martina Schmidt Richard Schultz
ibm.com/redbooks
International Technical Support Organization Java Security on z/OS - The Complete View December 2008
SG24-7610-00
Note: Before using this information and the product it supports, read the information in Notices on page ix.
First Edition (December 2008) This edition applies to Version 1, Release 10 of z/OS (Program Number 5694-A01).
Copyright International Business Machines Corporation 2008. All rights reserved. Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
Contents
Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .x Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi The team that wrote this book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi Become a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii Comments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii Part 1. Java and Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 1. Overview of Java on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.1 Why to choose Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1.1 Introduction to the Java programming language. . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1.2 Java package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Java Native Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2.1 Basic elements of the Java Native Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2.2 JNI and Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3 Accessing z/OS MVS datasets from Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3.1 Using the Java Record I/O API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.3.2 Using the JZOS toolkit API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.3.3 Running a Java program as a batch job . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3.4 Job management using the BPXBATCH and BPXBATSL utility programs . . . . . 11 1.4 Introduction to Java security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.1 The Java Virtual Machine Security framework components . . . . . . . . . . . . . . . . . 14 1.4.2 The byte code verifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4.3 SecurityManager and AccessController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.4.4 JAR file security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5 Java and z/OS security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.5.1 Authorized programs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.5.2 Program Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.5.3 APF, Program Control, and the z/OS JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.6 Exploiting System z hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.6.1 IBM System z Application Assist Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.6.2 Cryptographic hardware devices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Chapter 2. Java 2 authentication and authorization services. . . . . . . . . . . . . . . . . . . . 2.1 Introduction to Java Authentication and Authorization Service . . . . . . . . . . . . . . . . . . . 2.1.1 Differences between IBM JAAS on z/OS and Sun JAAS . . . . . . . . . . . . . . . . . . . 2.2 Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 JAAS LoginModule Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.2 JAAS sample application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Performance issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 26 27 28 29 30 34 42
Part 2. Platform-level security with z/OS Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Chapter 3. Introduction to z/OS Resource Access Control Facility . . . . . . . . . . . . . . . 47 3.1 What is RACF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.2 RACF infrastructure for identification, authentication, and authorization . . . . . . . . . . . 48
iii
3.2.1 The System Authorization Facility interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 RACF user, group, and resource profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 RACF commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Accessing RACF using the LDAP protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Administering RACF users and groups through LDAP . . . . . . . . . . . . . . . . . . . . . Chapter 4. System Authorization Facility interfaces in z/OS Java . . . . . . . . . . . . . . . . 4.1 System Authorization Facility interfaces in Java - overview . . . . . . . . . . . . . . . . . . . . . 4.2 Installation of SAF classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 The classes in detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 PlatformAccessLevel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.2 PlatformReturned . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.3 PlatformSecurityServer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.4 PlatformAccessControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.5 PlatformThread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.6 PlatformUser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 5. Java Security Administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Overview of Java Security Administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Java classes used . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4 Interface definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 UserGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.3 SecAdmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.4 SecAdminException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5 RACF implementing classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.1 RACF_User. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.2 RACF_Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.3 RACF_SecAdmin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4 RACF_remote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Usage and invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6.1 Running Java security code on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7 Sample code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.1 Simple program. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.2 Create groups and members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.3 Change password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 6. RACF PassTicket generation and evaluation by z/OS Java applications . 6.1 PassTicket overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 RACF configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.1 RACF PassTicket Application Profile definition. . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.2 Determining application name. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4 PassTicket evaluation versus logging on using a PassTicket . . . . . . . . . . . . . . . . . . . . 6.4.1 Permission to use PassTicket services from Java . . . . . . . . . . . . . . . . . . . . . . . . 6.5 PassTicket Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.1 Using Javadoc documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5.2 PassTicket generation from Java on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6 PassTicket evaluation from Java on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7 Audit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7.1 Tracing and debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.8 Miscellaneous PassTicket considerations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.8.1 One-time use of PassTickets and bypassing replay protection setting. . . . . . . . . iv
Java Security on z/OS - The Complete View
50 50 52 53 54 55 56 56 56 57 57 57 58 59 59 61 62 63 63 63 64 64 64 65 65 65 66 67 67 68 68 68 68 70 74 77 78 79 80 80 80 81 81 82 82 83 85 87 88 88 88
6.8.2 Scoping PassTicket Logon by user and group . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Chapter 7. z/OS Enterprise Identity Mapping for Java applications. . . . . . . . . . . . . . . 91 7.1 Enterprise Identity Mapping introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 7.1.1 The problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 7.1.2 Benefits of using EIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 7.1.3 EIM implementation concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 7.1.4 EIM components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 7.2 EIM Domain Controller overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 7.2.1 EIM LDAP Directory Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 7.2.2 Access control to the EIM Domain Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 7.2.3 LDAP setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 7.2.4 RACF profiles to keep EIM default parameters for LDAP bind information . . . . 101 7.2.5 RACF profiles to keep EIM default parameters for the local registry name . . . . 102 7.3 z/OS EIM Java API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 7.3.1 Configuring the EIM Java API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 7.4 Writing EIM Java applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 7.4.1 Basic EIM administration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 7.4.2 EIM runtime lookups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 7.5 A demonstration of EIM and other z/OS Java APIs . . . . . . . . . . . . . . . . . . . . . . . . . . 113 7.5.1 The eimjavademo application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 7.5.2 Setting up the demo environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 7.5.3 Running the demo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Part 3. z/OS Java cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 Chapter 8. Introduction to z/OS cryptography and Java . . . . . . . . . . . . . . . . . . . . . . . 121 8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Chapter 9. Introduction to Java Cryptographic Extension Framework and API . . . . 9.1 Java Cryptographic Extension overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 The JCE design point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 The JCE framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4 Cryptographic service providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.1 Installing and configuring providers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.2 Policy files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5 The IBM providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.1 IBMJCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.2 IBMJCE4578 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.3 IBMJSSE2 and IBMJSSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.4 IBMJCEFIPS and IBMJSSEFIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.5 IBMJAAS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.6 IBMJGSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.7 IBMSASL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6 The IBM providers - IBMJCECCA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7 The IBM providers - IBMPKCS11Impl. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7.1 Specific z/OS considerations for PKCS#11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chapter 10. Simple examples of Java cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1 Engine classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.1 SecureRandom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.2 MessageDigest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.3 Signature. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.4 Cipher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 126 126 127 128 128 130 131 131 132 133 133 135 135 136 136 138 139 145 146 146 147 147 148
Contents
10.1.5 KeyGenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 10.1.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . KeyPairGenerator149 10.2 Cryptographic services invocation examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 10.2.1 Random number generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 10.2.2 Message Digest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 10.2.3 Signature. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 10.2.4 Symmetric encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 10.2.5 Asymmetric encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 Chapter 11. Java and key management on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Key usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Introduction to Java key management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Interfaces and abstract classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 KeyStore-related classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 z/OS keystore details and provider requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.1 IBMJCE supported keystores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.2 IBMJCECCA supported keystores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.3 IBMPKCS11Impl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3.4 z/OS keystore repositories and JCE provider list requirements . . . . . . . . . . . . 11.4 Java programming and key management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1 Access control to z/OS resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2 UNIX System Services file system permissions . . . . . . . . . . . . . . . . . . . . . . . . 11.4.3 Access control to RACF key rings and certificates . . . . . . . . . . . . . . . . . . . . . . 11.5 A word about trust . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6 Java program examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.1 Dynamic Provider List example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.2 Generate X.509 certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.3 Reusing an existing RSA key in the ICSF PKDS . . . . . . . . . . . . . . . . . . . . . . . 11.6.4 Generate an AES CKDS key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.5 Generate a RACF RSA key pair with the private key in the PKDS . . . . . . . . . . Chapter 12. Usage examples - using Java keystores on z/OS . . . . . . . . . . . . . . . . . . 12.1 JCEKS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 JCECCAKS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 JCERACFKS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.4 JCECCARACFKS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.5 PKCS11IMPLKS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.6 Retrieving keys by their ICSF CKDS or PKDS label . . . . . . . . . . . . . . . . . . . . . . . . . 157 158 158 160 160 162 163 163 164 165 166 168 169 169 170 171 172 172 172 174 175 176 179 180 182 185 187 189 194
Part 4. Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Appendix A. z/OS integrated hardware cryptography setup details . . . . . . . . . . . . . Hardware components of the System z cryptography infrastructure . . . . . . . . . . . . . . . . . Cryptographic coprocessors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A word on clear keys and secure keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Trusted Key Entry workstation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . System z Application Assist Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The z/OS integrated hardware cryptography infrastructure . . . . . . . . . . . . . . . . . . . . . . . . Integrated Cryptographic Service Facility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java keystores and the ICSF VSAM datasets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hardware setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cryptographic devices and system families . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hardware installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi
Java Security on z/OS - The Complete View
199 200 200 202 203 203 203 204 205 205 205 206
Cryptographic hardware definitions on system z10 . . . . . . . . . . . . . . . . . . . . . . . . . . . Logical partition definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zAAP definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Software setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customizing SYSx.PARMLIB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ISPF panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Allocating CKDS, PKDS, and TKDS datasets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Startup procedure for ICSF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializing the Master Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pass Phrase Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
207 208 210 211 211 213 214 215 216 216
Appendix B. SAF sample code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Sample code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Appendix C. JSec sample code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a TSO user ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a protected user ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Deleting a user ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Showing attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Search users and groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appendix D. JSec attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . User attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Group attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Membership attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appendix E. EIM example setup program. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setup program: EimJavaSetup.java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Authentication program: EimJavaAuth.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Main program: EimJavaDemo.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appendix F. Basics of cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction to cryptography. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cryptographic algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Symmetric key algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Asymmetric key algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Padding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Encryption modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hybrid encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Digital signatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Digital certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Appendix G. Case study: IBM Encryption Key Manager . . . . . . . . . . . . . . . . . . . . . . . EKM overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java cryptographic providers used by EKM on z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . EKM network traffic security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EKM and z/OS keystores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Synchronization of multiple keystores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A possible extension to EKM capabilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a symmetric secure key in the ICSF CKDS . . . . . . . . . . . . . . . . . . . . . . . . . . Referring to the secure symmetric key in the CKDS. . . . . . . . . . . . . . . . . . . . . . . . . . . Using the secure symmetric key with EKM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 226 227 228 229 230 235 236 250 251 253 254 255 256 259 260 260 260 261 261 261 262 263 265 267 268 268 269 270 271 271 272 273 273
Appendix H. Performance case study: IBM Encryption Facility for z/OS OpenPGP support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Contents
vii
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IBM Java SDK 6 Runtime Environment for z/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . System z specialized Hardware: zAAP and CPACF. . . . . . . . . . . . . . . . . . . . . . . . . . . Encryption Facility OpenPGP support. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . General CP time reduction using System z specialized hardware. . . . . . . . . . . . . . . . . . . Hardware cryptographic acceleration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zAAP usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Execution time reduction using parallel processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Putting it all together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
276 276 276 277 278 279 279 280 281 282
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Online resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How to get Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Help from IBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 289 289 290 290 290
viii
Notices
This information was developed for products and services offered in the U.S.A. IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service. IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing, IBM Corporation, North Castle Drive, Armonk, NY 10504-1785 U.S.A. The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you. This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice. Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk. IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you. Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental. COPYRIGHT LICENSE: This information contains sample application programs in source language, which illustrate programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs.
ix
Trademarks
IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. These and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol ( or ), indicating US registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. A current list of IBM trademarks is available on the Web at http://www.ibm.com/legal/copytrade.shtml The following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:
AIX CICS DB2 eServer i5/OS IBM Language Environment Lotus Notes Lotus MVS Net.Commerce NetView Notes OS/390 OS/400 Processor Resource/Systems Manager RACF Redbooks Redbooks (logo) REXX S/370 System Storage System z10 System z9 System z System/370 Tivoli WebSphere xSeries z/OS z10 z10 BC z10 EC z9 zSeries
The following terms are trademarks of other companies: Novell, the Novell logo, and the N logo are registered trademarks of Novell, Inc. in the United States and other countries. EJB, J2EE, Java, Javadoc, JDK, JNI, JRE, JVM, Sun, and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. ESP, Windows, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States and other countries. Linux is a trademark of Linus Torvalds in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others.
Preface
This IBM Redbooks publication describes and explains which z/OS security services can be exploited by Java stand-alone applications executing on z/OS. It is intended for experienced z/OS users with a moderate knowledge of Java, and experienced Java users with some knowledge of z/OS. For experimentation and customization, it provides use cases that were composed and tested on a z/OS platform at z/OS V1R10 and SDK 6 SR1. The book describes the Java security model as implemented in the z/OS JVM, and explains the role of the major infrastructure components such as Security Manager, Access Controller, Class Loader and Byte Code Verifier. It also addresses specific z/OS-provided facilities such as the JZOS toolkit and the Java record I/O (JRIO), and explains how they fit within both security models. A full chapter is dedicated to Java Authentication and Authorization Services (JAAS) with practical examples of its use in z/OS, including the LoginModules that interact with the SAF interface. A discussion of the relationship of these services to the z/OS built-in security functions such as APF, Program Control, and so on is also provided. The book then addresses the specific security-relevant services that are provided to Java applications executing on the z/OS platform, and gives practical examples of their setup and use. Java SAF classes, the JSec API, exploitation of RACF PassTickets, and the use of the z/OS Enterprise Identity Mapping (EIM) infrastructure are covered. Exploitation of z/OS integrated hardware cryptography by Java applications is detailed, along with numerous practical examples of the use of these services. z/OS cryptographic key management features are also discussed. Finally, the book discusses two industry-class IBM Java products that exploit z/OS hardware cryptography, IBM Encryption Key Manager and IBM Encryption Facility for z/OS OpenPGP Support. It focuses on the exploited functionalities and performance optimization. It is strongly recommended that readers also refer to the following Redbooks for additional information about executing Java stand-alone applications on z/OS: Java Stand-alone Applications on z/OS Volume 1, SG24-7177 Java Stand-alone Applications on z/OS Volume 2, SG24-7291
xi
Science degree in Computer Science from Clarkson University. Jonathans areas of expertise include Java, RACF Java security, tape encryption, host encryption facility, the WebSphere family of products, and the PKI and OpenPGP systems. Pierre Bda is an IT Specialist in the Banking Competence Center (BCC) in Switzerland. He has more than 14 years of experience in mainframe security. He joined IBM in 2007. Pierres areas of expertise include RACF, security administration, and z/OS and storage administration. Michael Buzzetti is an IT Specialist at the IBM Design Center in Poughkeepsie, New York. He specializes in virtualization and security. He is a vocal advocate of Open Source and Linux. Mike holds a Bachelor of Science degree in Computer Science from Clarkson University. Saheem Granados is an Advisory Software Engineer who has worked for IBM for 10 years. He is a Certified Information Systems Security Professional who has been a designer and developer for critical z/OS security software, including Net.Commerce for OS/390, Security Server LDAP Server, Tivoli Federate Identity Manager, Trusted Key Entry, and Encryption Facility V1.2. Saheem has spent a majority of his career focusing on Java-based security on z/OS. He recently rejoined the Tivoli Directory Server for z/OS team. Ebbe Mlgaard Pedersen is an IT Architect from Denmark. He has 14 years of experience within IBM, developing and architecting applications for z/Series, mainly for the banking industry. Ebbes areas of expertise include z/OS, DB2, AIX, C, C++, Java, application architecting and application developing. Kin Ng is a Software Developer in Poughkeepsie, NY. He has more than 25 years of experience with large systems software. He has worked on TSO/E development, and was part of the team that contributed to the original releases of APPC/MVS and z/WLM. Kin has contributed to many releases of z/WLM and was part of the EWLM development team. He has worked in the z/OS Java security area for the past year. Michael Onghena is an Advisory Software Engineer in zSeries Security at IBM. He is a developer for RACF and has been with IBM for 16 years. Eysha Powers is a Software Engineer in the United States. She has been with IBM for more than four years. Eysha holds a Bachelor of Science degree in Computer Science from the University of Illinois at Urbana-Champaign and a Master of Science degree in Information Technology from Rensselaer Polytechnic Institute. Her areas of expertise include RACF, EIM, and Java Cryptography. Martina Schmidt is a Technical Presales Specialist in Germany. She has two years of experience in mainframes and holds a Bachelor in Applied Computer Science degree from the University of Cooperative Education in Stuttgart. Martinas areas of expertise include Java, Java batch and WebSphere Application Server on z/OS, with a focus on performance and security. Richard Schultz has worked for IBM for 29 years. He has held positions dealing with mainframe hardware and software technical support, with a concentration in performance measurement and analysis. For the past six years, he has specialized in performance evaluation of z/OS middleware cryptographic products. Richard provides advanced technical support on this topic internally, and provides data on this topic that is published for customers worldwide.
xii
Thanks to the following people for their contributions to this project: Paola Bari, Robert Haimowitz, Richard M. Conway, David Bennin and Roy Costa International Technical Support Organization, Poughkeepsie Center, Poughkeepsie Center The z-Delivery team Banking Competence Center (BCC), Switzerland Anne Emerick IBM STG z/OS Security Server Development, Poughkeepsie Brian Beegle IBM STG z/OS Java Development, Endicott Daniel Dranchak IBM STG z/OS Java development, Endicott Jason Katonica IBM STG z/OS Software Developer - Java, Poughkeepsie Deborah Mian IBM STG z/OS Directory and Java Development People Manager, Poughkeepsie Maura Schoonmaker IBM STG z/OS Security People Manager, Poughkeepsie Ross D. Cooper IBM STG, z/OS Security Software Development, Poughkeepsie
Comments welcome
Your comments are important to us! We want our books to be as helpful as possible. Send us your comments about this book or other IBM Redbooks in one of the following ways: Use the online Contact us review Redbooks form found at: ibm.com/redbooks
Preface
xiii
Send your comments in an e-mail to: redbooks@us.ibm.com Mail your comments to: IBM Corporation, International Technical Support Organization Dept. HYTD Mail Station P099 2455 South Road Poughkeepsie, NY 12601-5400
xiv
Part 1
Part
Chapter 1.
application. Continuing the example, classes in this package would be com.ibm.encryptionfacility.Encode.java or com.ibm.encryptionfaciliy.Decode.java. Java packages are delivered and deployed as Java ARchive (JAR) files. JAR files can contain the source code of the Java application, compiled classes, and any number of other resources. JAR files are compressed using the zip file format. They also integrate additional meta-data that relates to the application. For instance, JAR files include, by default, a META-INF directory. This directory contains the manifest of the JAR. The manifest contains a set of name-value pairs that describe the package. If the JAR file contains a number of Java classes, the manifest can contain the Main-Class keyword. This tells the JVM which classs main method should be used if the JAR file were to be executed as if it were a stand-alone program. JAR files can also be a set of classes that make up a library. The manifest can state which other JAR files that the classes included depend on. For more information about JAR files, refer to the JAR File Overview page located at: http://java.sun.com/javase/6/docs/technotes/guides/jar/jarGuide.html
Callable Services (BPX....), which in turn are executed by the z/OS UNIX Kernel. These callable services allow z/OS UNIX programs to access system resources. Therefore, the JNI is basically located between the Java Virtual Machine (JVM) and the operating system (z/OS). However, instead of going directly from the JVM to the operating system (as the dotted line in Figure 1-1 indicates), a native C/C++ library is used to invoke access to the required resources.
Java Application
JNI
2
JVM
Regular Java program without JNI
3
BPX1_ callable service
Language Environment
HFS HFS
NFS NFS
SMF SMF
WLM WLM
BCP
Using JNI offers advantages over using a 100% pure Java program. For example, it allows users to consider the reuse of code from another language that is already available. In addition, the native code generally executes faster than Java code, so some performance gains could also be expected from the use of JNI. However, there are also disadvantages to using JNI that users need to consider: Using JNI is not recommended for a J2EE environment such as WebSphere Application Server, because any operational anomalies in the calling program adversely affect the operations of the J2EE server. The zAAP (z Application Assist Processor) engine can exclusively be used to run Java code. Therefore, to realize substantial benefit from the zAAP, it is recommended that the use of native code be somehow limited. Note: Details about Java program developments that use the JNI is a very broad topic, and complete coverage of that topic is beyond the scope of this book. A basic introduction to Java programming with JNI is available at IBM developerWorks: http://www-128.ibm.com/developerworks/edu/j-dw-javajni-i.html
C /C + + c o d e
Table 1-1 lists the native data types and describes their size and attributes. Use this table when mapping Java native types to C data types in JNI code.
Table 1-1 Mapping of primitive types Java type Boolean Byte Char Short Int Long Float Double Primitive type jboolean jbyte jchar jshort jint jlong jfloat jdouble Description unsigned 8 bits signed 8 bits unsigned 16 bits signed 16 bits signed 32 bits signed 64 bits 32 bits 64 bits
JNI reference types correspond to different types of Java objects. Sometimes reference types are also called object types (either term is acceptable). They are organized in a hierarchy, as shown in Figure 1-3. In the C programming language, all non-C objects map to the jobject reference type. Accordingly, a Java String object will be referenced in C as a jstring. A java.util.Hashtable object will be referenced as a jobject. Object references play an important role when accessing Java objects from native code with JNI functions, or when passing Java objects as parameters to a native implementation.
Chapter 1. Overview of Java on z/OS
jobject jclass jstring jthrowable jarray jobjectArray jbooleanArray jbyteArray jchartArray jshortArray jintArray jlongArray jfloatArray jdoubleArray
all Java objects java.lang.Class.objects java.lang.String.objects Java.lang.Throwable.objects arrays object arrays boolean arrays byte arrays chart arrays short arrays int arrays long arrays float arrays double arrays
Signature type
Another main data type available in JNI is the signature type. To execute a Java method from native code, the user has to specify the exact signature of the method. For example, consider the following the Java method: long myMethod (float f, String s, Hashtable[] harr); It has the following type signature: (FLjava/lang/String; [Ljava/util/Hashtable;)J This may be considered as a more advanced topic, because calling Java code from within a native program can rapidly become complex to implement. If unsure about the exact signature of a Java method, the user can perform these simple steps: 1. Create a dummy Java class that defines a native method that has the same arguments and return types. For example: class Helpme { native long myMethod (float f, String s, java.util.Hashtable[] } 2. Compile the Java class. 3. Run the javah command on the class: javah -jni Helpme 4. The resulting C header file Helpme.h contains a description of the native method, including its signature: /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class Helpme */ #ifndef _Included_Helpme #define _Included_Helpme #ifdef __cplusplus extern "C" { #endif 8
Java Security on z/OS - The Complete View
harr);
/* * Class: Helpme * Method: myMethod * Signature: (FLjava/lang/String;Ljava/util/Hashtable;)J */ JNIEXPORT jlong JNICALL Java_Helpme_myMethod (JNIEnv *, jobject, jfloat, jstring, jobjectArray); #ifdef __cplusplus } #endif #endif
10
Type of access required Fine access to system error codes Data set access (Text Stream, Binary Stream and Record Mode) Data set access (Record mode) Portable text file processing (HFS) Portable text file processing (data sets) VSAM data set access (KSDS, ESDS, RRDS) HFS access
API to use JZOS JZOS JRIO JZOS JZOS JZOS, JRIO (KSDS only)) JRIO, java.io
For more information about JZOS, refer to the Redbooks publication Java Stand-alone Applications on z/OS, Volume II, SG24-7291.
1.3.4 Job management using the BPXBATCH and BPXBATSL utility programs
Just as with any other program written for mainframe operating environments, Java batch jobs must be submitted and controlled using JCL statements. IBM provides a utility program called BPXBATCH to run shell scripts and executable files that reside in the z/OS Hierarchical File System, as per directives in a deck of JCL statements. BPXBATCH has the restriction of handling standard I/O streams only when used within a JCL script. That is, the standard I/O streams must be directed to temporary z/OS UNIX files and then copied to datasets in a subsequent job step. Another limitation of BPXBATCH is its inability to allow executing programs to access DD cards defined in the enclosing JCL statements.
11
Therefore, another utility program called BPXBATSL is provided to address the limitations of BPXBATCH. BPXBATSL provides an alternate entry point into BPXBATCH and forces a program to be initiated in the same address space, using a local spawn function instead of the traditional UNIX fork/exec. As a consequence of this, all DD cards specified in the JCL deck are made available to the invoked program. Table 1-3 provides a comparison of these two approaches.
Table 1-3 Comparison of BPXBATCH and BPXBATSL BPXBATCH Inherit user profile Return code Yes Returns the value returned from the running program. BPXBATSL No Returns the value returned from the running program multiplied by 256. This is useful in determining errors in BPXBATSL invocation versus program errors in the running program. Yes Yes Yes
DD cards supported Use z/OS data sets JVM runs in the same address space
For more information about BPXBATCH and BPXBATSL, refer to the Redbooks publication Java Stand-alone Applications on z/OS, Volume I, SG24-7177.
12
following step in a job, which allows for inclusion of Java program steps in a chain of z/OS utilities and programs. Another considerable benefit of JZOS is its full support for accessing the DD statements. Because Java programs launched via JZOS run in the same address space as any other steps, Java programs are able to access DD statements specified in a job. The JZOS batch launcher can direct stdout and stderr input streams to standard z/OS datasets and to the JES SYSOUT dataset. Also, Java programs are able to read from a stdin that is actually a standard z/OS dataset. Consequently, system operators are able to monitor the execution of Java programs via System Display and Search Facility (SDSF), just as they would monitor other job steps in z/OS. Table 1-4 summarizes the differences between BPXBATCH, BPXBATSL, and JZOS. Although JZOS offers many additional features that are desirable to integrate Java programs in batch jobs, it is not intended to replace BPXBATCH and BPXBATSL. For instance, a job that requires you to run shell scripts or programs residing in a z/OS UNIX file will continue to use BPXBATCH and BPXBATSL.
Table 1-4 Comparison between BPXBATCH, BPXBATSL and JZOS BPXBATCH Run in the same address space DD statements supported stdin, stdout and stderr to MVS data set Console communication Return code (System.exit) Running programs and shell scripts in USS No No No No Yes, but always 1 otherwise Yes BPXBATSL Yes Yes No Yes, via JNI calls RC multiplied by 256 Yes JZOS Yes Yes Yes Yes Yes No
For more information about JZOS, refer to the Redbooks publication Java Stand-alone Applications on z/OS, Volume II, SG24-7291.
13
Class Loader
The JVM that runs above the operating systems has its access to these resources controlled by the operating system access control mechanisms themselves (access control lists, files, or directories, permissions). The Java Runtime Execution Engine and the Java Platform Classes are two of the core components that make up the Java Runtime Environment (JRE) that runs above the operating system. The execution engine and platform classes make up the JVM. These components create the necessary abstraction layer to isolate the platform-dependent code from the higher level Java code. The JVM uses the Class Loader to obtain and load the proper classes to be executed. The class loader executes at a higher lever than the platform class. It does not have any perception of the files and file system infrastructure when loading the byte code into the execution engine. The class loader also allows for libraries to be dynamically loaded at run time.
14
other malicious acts. These are detected by the byte code verifier, which makes sure that object field and method accesses are always performed according to the rules. If an object field is set as private, then the byte code verifier enforces that all access follows the rules set forth by the language specifically for private members of an object. The byte code verifier also enforces type safety; that is, every object is always accessed by what it is. For instance, an object that is instantiated with a type of OutputStream is always accessed as an OutputStream and not as any other type. The verifier ensures that the code adheres to a number of base constructs: There are no stack overflows. There are no stack underflows. All accesses to both registers and stores are valid. All data conversions are legal. Byte code instructions parameters are legal. The verifier is independent of the compiler. It can certify code from the embedded compiler or any other compiler. When using the Just In Time (JIT) compiler, the byte code verifier is used exactly the same way. Verification and certification at such a low level can assure developers and end users of the validity and safety of the code to be executed. Also note that JAR signing, described in 1.4.4, JAR file security on page 16, brings an additional level of verification to the integrity of the byte code.
SecurityManager sm = System.getSecurityManager(); if (sm != null ){ sm.checkRead(file); } The proper permission would have been created by the default SecurityManager, as shown in Example 1-2.
15
AccessController.checkPermssion(new FilePermission(file, read)); Developers are encouraged to use the more recent AccessController, rather than SecurityManager. Customizing (that is, subclassing) of SecurityManager should only be undertaken with extreme caution. For the purposes of this book, it is assumed that no customization is done and that the default SecurityManager is used. As shown in Example 1-2 on page 16, the AccessController utilizes classes of type Permission. Permission is an abstract class that represents a system resource. Java provides a number of Permission classes, such as RuntimePermission, FilePermission, SocketPermission and AllPermission. These classes allow developers to implement the proper access checks prior to manipulating a system resource. They also prevent unauthorized code from running, because a SecurityException is raised in case of denied permission. Most implementation of the abstract Permission class include a list of actions that make up the scope of the controlled access. As an example, FilePermission includes read, write, delete, and execute actions. SocketPermission includes connect, accept, listen, and resolve. Developers are free to create their own Permission classes. Java 2 Security also introduces the concept of ProtectionDomain. A ProtectionDomain can be thought of as the encapsulation of a set of classes, or a CodeSource, of which instances are granted specific Permissions when the classes are being executed on behalf of a set of Principals. The Permissions granted in the ProtectionDomain override, at class execution time, the security policy that is being enforced by the JVM. ProtectionDomains allow the current Policy to dynamically map permissions to a CodeSource or a principal identity when it comes to check permission. For example, the default Policy system that is based on the AccessController function reads its policy definitions from a set of static files. These files are read and parsed when the JVM first starts. If the Policy implementation allows loading the policy from a dynamic data source (such as a database or an LDAP directory), the ProtectionDomain can then couple, at run time, the running CodeSource or principal identity to the permissions specified in the dynamically loaded policy. Note: Many integrated development environments offer the ability to generate code automatically. Users must exercise caution when exploiting this facility, because when using automatic generation there is always a potential exposure for the final code not to abide by all the specific rules relevant to the users specific execution environment. In other words, Java Security can protect from a large number of attacks, but it cannot protect from mistakes introduced by developers or their tools.
16
The Java platform uses public key cryptography (that is, an asymmetric algorithm with a private and public key pair) to digitally sign JAR files. This is done in a way similar to how the SSL/TLS protocol exploits public key cryptography. The private key signs the JAR file, and the public key is used to verify the JAR file. The public key and its digital certificate are included in the JAR file. The certificate is digitally signed by a trusted Certificate Authority (CA). The certificate indicates who owns the public key placed in the JAR. The overall process of signing includes two steps: 1. A developer signs the JAR file, using a private key. 2. The public key is placed in the JAR with the accompanying digital certificate. The Certificate Authority (CA) needs to be in a trusted Java keystore in the receiving system. This keystore should be as protected as the JVM libraries are, from the operating system perspective. The jarsigner tool and keystore tool can make use of the Java Cryptography Extension (JCE). This is discussed in detail in Part 3, z/OS Java cryptography on page 119. After the JAR is signed, a human readable signature file is generated. The signature file is located in the META-INF directory of the signed JAR file, which is the same location as the JAR files manifest. The signature file contains a set of hashes, or checksum values, of the contents of the JAR file. The hashes are used to verify that the Java classes have not changed since the JAR file was signed. Example 1-3 displays a sample signature file.
Example 1-3 Sample signature file
Signature-Version 1.0 SHA1-Digest-Manifest: h1y5k9TlZrtI+xvgaqMyRsE4V4== Created-By: 1.6.0 Name: com/ibm/redbooks/sg247610/jaa/RunSamples.class SHA1-Digest: ba4b72e4c67be054fa91b8eadb477= Name: com/ibm/redbooks/sg247610/jaa/SampleAuthentication.class SHA1-Digest: 8psH48cnz3nb57vb1mz0rn76fctde= The SHA1-Digest-Manifest line is the hash of the entire manifest and each file included in the JAR file has its own SHA-1 hash. When the JAR file is being verified by the receiving JVM, before the class loader and byte code verify are started, the signature file is hashed and the results is compared with the SHA1-Digest-Manifest. This prevents malicious attackers from providing fake hashes. Then, each file included in the JAR file is hashed again and the results compared. If any the hashes do not match, a security exception is throw and the class loader does not load the classes.
17
The underlying operating system security must be set up to allow proper privileges for the JVM. System file level access control is a crucial element for you to consider. The JVM libraries should be accessible in read-only mode for all users except for the system administrator who is in charge of installing and maintaining the JVM. This is intended to guarantee that JVM component integrity will not be exposed to compromise by other z/OS components or even by Java applications that would call external z/OS components. There are two main features of z/OS security that the JVM and application environments must abide by: Authorized Program Facility (APF) Program Control The requirements to use APF-authorized libraries or program-controlled libraries must be carefully determined. This can often be difficult to achieve because of a lack of information regarding the deployment of the application on z/OS. In any case, it requires a system security administrator to work jointly with the application developer to establish the proper setup of this part of the execution environment.
18
For programs residing in the z/OS UNIX file system, the APF-authorized extended attribute bit, also known as the a bit, should be set for the file that contains the program. The program has been link edited with Authorization Code=1 (AC=1) as a load module that resides in the APF-designated library if it is the first program in a chain of modules. Or it is not link-edited with AC=1, but still resides in an APF-authorized library and has been invoked in a chain of programs that was initiated by an AC=1 program. Proper protection has to be used to control access to the APF libraries and to the operator commands that modify the list of APF libraries or the a extended attribute. For more detailed information about the z/OS RACF External Security Manager and protection of the a extended attribute, refer to z/OS UNIX System Services Planning, GA22-7800. Note that If the user tries to run a program from an authorized library that is not link-edited with AC=1, it will not run APF-authorized. However, that same program could be fetched by another that is running APF-authorized and executed in the authorization state in which it is called, or even have its state changed. Important: The system automatically adds SYS1.LINKLIB and SYS1.SVCLIB to the APF list at IPL. In addition, any module in the link pack area (pageable LPA, modified LPA, fixed LPA, or dynamic LPA) will be treated by the system as though it came from an APF-authorized library. Users must ensure that they have properly protected SYS1.LPALIB and any other library that contributes modules to the link pack area to avoid system security and integrity exposures, just as they would protect any APF-authorized library.
MBUZZET @ WTSC60:/u/mbuzzet>extattr test.txt test.txt APF authorized = NO Program controlled = NO Shared address space = YES Shared library = NO
19
RALTER PROGRAM * ADDMEM(SYS1.SCEERUN2//NOPADCHK) UACC(READ) When the program resides in an HFS file, then the p extended attributes must be set for the file. Alike the a (APF) extended attributes, only users permitted to the BPX.FILEATTR.PROGCTL resource in the RACF FACILITY class can set the p extended attribute for a z/OS UNIX file. Likewise, any change to the file automatically resets the bit. Example 1-4 on page 19 and Example 1-5 on page 19 illustrate the use of the extattr command to display the extended attributes of two files. The program control extended attribute is shown along with the APF extended attribute. The indication of whether a program is controlled or not influences the behavior of z/OS when the BPX.DAEMON profile is defined in the FACILITY class of RACF profiles. When loading programs into the user address space, either from a z/OS data set or HFS file, z/OS checks whether the loaded program is marked as being program-controlled. If the program is not controlled, it therefore renders the address space dirty and a message is issued at the system console, as shown in Example 1-7.
20
ICH420I PROGRAM CELHV003 FROM LIBRARY SYS1.CMDLIB CAUSED THE ENVIRONMENT TO BECOME UNCONTROLLED. The execution of the program modules in the now-dirty address space continues until a program residing in the address space calls one of the following functions: setuid() seteuid() setruid() pthread_security_np auth_check_resource_np _login() _spawn() _passwd() Because the system requires that the address space be clean to execute any of those functions, the function is not executed in this case and an error code is returned. The message shown in Example 1-7 on page 21 can then be quite useful in pinpointing the reason why the address space became dirty.
21
YES
22
Note: Another zAAP option in the parmlib member IEAOPTxx named IFACROSSOVER is ignored since z/OS 1.8 or since z/OS 1.6 with zIIP support. It should be removed from IEAOPTxx. For additional information about the zAAP specialty engine, refer to: http://www-03.ibm.com/systems/z/zaap/
23
Note: There is a CPACF in the specialty engines as well. Workloads eligible for the IFL, zAAP, or zIIP will consume CPACF cycles in the specialty engine if they invoke the MSA functions.
Crypto Express2 Coprocessor (CEX2C) The CEX2C is a so-called secure coprocessor. This means the coprocessor deals with
secure keys. Those secure keys are always encrypted when they are residing outside the CEX2C physical boundaries so that no one can see the actual value of an application key in system storage or a disk device. The CEX2C coprocessor has been certified at the FIPS 140-2 standard for cryptographic modules with the highest possible level (level 4). The coprocessor provides the following functions, among others: Secure key functions: Symmetric DES, T-DES encryption/decryption Message authentication, hashing PIN processing RSA asymmetric encryption/decryption and digital signature generation/verification Key generation and management, true random number generation Clear key RSA functions for SSL/TLS acceleration The very sophisticated internal architecture, where the cryptographic workload is dispatched and managed into the cryptographic engines by an internal operating system and firmware, also allows as an option to compile into the coprocessor firmware the customers own cryptographic algorithms. A CEX2C in System z9 or z10 can be manually switched into accelerator mode (CEX2A). Likewise, it can be switched back to coprocessor mode. Any combination of CEX2Cs and CEX2As is possible in a CEX2 feature.
24
Chapter 2.
25
When working with the Java platform's security framework, users should be aware of the concepts, classes, and interfaces that are used throughout the platform. Figure 2-1 illustrates the framework components and their interactions.
26
LoginModule
Principal Credential
CallbackHandler
LoginContext
JAAS Application
Figure 2-1 JAAS component overview
The javax.security.auth.Subject class represents an identity or a collection of information that comprises at least one identity (note that a single Subject may relate to multiple identities). The binding of these two entities is done through the javax.security.auth.Subject class, using the Principal objects as parameters. A Principal represents an entity which could be a person, company, or machine. In addition to Principals, Subjects can store security-related objects that are referred to as credentials. There are two sets of credentials, those that are private to the Subject and those that can be made public. For instance, a Subject might own a secret cryptographic key in its private set of credentials and a public key or Kerberos token in its public credentials. All of the information stored in a Subject can be used to make access decisions based on who or what the requesting identity is. Subjects, Principals, and credentials are all abstract notions, which makes the security framework very flexible. A Subject can contain information about a user (such as an LDAP distinguished name) as well as the credentials that have been obtained during the log on procedure. The security framework allows you to make a decision based on all of these, on a combination of these, or on a single piece of this information.
Auditing
Note, however, that auditing is not currently addressed in the core feature set of the Java authentication and authorization framework. It is the responsibility of application developers to develop their own auditing scheme.
27
IBM has made the following changes: All classes in the package com.sun.* have been reimplemented and moved to the respective com.ibm.* packages. IBM ships a specific JAAS LoginModule, OS390LoginModule, which supports basic login using the z/OS System Authorization Facility (SAF) that is using RACF or an equivalent product. IBM ships the SAFPermission classes for checking access to SAF resources. For more information about this topic, refer to the SAFPermission class in Chapter 4, System Authorization Facility interfaces in z/OS Java on page 55. The IBM specific ThreadSubject.doAs has been included as the default implementation of ThreadSubject. For more information about the IBM version of JAAS, refer to the following site: http://www-03.ibm.com/servers/eserver/zseries/software/java/jaas.html Note: To use the JAAS code that ships with the IBM Java platform on z/OS, you must enable it by adding auth.policy.provider=com.ibm.security.auth.PolicyFile to the java.security file. This file is normally located in $JAVA_HOME/lib/security/java.security.
2.2 Authentication
JAAS authentication is a plugin-based framework. This allows a clear separation between authentication technologies and applications. Thus, application programmers do not have to be concerned with what type of authentication mechanism is being used. Instead, they can develop applications that make sure the Java security framework is properly called. Note that the pluggable JAAS LoginModules can be chained together. This is similar to the Pluggable Authentication Module (PAM) approach developed for other platforms. It provides applications with a set of possible authentication checks. To use JAAS, application developers first instantiate a javax.security.auth.login.LoginContext object.The LoginContext works with the LoginModules and a configuration file to authenticate a user. The configuration file specifies which LoginModules to use for this application, as well as the order in which these LoginModules should be called. The LoginContext can also use javax.security.auth.callback.CallbackHandler to communicate to the entity that is requesting authentication. The CallbackHandler can ask the entity for the information required to complete the process. There are many possible uses of the CallbackHandler, such as asking the user for a user name and password, a personal identification number (PIN), or other kinds of authentication data. In addition, the application can provide the status of the authentication process through the CallbackHandler. CallbackHandlers can be chained together in a way similar to LoginModules. If the authentication process requires a user name, password, and authentication token (such as a Kerberos ticket, for example), the LoginModules can support the proper CallbackHandler for each type of information.
28
TestApplication { com.ibm.security.auth.module.OS390LoginModule required debug=true; }; TestApplication is the name of the Java application that will make use of this LoginModule configuration. The Java class used for authentication is com.ibm.security.auth.module.OS390LoginModule. The required attribute (flag) tells the JAAS runtime that for the login process to succeed, this LoginModule must authenticate successfully. The JAAS framework implements four different types of flags for LoginModules, as described in Table 2-1.
Table 2-1 LoginModule flag Flag required Description The login module is required to succeed. - If login fails or succeeds, authentication still continues to proceed down the LoginModule list. The login module is required to succeed. - If login succeeds, authentication still continues to proceed down the LoginModule list. - If it fails, control is immediately returned to the application. Authentication does not continue down the LoginModule list. The login module is not required to succeed. - If it does succeed, control is immediately returned to the application and authentication does not proceed down the LoginModule list. - If it fails, authentication proceeds down the LoginModule list. The login module is not required to succeed. - Whether or not this module succeeds, authentication proceeds down the LoginModule list.
requisite
sufficient
optional
Order matters when traversing the LoginModule list. The overall authentication succeeds if all of the required and requisite LoginModules succeed. If the configuration defines a sufficient LoginModule, and it succeeds, then only the required and requisite LoginModules encountered before the sufficient module need to succeed because authentication ends as soon as the sufficient module succeeds). If the configuration lacks a required or requisite LoginModule, then there must be at least one optional or sufficient module defined. LoginConfigurations can also define a set of options to be passed into the LoginModule. The LoginModule defines what options are available. These options are then placed in the configuration file as a key-value pair. The key and value should be separated by an equal (=)
Chapter 2. Java 2 authentication and authorization services
29
sign, and the value should be surrounded in double () quotation marks. The configuration can also have JVM level variables expanded. For instance, if the configuration contains somekey=${java.home}, the configuration will expand that to whatever the java.home JVM variable is set to when starting Java. Example 2-1 illustrates the option debug=true being passed into the com.ibm.security.auth.module.OS390LoginModule.
package com.ibm.redbooks.sg24160.jaas; import import import import import import import import import import import import import import java.io.BufferedReader; java.io.IOException; java.io.InputStreamReader; java.security.Principal; java.util.Set; javax.security.auth.Subject; javax.security.auth.callback.Callback; javax.security.auth.callback.CallbackHandler; javax.security.auth.callback.NameCallback; javax.security.auth.callback.PasswordCallback; javax.security.auth.callback.TextOutputCallback; javax.security.auth.callback.UnsupportedCallbackException; javax.security.auth.login.LoginContext; javax.security.auth.login.LoginException;
import com.ibm.security.util.Password; public class SampleAuthentication { public static void main(String[] args) { authenticate(); } public static Subject authenticate() { Subject subject = null; try { LoginContext lc = new LoginContext("RunSamples", new MyCallbackHandler()); lc.login(); subject = lc.getSubject(); Set principals = subject.getPrincipals(Principal.class); System.out.println("Login a success. Subject contains : " + principals.toString()); } catch (LoginException ex) { System.err.println("LoginException: " + ex.getMessage()); ex.printStackTrace(); }
30
return subject; } } /** * The application must implement the CallbackHandler. * * <p> * This application is text-based. Therefore it displays information to the user * using the OutputStreams System.out and System.err, and gathers input from the * user using the InputStream, System.in. */ class MyCallbackHandler implements CallbackHandler { /** * Invoke an array of Callbacks. * * <p> * * @param callbacks * an array of <code>Callback</code> objects which contain the * information requested by an underlying security service to be * retrieved or displayed. * * @exception java.io.IOException * if an input or output error occurs. * <p> * * @exception UnsupportedCallbackException * if the implementation of this method does not support one * or more of the Callbacks specified in the * <code>callbacks</code> parameter. */ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof TextOutputCallback) { // display the message according to the specified type TextOutputCallback toc = (TextOutputCallback) callbacks[i]; switch (toc.getMessageType()) { case TextOutputCallback.INFORMATION: System.out.println(toc.getMessage()); break; case TextOutputCallback.ERROR: System.out.println("ERROR: " + toc.getMessage()); break; case TextOutputCallback.WARNING: System.out.println("WARNING: " + toc.getMessage()); break; default:
31
throw new IOException("Unsupported message type: " + toc.getMessageType()); } } else if (callbacks[i] instanceof NameCallback) { // prompt the user for a username NameCallback nc = (NameCallback) callbacks[i]; // ignore the provided defaultName System.err.print(nc.getPrompt()); System.err.flush(); nc.setName((new BufferedReader(new InputStreamReader(System.in))).readLine()); } else if (callbacks[i] instanceof PasswordCallback) { // prompt the user for sensitive information PasswordCallback pc = (PasswordCallback) callbacks[i]; System.err.print(pc.getPrompt()); System.err.flush(); try { pc.setPassword(Password.readPassword(System.in)); } catch (Exception e){ System.err.println("Error obtaining password "); e.printStackTrace(); } } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } }
This module defines two classes, SampleAuthentication and MyCallbackHandler. SampleAuthentication has an authenticate method and a main method to enable running this class from the command line. MyCallbackHandler has one method: handle. This class is used to communicate with the user, using a test-based prompt for the user name and password. The authenticate method defines a new LoginContext passing in the name RunSamples, and a new instance of the MyCallbackHandler object. The newly created LoginContexts login method is run. At this point, the Java 2 security system runs through the list of LoginModules that were defined in the configuration. Notice how the code does not have any mention of the actual class to use to do the login. To tie this sample application to the sample configuration. a few options need to be specified when starting Java. java -Djava.security.auth.login.config=jaas.config SampleAuthentication The parameter -Djava.security.auth.login.config tells JAAS where it can find the configuration file that defines which LoginModules to use. After compiling SampleAuthentication, it can be run as shown in Example 2-3. 32
Java Security on z/OS - The Complete View
WTSC60:/u/mbuzzet/sg247610>/usr/lpp/java/J6.0/bin/java -Djava.security.auth.login.config=sample_jaas.config -jar sg24_7610_samples_jaas.jar ----------------------------------OS/390 user id:mbuzzet OS/390 password: [OS390LoginModule] authentication with RACF succeeded userID = mbuzzet [OS390LoginModule] added OS390Principal and OS390PasswordCredential to Subject Login a success. Subject contains : [OS390UserPrincipal: userName: mbuzzet] ----------------------------------Example 2-3 shows a successful run of the SampleAuthentication. User mbuzzet entered a valid password and successfully authenticated with RACF. The LoginModule then created a OS390UserPrincipal, which represents a RACF user, and attached it to the Subject. Also, the LoginModule attached a OS390PasswordCredential to the Subject. The Subject is now fully formed and can be used throughout the Java code. The SampleAuthorization code merely displays that the login was successful and shows what the current Subject contains after authentication. Example 2-4 shows an unsuccessful attempt to authenticate. Notice that there are a number of error values displayed. This is because the debug option was passed into the LoginModule from the configuration file detailed in Example 2-1. The stack trace also shows where and why the login attempt failed. In this case, the authentication attempt was cancelled due to an incorrect user password. Because stack traces should be read backwards, we can see that line 21 of the SampleAuthentication class created a LoginContext. From there, the system called down the OS390LoginModules login method. This is where the error occurred. Note: Many authentication systems do not differentiate between an incorrect password and an incorrect username. If they did, user names could be determined and a brute force attack could be used to gain unauthorized access. The OS390Login module returns an invalid password whenever the supplied credentials do not match the credential store.
Example 2-4 Unsuccessful attempt to login
WTSC60:/u/mbuzzet/sg247610>/usr/lpp/java/J6.0/bin/java -Djava.security.auth.login.config=sample_jaas.config -jar sg24_7610_samples_jaas.jar OS/390 user id:nobody OS/390 password: [OS390LoginModule] authentication with RACF failed. Contents of PlatformReturned object: success = false errno = 143 errno2 = 151782877 errnoMsg = EDC5143I No such process. [OS390LoginModule]: aborted authentication attempt LoginException: Incorrect user password javax.security.auth.login.FailedLoginException: Incorrect user password
Chapter 2. Java 2 authentication and authorization services
33
at com.ibm.security.auth.module.OS390LoginModule.login(OS390LoginModule. java:238) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:59) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:39) at java.lang.reflect.Method.invoke(Method.java:612) at javax.security.auth.login.LoginContext.invoke(LoginContext.java:795) at javax.security.auth.login.LoginContext.access$000(LoginContext.java:2 09) at javax.security.auth.login.LoginContext$4.run(LoginContext.java:709) at java.security.AccessController.doPrivileged(AccessController.java:251 ) at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:7 06) at javax.security.auth.login.LoginContext.login(LoginContext.java:603) at com.ibm.redbooks.sg24160.jaas.SampleAuthentication.authenticate(Sampl eAuthentication.java:30) at com.ibm.redbooks.sg24160.jaas.SampleAuthentication.main(SampleAuthent ication.java:23)
2.3 Authorization
JAAS authorization combines the Java platform version 1.3 code source-based access controls with identity-based access control. After an identity is authenticated by JAAS as described in 2.2, Authentication on page 28, the Security Manager can make access control decisions. This constitutes the core of Java 2 Security. Note: Java 2 Security can be turned on or off by setting a JVM property. The -Djava.security.manager option, when present, enables Java 2 Security. Access decisions are determined by an AccessControlContext. The AccessControlContext is a Java class that represents an encapsulation of system resources. The AccessControlContext is a snapshot retrieved from the AccessController (see 1.4.3, SecurityManager and AccessController on page 15 for an explanation of the AccessController). The AccessController class makes access decisions based on the current execution thread or environment that it encapsulates. AccessControlContext allows you to make access control decisions from within a different context. This may seem confusing at first, so imagine a scenario where you have a set of worker threads in the Java Virtual Machine. Each thread might need to verify that the caller has authorization to do some work. To do this, each thread can ask the AccessController for an AccessControlContext. This is done by calling the static method getContext defined in the AccessController class. This reference to a context can then be used to perform any type of permission checking. Prior to JAAS, AccessControlContext attached the location of the code source and the verification of the digital signature of JAR files. The original implementation therefore defined security based on where the code was coming from. JAAS adds the Subject, complete with Credentials and a set of Principals to the AccessControlContext. As a result,
34
SecurityManager and AccessController can make decisions based not only on where the code came from, but also on who is executing the code. It is important to note that the Java platform access control list exploitation is based on the idea of least privileged. A Java applications thread of execution can include any number of different modules, packages and classes, all with different security characteristics. The intersection of these characteristics is given to the thread of execution. For example, if a program that was in an unsigned package calls a method from a package that was signed, the authority level is reduced to the least common denominator. The executing code will have the authority of an unsigned package. When the Java Virtual Machine starts with a SecurityManager running, it has the authority of the identity that started the initial process. To allow JAAS authenticated users to have access to resources that are different from the initial identity, the Java platform provides the ability to change the Subject that is associated with the AccessControlContext. This is known as the doAs family of methods. These methods allow the calling code to associate a different Subject to an AccessControlContext when performing a privileged action. The Subject object has the following static methods: doAs(Subject, PrivilegedAction) doAs(Subject, PrivilegedActionException) doAsPrivileged(Subject, PrivilegedAction, AccessControlContext) doAsPrivileged(Subject, PrivilegedActionException, AccessControlContext) The doAs methods use the current AccessControlContext and attach the Subject that is passed in. The doAsPrivileged allows the running code to provide a specific AccessControlContext. A PrivilegedAction is a Java interface that defines a single method, the run method. If the doAs of doAsPrivileged get passed a PrivilegedAction that may throw a check exception, then the PrivilegedActionException form should be used. This allows the exceptions to be propagated properly to the calling code. Example 2-5 shows a very simple implementation of a PrivilegedAction. This class implements the run method. Basically, when this code is executed, it will check SAF to see if the AccessControlContext it is running under has UPDATE authority to the resource BPX.SERVER in the RACF FACILITY class. If the authority is granted, it will display the message PASSED SAFPermission FACILITY BPX.SERVER, Update. Otherwise, it will display FAILED SAFPermission FACILITY, BPX.SERVER, Update and the exception that caused the failure.
Example 2-5 Sample SAF Permission
package com.ibm.redbooks.sg247610.jaas; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; import com.ibm.security.auth.SAFPermission; public class SampleSAF implements PrivilegedAction<Object> { public Object run() { // Get the current AccessControlContext AccessControlContext accessControlContext = AccessController.getContext();
35
// Create the SAFPermission and do checkPermission. try { accessControlContext.checkPermission(new SAFPermission("FACILITY", "BPX.SERVER", SAFPermission.__UPDATE_RESOURCE)); System.out.println("PASSED SAFPermission FACILITY BPX.SERVER, Update "); } catch (Exception e) { System.out.println("FAILED SAFPermission FACILITY, BPX.SERVER, Update " + e); } return (Object) null; } } Example 2-6 combines the features of Example 2-4 and Example 2-5 to form a complete JAAS application. When started, the application will prompt for a user name and password. After a successful login, the application will check to see whether the new identity created as a result of the authentication has the UPDATE authority to BPX.SERVER.
Example 2-6 SampleAuthorization
package com.ibm.redbooks.sg247610.jaas; import java.security.PrivilegedAction; import javax.security.auth.Subject; public class SampleAuthorization { Subject sampleSubject = null;
public SampleAuthorization (){ this.sampleSubject = SampleAuthentication.authenticate(); } public void runSAF() { try { PrivilegedAction<Object> action = new SampleSAF(); Subject.doAsPrivileged(this.sampleSubject, action, null); } catch (Exception e) { e.printStackTrace(); } } public void runSimpleFile() { try { PrivilegedAction<Object> doIt = new SampleFile(); Subject.doAsPrivileged(this.sampleSubject, doIt, null); } catch (Exception e) { e.printStackTrace(); } 36
Java Security on z/OS - The Complete View
} public void runSimpleProperty() { try { PrivilegedAction<Object> doIt = new SampleProperty(); Subject.doAsPrivileged(this.sampleSubject, doIt, null); } catch (Exception e) { e.printStackTrace(); } } }
To run the code in Example 2-6, the JVM needs to start with a few extra arguments. Because the application is using JAAS, we need a JAAS configuration file. We can reuse the one in Example 2-1. In addition to the JAAS configuration file, we need a policy file.
Policy file
A policy file is a flat text (ASCII) file. Policy files are used by the default SecurityManager to grant access to Java Permissions. When running with a security manager, if access to a resource is required but it is not defined by a policy file, then access is denied. Access to policy files must be restricted in order to guarantee their integrity. Similar to files and libraries that make up the JVM, policy files should be kept read-only to almost all users, even the initial identity that started the JVM. We recommend creating a specific group of users that have write access to these files. This will prevent other users from changing the authorizations defined by the system programmer, the application developer, or the security administrator who created the policy files. It will also prevent unauthorized Java code from corrupting or changing what is defined in the policy file. Example 2-7 contains the statements we need in the policy file for the sample application.
Example 2-7 Java policy file
grant { /* permissions for JAAS */ permission javax.security.auth.AuthPermission "createLoginContext.RunSamples"; /* permissions for SampleCallbackHandler */ permission java.lang.RuntimePermission "writeFileDescriptor"; permission java.lang.RuntimePermission "readFileDescriptor"; /* permissions for SampleAuthentication */ permission javax.security.auth.AuthPermission "doAs"; permission javax.security.auth.AuthPermission "getSubject"; permission javax.security.auth.AuthPermission "doAsPrivileged"; }; /* permsissions for SampleSAF */ grant codeBase"file:/-" { permission com.ibm.security.auth.SAFPermission "*", "*";
37
}; /* permissions for SampleFile */ grant Principal com.ibm.security.auth.OS390UserPrincipal "mbuzzet" { permission java.io.FilePermission "foo.txt", "read"; permission java.util.PropertyPermission "java.class.path", "read"; }; The syntax of a Java policy file is similar to the syntax of a JAAS configuration file. Permissions are granted by the use of a grant statement. Inside the brackets are a set of permission statements ended by a semicolon (;). The general structure of a policy file is depicted in Example 2-8.
Example 2-8 Policy file syntax
grant [SignedBy signer_name] [,CodeBase URL] [, Principal [principal_class_name] principal_name] [, Principal [principal_class_name] principal_name]... { permission permission_class_name [ target_name] [, action] [SignedBy signer_names]; } Example 2-7 shows that we are granting access to createLoginContext. Because the first grant statement is not followed by a modifier (such as a code path or a Principal name), it applies to every identity. This particular permission is used to allow the JAAS LoginModule to create a LoginContext. The RunSamples name tells the SecurityManager that this applies to context name RunSamples. In Example 2-2, we created a named LoginContext with the same name. If we wanted to authorize every application to be able to create the LoginContext, we could replace the RunSamples name with an asterisk (*). The read and write FileDescriptor permission are used by the callback handler included in the authentication section. The doAs and doAsPrivileged permissions grant the caller the ability to call the doAs family of methods. The second grant statement has a codeBase modifier. This is the older-style authorization, based on file locations. This particular statement gives access to all files. Access is given to all of the SAFPermission options. The final grant statement shows how to authorize a specific principal to a set of resources. As shown, we are assigning the ability to read the file foo.txt and read the JVM system property java.class.path to user mbuzzet of the class com.ibm.security.auth.OS390UserPrincipal. Instead of granting access based on a Principal or a codeBase, policy files also support a signedBy modifier. This modifier indicates the alias for a certificate that is stored in a key store. The digital signature of the code is verified against the public key of the alias after it is retrieved from the keystore. The values of signedBy can be a single alias or a comma-separated list of aliases. Policy files also support property expansion. When a string like ${random.property} appears in a policy file, it will be expanded to the current value of the property. For instance, granting the read operation to a file in a users home directory would look something like the following: permission java.io.FilePermission ${user.home}, read;
38
If the users name is Bill, and Bills home directory is /home/bill, then the system will see the permission as: permission java.io.FilePermission /home/bill. read; Property expansion can reduce the overall complexity of a given policy file. It also can make applications more platform-independent. The property expansion mechanism automatically inserts the proper file system separators. In the preceding example, if Bills home directory was located at C:\users\Bill, then the expanded line would have the proper file system separators. Note: Property expansion does not work with nested properties. A property like ${random.${user.home}} will not be expanded and the entire permission line will be ignored. In addition, if the property is not defined, the line is ignored.
This option tells Java to use a SecurityManager, thus turning on authorization. This option is also used to tell the JVM which SecurityManager to use. If left blank, the default is assumed. This is the Java 2 policy file to use. It includes all of the grant statements.
-Djava.security.policy=. /java2_1.policy
MBUZZET @ WTSC60:/u/mbuzzet/sg247610>/usr/lpp/java/J6.0/bin/java -Djava.securit y.auth.login.config=sample_jaas.config -Djava.security.manager -Djava.security.policy=sample_java2.policy -jar sg24_7610_samples_jaas.jar ----------------------------------OS/390 user id:mbuzzet OS/390 password: [OS390LoginModule] authentication with RACF succeeded userID = mbuzzet [OS390LoginModule] added OS390Principal and OS390PasswordCredential to Subject Login a success. Subject contains : [OS390UserPrincipal: userName: mbuzzet] ----------------------------------Checking SAF authorization PASSED SAFPermission FACILITY BPX.SERVER, Update ----------------------------------Checking File authorization PASSED FilePermission foo.txt read foo.txt does not exist ----------------------------------Chapter 2. Java 2 authentication and authorization services
39
Checking Property authorization PASSED PropertyPermission java.class.path read java.class.path = sg24_7610_samples_jaas.jar The policy file gives authorization to check the SAFPermission. The user mbuzzet must also have the proper SAF permission. Example 2-10 shows a session where the same policy file is in use, but a different set of credential are given to JAAS (and thus SAF). The user ramaa does not have the proper authority-defined SAF, but does have the proper authority defined in the Java policy file.
Example 2-10 Unsuccessful use of SAFPermission
MBUZZET @ WTSC60:/u/mbuzzet/sg247610>/usr/lpp/java/J6.0/bin/java -Djava.security.auth.login.config=sample_jaas.config -Djava.security.manager -Djava.security.policy=sample_java2.policy -jar sg24_7610_samples_jaas.jar ----------------------------------OS/390 user id:ramaa OS/390 password: [OS390LoginModule] authentication with RACF succeeded userID = ramaa [OS390LoginModule] added OS390Principal and OS390PasswordCredential to Subject Login a success. Subject contains : [OS390UserPrincipal: userName: ramaa] ----------------------------------Checking SAF authorization FAILED SAFPermission FACILITY, BPX.SERVER, Update
java.security.AccessControlException: Access denied (FACILITY BPX.SERVER 2) ----------------------------------Checking File authorization FAILED FilePermission foo.txt read ----------------------------------Checking Property authorization FAILED PropertyPermission java.class.path read
Example 2-10 shows how different security models and their implementations can operate together. It also shows that in order to protect an application, the entire stack must be taken into consideration. z/OS provides the Java platform with many proven security technologies. Java can utilize these technologies and give developers a highly secure platform to deploy mission-critical applications.
Policy Tool
Policy files can be very complex, but they provide great flexibility. For more information about this topic, you can refer to the Default Policy Implementation and Policy File Syntax document located at: http://java.sun.com/javase/6/docs/technotes/guides/security/PolicyFiles.html However, writing policy files by hand is cumbersome and can be error-prone. The Policy Tool, which ships with the Java Developer Kit (JDK), provides a graphical interface on a
40
workstation. The tool is written in Java and shields developers from having to know the strict syntax of policy files. Figure 2-2 shows the Policy Tool main window. It displays the name of the policy file, and all of the policy entries it includes.
Adding a policy entry is a simple operation, as shown in Figure 2-3. The Policy Tools entry dialog box allows developers to select the codeBase, signedBy, or a set of principals to associate permissions to.
41
In this example, we add the permission to read the java.class.path property. Figure 2-4 shows the dialog box used to add a principal.
party-supplied packages. Each of these packages could require an extraordinary amount of permission checks. Many Java 2 Enterprise Edition (J2EE) Web and Enterprise Java Bean (EJB) containers ship with Java 2 security turned off. With WebSphere Application Server, for instance, the documentation generally advises using against Java 2 security if performance is an issue. Instead, it suggests using thorough code reviews and setting proper access controls in the underlying operating system.
43
44
Part 2
Part
45
46
Chapter 3.
47
48
The profiles in the RACF database are defined and maintained by RACF administrators or users declared as owner of the resources. Note: RACF also supports controlling access for certain kinds of resources that are not registered with profiles in the RACF database. z/OS UNIX resources are examples of such types of resources. However, RACF still creates the data structures where the access control information is kept (for example, for the z/OS UNIX file File Security Packet (FSP), which RACF creates in the file system). But it the resource manager s responsibility to provide RACF with the information needed to allow it to make an access control decision and generate the relevant auditing data.
z/OS
1
User
User Identification And Authentication or identity mapping userID group Code requests to access a resource
Administrator
2
request To access Resource
S A F
RACF
5
Resource
Auditing
Auditor
The following interactions occur in the infrastructure shown in Figure 3-1: 1. An application, or a z/OS component, requests the user to supply identification and authentication data. z/OS provides support for several forms of identification and authentication including a user identity and a password, or a digital certificate or a Kerberos ticket. If the user provides a user ID and a password to the requesting application, the application calls RACF to evaluate the validity of the user ID and the password. If the user authenticates with a digital certificate or a Kerberos ticket, the application must proceed with validating the certificate or ticket. After validation, the application calls RACF to obtain a RACF user ID that maps to the certificate or the Kerberos ticket. RACF responds to the request with Return and Reason codes, and with a RACF user ID in the case of a successful mapping request. These codes indicate whether or not the operation was successful in RACF. 2. The application now runs under a RACF user ID that is used to access a resource in the system, along with the list of user groups that this specific user ID belongs to.
Chapter 3. Introduction to z/OS Resource Access Control Facility
49
3. In z/OS, access to resources is mediated by specialized z/OS components called resource managers. It is the role of the resource manager to call RACF to verify whether the user can be granted access to the resource. 4. The resource manager also grants or denies access to the application for the resource, according to the response from RACF. 5. Authentication accesses to resources and other security events can be recorded in an audit trail comprised of z/OS SMF records. Note that specific RACF users can be given the AUDITOR attribute and can define auditing criteria. RACF can enforce a separation of duties with respect to security administration and auditing by allowing the administrator to change access control rules and user definitions, but not to change certain auditing controls. Conversely, the auditor can change auditing controls but cannot make administrative changes to RACF profiles. In other words, administrators cannot prevent auditors from auditing them, and auditors cannot authorize themselves to resources.
50
profile extension
user ID
password
owner
attributes
groups
security classification
TSO segment
User attributes: SPECIAL AUDITOR OPERATIONS AUTHORITY CLAUTH REVOKE WHEN RESTRICTED PROTECTED UAUDIT
The name of the profile is the user ID itself. The password entry is kept one-way encrypted in the USER profile. The owner of a profile can change the profile. The user attributes define the responsibilities, authorities, or restrictions that a specific user has while defined to the system. Every user belongs, at a minimum, to one default group. The security classification determines the user's ability to access resources classified at security levels. Segments are optional extensions to the RACF profile and are used to save information for the resource managers like TSO or CICS. As previously mentioned, with RACF, all defined users belong to at least one group, known as a default group. A group is a collection of RACF users who share common access requirements to protected resources or who have similar attributes within the system. Groups are intended for administrative convenience. Note that RACF groups form a hierarchical or tree administrative structure, where each group is owned by a superior group. Groups can also own resources, as well as users and other groups. Figure 3-3 shows a GROUP profile in RACF.
RACF base profile
group ID
owner
TERMUACC
superior group
subgroups
51
A RACF user can be a member of more than one group. In RACF terminology, the users are connected to that group. A group owner, usually the user who defined the group to RACF, can define and control the other users connected to the group. The group owner can also delegate various group administrative responsibilities and authorities to other users connected to the group. The connect information in a user profile describes what the user can do when connected to that group, by including group authorities and group-related user attributes, as well as other information. Resources, that is datasets or general resources, are protected using resource profiles. Figure 3-4 shows such a resource profile.
RACF base profile
resource name
owner
UACC
access list
security classification
auditing
The name of the profile equals the name of the resource, and generic names are allowed. Using generic names, one profile can protect multiple resources. The owner of a profile can modify it. The universal access authority (UACC) describes in which way everyone is allowed to access the resource. It is usually recommended to set the UACC to NONE. The access list describes which user or group can access the resource beyond the access level set in UACC.
52
CONNECT REMOVE ADDUSER ALTUSER DELUSER LISTUSER SEARCH PASSWORD RACLINK user ADDGROUP ALTGROUP DELGROUP LISTGROUP SEARCH
RACF database
group
dataset
general resource
The highlighted boxes show the RACF commands for users and group administration. The commands ADDUSER, ALTUSER, DELUSER, LISTUSER, SEARCH, PASSWORD and RACLINK are used to administer users in RACF, along with ADDGROUP. The commands ALTGROUP, DELGROUP, LISTGROUP, and SEARCH are used to administer groups. The commands CONNECT and REMOVE are used to create or delete connections between users and groups. A user with the SPECIAL or group-SPECIAL attribute can issue all of the commands. A user with the AUDITOR or group-AUDITOR attribute can use only commands to search and list profiles, and to record RACF activities and events.
53
RACF supports the Password Enveloping function that allows an authorized LDAP client to securely extract a RACF user password out of the RACF database using the LDAP protocol. In z/OS V1R10, the function is expanded to provide Password Phrase enveloping.
z/OS
TCP/IP stack
LDAP client
LDAP Server
SDBM
RACF Schema
SSL/TLS
z/OS UNIX config
54
Chapter 4.
55
56
You can find a complete Java class containing all examples shown below in Appendix B, SAF sample code on page 221.
4.3.1 PlatformAccessLevel
With z/OS Security Server (RACF), permissions to resources are granted using the READ, UPDATE, CONTROL or ALTER access levels. PlatformAccessLevel is an interface used as a placeholder for these named constants. The constants are used by the accessLevel parameter of methods in the PlatformAccessControl class.
4.3.2 PlatformReturned
This class is a helper used by the PlatformAccessControl and PlatformUser classes. It provides an output structure which is filled with various error codes and values by the called z/OS security service, such as an access control check. The heart of the SAF interfaces in Java are four final classes, each of them representing a platform entity of z/OS. Methods of each class represent an API to manipulate this platform entity. Note: These methods come as static methods intended to be invoked without the need to instantiate an object of the class.
4.3.3 PlatformSecurityServer
This class represents the z/OS Security Server (such as RACF). Methods of this class are called to confirm the active status of the Security Server as shown in Example 4-1.
Example 4-1 isActive
if (PlatformSecurityServer.isActive()) System.out.println("Security Server is active."); else { System.out.println("Error."); return; } Methods of this class are also called to confirm that a specific class of resources is active. Note that the resource type is case sensitive, so you have to type it in upper case letters, as shown in Example 4-2.
Example 4-2 resourceTypeIsActive()
57
4.3.4 PlatformAccessControl
This class represents the access control function of the z/OS Security Server. It can be used to check the permission of the current user to a specific resource. If the current thread has a security context, the thread user ID is checked in an access control check. If not, the user ID associated with the current process is checked. This class actually wraps the __check_resource_auth_np service() function of the z/OS C/C++ Run Time Library. For authorization to use this function, the caller must have read permission to the BPX.SERVER Facility class, or if BPX.SERVER is not defined, the caller must be a superuser (UID=0). Note that the resource type and the resource name are case sensitive, so you have to type them in upper case letters, as shown in Example 4-3.
Example 4-3 checkPermission
PlatformReturned pr = PlatformAccessControl.checkPermission("FACILITY","BPX.SERVER",PlatformAccessLevel. READ); if (pr == null) System.out.println("User has READ access to the resource named BPX.SERVER of resource type FACILITY"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success + "\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } If the user is authorized for the specific resource, checkPermission() returns null; otherwise, pr is filled with error codes and messages. If in this example the user has no READ access to the resource, pr would return the following output: success: false errno: 139 errno2: 154665176 errnoMsg: EDC5139I Operation not permitted. The method checkPermission() can also be used to check whether a specific user has permission to a resource, as shown in Example 4-4. In this case, the user identity is specified as a parameter for this method.
Example 4-4 checkPermission for a specified user
PlatformReturned pr = PlatformAccessControl.checkPermission("anyUser","FACILITY","BPX.SERVER",PlatformAc cessLevel.READ ); if (pr == null) System.out.println("anyUser has READ access to the resource named BPX.SERVER of resource type FACILITY"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success +
58
4.3.5 PlatformThread
This class wraps z/OS UNIX thread level functions. It represents a UNIX thread that is mapped onto an z/OS task (TCB). The method getUserName is useful to extract the user associated with the current thread, as shown in Example 4-5. The method getUserName wraps the BPX1ENV UNIX System Services Assembler callable service.
Example 4-5 getUserName
4.3.6 PlatformUser
This class represents a z/OS user ID, which is the basis for z/OS platform authentication and access control. The parameters for user, password, and group are not case-sensitive. The authenticate method validates a user ID and a password as shown in Example 4-6. It wraps the _passwd() function.
Example 4-6 authenticate
PlatformReturned pr = PlatformUser.authenticate("anyUser","password"); if (pr == null) System.out.println("Password check was successful"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success + "\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } The isUserInGroup method checks whether a user is a member of a specific user group, as shown in Example 4-7.
Example 4-7 isUserInGroup
boolean isMember = PlatformUser.isUserInGroup("anyUser,anyGroup"); if (isMember) System.out.println("anyUser is a member of anyGroup"); else { System.out.println("anyUser is not a member of anyGroup"); } The changePassword method is used to change a user's password. The user ID and the current password are validated before the password is changed to the new value; see Example 4-8 on page 60.
59
PlatformReturned pr = PlatformUser.changePassword("anyUser","oldPwd","newPwd"); if (pr == null) System.out.println("Password change successful.\n"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success + "\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } Note: The functions wrapped by the methods of PlatformUser and PlatformAccessControl require that all modules within the address space must be loaded from a program controlled library when the BPX.DAEMON resource is defined in the RACF FACILITY class. Ask your system administrator to properly assign the program controlled status to the required libraries. When writing this chapter we found out that the following libraries had also to be program controlled: Program EAGRTPRC from library REXX.SEAGALT Program EX from library SYS1.CMDLIB Program ISPQRY from library ISP.SISPLOAD Program ISPCFIGU from library SYS1.USER.LOAD HFS program /bin/fomtlinp If you are using the SAF interface with JZOS batch launcher, then you also have to set the JZOS PDS load libraries program controlled. Program Control and APF authorization are explained in 1.5, Java and z/OS security on page 17.
60
Chapter 5.
61
RACF
Java application
JSec API
JVM
JNDI
TCP/IP
TCP/IP
SDBM backend
The API is designed to be extensible for future RACF enhancements or for use with other security repositories. The generic interface would need another security provider-specific implementation in order to be used with another security repository. The JSec API provides for easy mapping between this interface and the user interface constituted with the RACF TSO commands: ADDUSER, ALTUSER, ADDGROUP, ALTGROUP, CONNECT and REMOVE. Note: RACF uses the term CONNECT to add a user to a group. However, the Java interface uses terms such as add member and membership attributes, which correspond to the options on the CONNECT command. The implementation details of Java security administration and description of classes and methods used are documented at: http://www.ibm.com/servers/eserver/zseries/zos/racf/racfjsec/doc/index.html A compressed version of the javadoc can be downloaded using the following link: ftp://ftp.software.ibm.com/eserver/zseries/zos/racf/jsec/JSec_javadoc.zip
62
5.2 Installation
The requirements for using Java Security Administration are: z/OS version 1 release 9 or above Java (IBM 31-bit SDK for z/OS Java 2 Technology Edition, V5) The z/OS Integrated Security Services LDAP Server or the IBM Tivoli Directory Server for z/OS configured and running with the SDBM back-end. Refer to IBM Tivoli Directory Server Administration and Use, SC23-5191, or z/OS Integrated Security Services LDAP Server Administration and Use, SC24-5923, for setup details. Note: The JSec API works with both of these LDAP servers, but there is a limitation to the z/OS Integrated Security Services LDAP. Its SDBM version is limited to get a maximum of 4096 lines as a response to a RACF command. This may be an issue only in very specific cases like listing the users or groups in a large RACF DB. The new IBM Tivoli Directory Server in z/OS 1.8 has no such limitation. The Java security code is packaged into two jar files in HFS: /usr/include/java_classes/userregistry.jar (this contains the Java interface) /usr/include/java_classes/RACFuserregistry.jar (this contains the RACF-specific implementation)
javax.naming.directory.BasicAttributes javax.naming.directory.ModificationItem
63
Java interfaces and classes in com.ibm.security.userregistry.* that can be used for any security provider.
5.4.1 User
The interface ibm.com.security.userregistry.User extends ibm.com.security.Principal. This interface offers methods to: Get the attributes for the user from the security repository using getAttributes() Get a list of all user groups the user is a member of, using getGroups() Get the name of the user or its userID using getName()
5.4.2 UserGroup
The interface ibm.com.security.userregistry.UserGroup extends ibm.com.security.acl.Group and is intended to be a group of individual users. Implementations of this interface can be designed to support adding groups as members of other groups or not. Note: RACF does not support groups being members of other groups. This interface offers methods to: Add a member to the group using addMember() Get the attributes for the group from the security repository using getAttributes() Get the membership attributes for a user in the group using getMembershipAttributes() Get the name of the group using getName() Check if a user is member of the group or not, using isMember() Get a list of all members in the group using members() Modify membership attributes for a user in the group in the security repository using modifyMembershipAttributes() Remove a user from the group using removeMember()
5.4.3 SecAdmin
A very important interface is com.ibm.security.userregistry.SecAdmin. This interface is the primary interface in the security administration of users and groups. It provides the following methods: createUser() and createGroup() to define a new user or group in the security repository deleteUser() and deleteGroup() to delete an existing user or group from the security repository getUser() and getGroup() to instantiate a User or UserGroup object to work with in the application modifyUser() and modifyGroup() to change, add or delete attributes for an existing user or group
64
5.4.4 SecAdminException
This class is implemented for all exceptions thrown by the interfaces previously defined.
5.5.1 RACF_User
The class ibm.com.eserver.zos.racf.userregistry.RACF_User implements com.ibm.security.userregistry.User. The RACF_User object has no constructor. That is, a User object must be obtained by calling the getUser() or createUser() method of RACF_SecAdmin. To use the methods provided in this class, the User object must be cast to a RACF_User object. An example would be: ((RACF_User) ibmuser) This class offers two utility methods to: Obtain user attributes and their properties in a BasicAttributes object using attributesInfo() Display an HTML table of user attributes and their properties using attributesHTML() as shown in Table 5-1 on page 63 This method returns a String which has to be put in a Web browser in order to actually see the HTML table. For each attribute, the table displays the name and a description, whether it can be modified, whether it is a segment, whether it is a Boolean attribute, and whether it can have multiple values. A Boolean attribute is an attribute that does not have a particular value. The user either has this attribute or not. An example would be BASE_SPECIAL. A user either has the SPECIAL attribute or it does not. This can be contrasted to, for example, OMVS_UID where the caller would assign a specific value to the OMVS_UID attribute.
Table 5-2 Sample output from RACF_User.attributesHTML() User attributes Attribute name BASE_ADSP Description All permanent tape and DASD data sets created by user are automatically RACF-protected by discrete profiles. Modifiable Yes Segment No Boolean attribute Yes Multi-value attribute No
65
User attributes Attribute name BASE_AUDITOR Description Indicates user has full responsibility for auditing the use of system resources, and is able to control the logging of detected accesses to any RACF-protected resources during RACF authorization checking and accesses to the RACF database. Names of installation-defined security categories, which must be defined as members of the CATEGORY profile in the SECDATA class. Classes in which user is allowed to define profiles to RACF for protection. Classes can be USER, and any resource classes defined in the class descriptor table. The date this user was defined to RACF. These are the first five attributes of over 100. Modifiable Yes Segment No Boolean attribute Yes Multi-value attribute No
BASE_CATEGORY
Yes
No
No
Yes
BASE_CLAUTH
Yes
No
No
Yes
No
No
No
No
All possible user attributes and descriptions are listed in Appendix D, JSec attributes on page 235.
5.5.2 RACF_Group
The class ibm.com.eserver.zos.racf.userregistry.RACF_Group implements com.ibm.security.userregistry.UserGroup. The RACF_Group object has no constructor. That is, a UserGroup object has to be obtained by calling getGroup() or createGroup() method of RACF_SecAdmin. To use the methods provided in this class, the UserGroup object has to be cast to a RACF_User object. An example would be: ((RACF_Group) ibmgroup) This class offers four utility methods: attributesInfo() and membershipAttributes() both return a BasicAttributes object containing either group attributes and their properties or membership attributes and their properties. attributesHTML() and membershipAttributesHTML() both return an HTML table of group or membership attributes and their properties. All possible group and membership attributes and their description are listed in Appendix D, JSec attributes on page 235 under Group attributes on page 250 and Membership attributes on page 251.
66
5.5.3 RACF_SecAdmin
The class ibm.com.eserver.zos.racf.userregistry.RACF_SecAdmin implements com.ibm.security.userregistry.SecAdmin. This class offers: A method to create a user with the same attributes as an existing user using clone_user(). Actually not all attributes are copied from the existing user, for different reasons. BASE_PASSWORD and PROXY_BINDPW are not duplicated for security reasons. BASE_UAUDIT is not allowed to be set on a user ID creation. KERB_KERBNAME, LNOTES_SNAME and NDS_UNAME must be unique values across the system. Each user should have a unique OMVS_UID. clone_user() does not make the new user a member of any group other than the default group. Utility methods to sort attributes alphabetically by name using BasicAttributesToTreeMap() and to display all attributes, one on each line in alphabetical order using displayAttributes()
5.5.4 RACF_remote
The RACF_remote object defines the connection parameters of a remote or local RACF to be accessed via the z/OS LDAP server and SDBM back-end. A RACF_remote object is constructed with five strings: The connection URL for the z/OS LDAP server Like all URLs, this follows the convention: prototype://hostname:portnumber. An example of a connection URL would be: "ldap://wtsc60.itso.ibm.com:389" The connection mode It should be either set to simple for using LDAP or to secure for using LDAPS (that is, LDAP over an SSL/TLS connection). If it is null, simple will be used. The connection principal This is the RACF user ID to be used for LDAP bind. All RACF operations will be done using this users authority after a successful bind. The connection credentials This is the password of the RACF user ID used as connection principal. The connection suffix This is the SDBM back-end suffix; that is, the root of the LDAP naming space assigned to the RACF directory. The suffix appears as the last part of the distinguished name for any RACF LDAP entry. Note: Refer to IBM Tivoli Directory Server Administration and Use for z/OS, SC23-5191, or z/OS Integrated Security Services LDAP Server Administration and Use, SC24-5923, for information about installing and setting up the related functions.
67
01 02 03 04 05 06 07 08 09
68
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
RACF_remote remote = new RACF_remote("ldap://wtsc60.itso.ibm.com:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); try { SecAdmin racfAdmin = new RACF_SecAdmin(remote); if (racfAdmin != null) { User ibmuser = racfAdmin.getUser("IBMUSER"); BasicAttributes ibmuser_attr = ibmuser.getAttributes(); System.out.println("Attributes returned for IBMUSER are: "); RACF_SecAdmin.displayAttributes(ibmuser_attr); } } catch (Exception e) { System.out.println("Exception in Sample.java " + e.getMessage() + "\n"); e.printStackTrace(); } } }
The first four lines show the necessary import statements. The RACF_remote object containing the connection information is created in line 10. It includes the hostname, the information that a simple, unsecured connection is used, the user ID and passwords well as the target SDBM suffix. Note: The user ID provided in the RACF_remote object is the user ID that effectively executes the RACF commands. It is therefore important to ensure that this user ID possesses the proper RACF privileges. If an incorrect password is entered, line 29 will produce the following error message: com.ibm.security.userregistry.SecAdminException: Error initially connecting to LDAP/SDBM. Original error: [LDAP: error code 49 - R000104 The password is not correct or the user id is not completely defined (missing password or uid) (srv_authenticate_native_password)] At line 18, the RACF_remote object is provided as a parameter to the RACF_SecAdmin constructor. This means that a connection to the LDAP server is required. If the RACF_SecAdmin object was created successfully (line 19), then the getUser method returns a User object (line 21) and the getAttributes method returns the users attributes (line 22). Finally, these attributes are displayed in line 24 using the RACF_SecAdmin.displayAttributes method. The output should look like in Example 5-2 on page 70.
69
Attributes returned for IBMUSER are: BASE_CREATED: 06/06/08 BASE_DAYS: SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY BASE_DFLTGRP: SYS1 BASE_LAST-ACCESS: 06/25/08/13:02:32 BASE_OPERATIONS: No values <-- Boolean attribute BASE_OWNER: IBMUSER BASE_PASS-INTERVAL: 30 BASE_PASSDATE: 06/17/08 BASE_PASSWORD: Password Exists BASE_SECLABEL: SYSMULTI BASE_SPECIAL: No values <-- Boolean attribute BASE_TIME: ANYTIME BASE_USERID: IBMUSER OMVS_PROGRAM: /bin/sh OMVS_UID: 0 Most attributes have one or more values. For example, the first attribute, BASE_CREATED, which is the date the user was created, has a value of 06/06/08. The second attribute, BASE_DAYS are the days of the week the user can access the system. It has seven values (SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY). However, there are Boolean attributes, where the user either has the attribute or does not have the attribute, such as BASE_SPECIAL. When displayed in the preceding example, you see: BASE_SPECIAL: No values This indicates the user has the BASE_SPECIAL attribute, meaning the user is allowed to issue all RACF commands with all operands except the operands that require the AUDITOR attribute. If the user did not have the BASE_SPECIAL attribute, then you would not see BASE_SPECIAL at all when displaying the attributes.
01 02 03 04 05 06 07 08 70
09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
{ SecAdmin racfAdmin = null; UserGroup savants = null; User savant; RACF_remote remote = new RACF_remote("ldap://9.12.4.18:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } try { savants = racfAdmin.createGroup("savants", null); System.out.println("We just created a group called savants."); } catch (SecAdminException e) { System.out.println("Unable to create group 'savants'. "+e.getMessage()); return; } try { System.out.println("Now we are going to add some members."); savants.addMember(racfAdmin.createUser("Ohm",null)); savants.addMember(racfAdmin.createUser("Humboldt",null)); savants.addMember(racfAdmin.createUser("Curie",null)); savants.addMember(racfAdmin.createUser("Roentgen",null)); savants.addMember(racfAdmin.createUser("Bashful",null)); savants.addMember(racfAdmin.createUser("Bohr",null)); savants.addMember(racfAdmin.createUser("Einstein",null)); } catch (SecAdminException e) { System.out.println("Exception trying to add members to group 'savants'."+e.getMessage()); return; } System.out.println("savants Members:"); for (Enumeration ae = savants.members(); ae.hasMoreElements();) { User user = (User)ae.nextElement();
71
61 62
System.out.println(user.getName()); }
When you are connected to the SDBM back-end, you can create a new RACF group named SAVANTS with default attributes on line 32. Therefore, the SecAdmin.createGroup method is used. In line 44 to 50, seven members with default attributes are created and added to group SAVANTS. The lines 58 to 61 will display the names of all members of the group SAVANTS. If the user ID provided in the RACF_remote object has insufficient authorizations to add groups to the security repository, the following error message will be produced by the code in line 37. Unable to create group 'savants'. Error creating Group. Original error: [LDAP: error code 80 - ICH00007I INSUFFICIENT AUTHORITY TO SUPERIOR GROUP.] If the group that you want to add already exists, the code in line 37 will produce the following error message: Unable to create group 'savants'. Group savants already exists. The same applies for adding users if there is insufficient authorization or a user already exists. Assuming that the user Einstein is the leader of the group, that user should have the BASE_SPECIAL attribute. Example 5-4 illustrates how to modify the membership attributes of user Einstein.
Example 5-4 Modify attributes
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
try { System.out.println("Einstein is leader of the group, should be SPECIAL."); ModificationItem mods[] = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("BASE_SPECIAL")); savant = racfAdmin.getUser("Einstein"); savants.modifyMembershipAttributes(savant,mods); } catch (SecAdminException e) { System.out.println("Error modifying membership attributes "+e.getMessage()); return; } try { BasicAttributes member_at = savants.getMembershipAttributes(savant); System.out.println("Membership attributes returned for Einstein are: "); RACF_SecAdmin.displayAttributes(member_at); savant = racfAdmin.getUser("Bohr"); member_at = savants.getMembershipAttributes(savant); System.out.println("Membership attributes returned for Bohr are: ");
72
86 87 88 89 90 91 92 93
How to declare, define, and use a ModificationItem array is shown in lines 66 to 70. The lines 79 to 86 get the membership attributes of the users Einstein and Bohr and display them. The output from this running code is shown in Example 5-5. You can see that Einstein has an attribute BASE_SPECIAL. The user Bohr, which was created with default attributes and had not been modified, does not.
Example 5-5 Output of membership attributes
Membership attributes returned for Einstein are: BASE_AUTHORITY: USE BASE_CONNECT-DATE: 06/25/08 BASE_CONNECTS: 0 BASE_OWNER: IBMUSER BASE_SPECIAL: No values BASE_UACC: NONE Membership attributes returned for Bohr are: BASE_AUTHORITY: USE BASE_CONNECT-DATE: 06/25/08 BASE_CONNECTS: 0 BASE_OWNER: IBMUSER BASE_UACC: NONE Finally, Example 5-6 illustrates how to remove user Roentgen from the group and delete the user ID Roentgen from the security repository.
Example 5-6 Delete user
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
try { savant = racfAdmin.getUser("Roentgen"); savants.removeMember(savant); racfAdmin.deleteUser("Roentgen"); System.out.println("savants after removing member Roentgen:"); for (Enumeration ae = savants.members(); ae.hasMoreElements();) { User user = (User)ae.nextElement(); System.out.println(user.getName()); } } catch (SecAdminException e) { System.out.println("Error deleting Roentgen from savants "+e.getMessage()); } } }
73
Line 96 shows how to remove Roentgen from the group SAVANTS using the UserGroup.removeMember method. To delete Roentgen from RACF, the SecAdmin.deleteUser method is used (line 97). The lines 99 to 103 will print out all members of the group SAVANTS, and Roentgen should not appear there anymore.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
import com.ibm.eserver.zos.racf.userregistry.*; import com.ibm.security.userregistry.*; import javax.naming.directory.*; public class ChangePassword { public static void main(String[] args) { SecAdmin racfAdmin = null; User catuser = null; RACF_remote remote = new RACF_remote("ldap://9.12.4.18:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } BasicAttribute pwd = new BasicAttribute("base_password"); pwd.add("wuff"); pwd.add("noexpired"); try { System.out.println("Changing password for Cat"); ModificationItem mods[] = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,pwd); racfAdmin.modifyUser("cat",mods); } catch (SecAdminException e){ System.out.println("Error changing password "+e.getMessage());
74
40 41 42 43
return; } } }
To change a users password, you must first create a new BasicAttribute object (line 28). In line 29 and 30, store the new password and the information noexpired in the BasicAttribute object. Then create a ModificationItem which contains the information that an attribute has to be replaced and the new BasicAttribute (line 35). Now you can modify the user Cat with this ModificationItem (line 36).
75
76
Chapter 6.
77
There are exceptions to the single-use protection of Passtickets; refer to 6.8, Miscellaneous PassTicket considerations on page 88 for more information about this topic.
78
An additional function, the secured signon session key, is closely related to the PassTicket functionality. It gives z/OS applications the ability to generate an 8-byte key from an existing PassTicket, which can be used as a symmetric encryption key. Due to the lack of Java interfaces to this function, this functionality is beyond the scope of this book and is not covered.
6.2 Documentation
Description and use of PassTickets is documented across multiple RACF publications. This can make it difficult to find the appropriate information at times. In the RACF publications, PassTicket support is usually described as the Secured Signon Function. When searching the IBM publications for information about PassTicket, a search for Secured Signon may yield additional results. Table 6-1summarizes the nature of the information on PassTicket given in the various RACF publications.
Table 6-1 PassTicket information in the RACF documentation Publication z/OS Security Server RACF Security Administrator's Guide, SA22-7683 Topic PassTicket overview. Details about how to configure RACF to define and use PassTickets. PassTicket application profile definition information, including options for the protection of the secret key. Discussion of how to derive RACF profile names, including how to determine the application names of various z/OS subsystems and the user ID and group scoping functionality. Overview of how RACF processes PassTickets. Bypassing replay protection, when is it appropriate, and how to do it. Troubleshooting. z/OS Security Server RACF Macros and Interfaces, SA22-7682 Describes various IBM supported mechanisms that can be used to generate PassTickets on z/OS. Details about the PassTicket generation algorithm which can be used to implement non-z/OS PassTicket generation code. This book contains the only mention of the Java PassTicket interfaces and a pointer to the location of the documentation which is found in the UNIX file system. z/OS Security Server RACF System Programmer's Guide, SA22-7681 Another overview of PassTickets.
79
Topic Discussion about the R_gensec and R_ticketserv callable services which generate and evaluate PassTickets. This includes return codes from these functions. Documents audit records created by the R_ticketserv and R_gensec services when they perform PassTicket operations. Details about using SAF Trace.
z/OS V1R9.0 Security Server RACF Auditor's Guide z/OS Security Server RACF Diagnosis Guide, GA22-7689
client and it is up to z/OS to determine the application name, based on how the user connected to the system. In some cases, it is easy to determine the application name. The PassTicket is used to log on to a custom z/OS application which directly specifies the application name in a call to RACROUTE REQUEST=VERIFY using the APPL= parameter. In this case, the generator and evaluator can decide in advance which application name to use and code the same application name during generation and evaluation. Logging on to existing applications might be problematic because the user needs to determine which application name will be used by RACF during the PassTicket evaluation process. Some applications have simple constant names, but others require scrutiny to determine which name to use. z/OS Security Server RACF Security Administrator's Guide, SA22-7683, discusses in detail how to select application names in the chapter Using the Secured Signon Function. In addition to the applications that are documented in the RACF publication, OMVSAPPL is used, as an application name, by UNIX System Services applications that call _passwd() and _pthread_security_np(). In z/OS V1R10, the new UNIX System Services functions _passwd_appl() and _pthread_security_np_appl() have been created. They allow an application to be specified directly on the call, overriding the default OMVSAPPL. WebSphere Application Server uses CBS390 as the default application name, but this can be overridden by using the security.zOS.domainName property.
81
These authorization profiles are all defined in the PTKTDATA class and can be defined using RDEFINE and changed using RALTER. RDEFINE IRRPTAUTH.application.target-user UACC(NONE) Where: application is the application name that this profile protects. Another profile in the PTKTDATA class must exist with this application name and contain a key in the SSIGNON segment. target-user is the user ID for whom a Passticket operation is to be performed. UACC(NONE) defines that, by default, no one may perform PassTicket operations. Users with UPDATE access to a IRRPTAUTH profile are allowed to generate PassTickets for target-user for use with the application application. Generics are allowed in these profiles, so profiles that cover multiple users or multiple applications can be defined. Users with READ access to a IRRPTAUTH profile are allowed to evaluate PassTickets for target-user for use with application application.
82
>jar -xvf IRRRacfDoc.jar created: META-INF/ inflated: META-INF/MANIFEST.MF created: doc/ inflated: doc/allclasses-frame.html inflated: doc/allclasses-noframe.html created: doc/com/ created: doc/com/ibm/ created: doc/com/ibm/eserver/ created: doc/com/ibm/eserver/zos/ created: doc/com/ibm/eserver/zos/racf/
Figure 6-1 Using the jar utility to expand IRRRacfDoc.jar
If the jar utility is unavailable, the file can be processed as a zip file after renaming it to IRRRacfDoc.zip. From here, the index.html file in the document directory is opened using a Web browser and the documentation is viewable.
83
import com.ibm.eserver.zos.racf.IRRPassTicket; import com.ibm.eserver.zos.racf.IRRPassTicketGenerationException; public class ptGen { public static void main(String args[]) { IRRPassTicket x; // Sample user and appl info.. String userid="IBMUSER"; String appl="SAMPAPPL"; // New instance of passticket class try { // Get new PT object x= new IRRPassTicket(); System.out.println("User="+userid+" appl="+appl); // Generate new PassTicket. String pt= x.generate(userid,appl); System.out.println("New PassTicket: " + pt); // Catch failure. } catch (IRRPassTicketGenerationException bx) { System.out.println("Generation Exception caught: " + bx); bx.printStackTrace(); } } }
Figure 6-2 Program to generate a PassTicket
Compile > javac -classpath /usr/include/java_classes/IRRRacf.jar ptGen.java Execute >java -classpath /usr/include/java_classes/IRRRacf.jar:. ptGen User=IBMUSER appl=SAMPAPPL New PassTicket: R4CHQH1V In practice it would be expected that the generated PassTicket be used to log on to a remote server and not to be displayed on the screen.
84
These return codes are found in z/OS Security Server RACF Callable Services, SA22-7691. If a 31-bit JVM is used, the failing service is R_ticketserv (IRRSPK00). If a 64-bit JVM is used, the failing service is R_gensec (IRRSGS64).
85
Execute (use another program to first generate PassTicket) >java -classpath /usr/include/java_classes/IRRRacf.jar:. ptGen User=IBMUSER appl=SAMPAPPL New PassTicket: 6IJX0888 >java -classpath /usr/include/java_classes/IRRRacf.jar:. ptEval 6IJX0888 User=IBMUSER appl=SAMPAPPL pt=6IJX0888 PassTicket is valid If the PassTicket is evaluated a second time, the evaluation fails because the PassTicket may not be reused. >java -classpath /usr/include/java_classes/IRRRacf.jar:. ptEval 6IJX0888 User=IBMUSER appl=SAMPAPPL pt=6IJX0888 PassTicket evaluation failed.SafRc=8, racfRc=16 racfRsn=32
The single use restriction of PassTickets can be bypassed. Refer to 6.8, Miscellaneous PassTicket considerations on page 88.
86
6.7 Audit
The Java PassTicket interfaces create audit records if audit settings are activated on PTKTDATA application profiles which contain the key. It is good practice to log the generation of PassTickets because, in effect, this action allows one user the ability to gain access as another user. Audit can be set as follows: RALTER PTKTDATA OMVSAPPL AUDIT(SUCCESS(UPDATE)) Audit records show when a PassTicket is generated or evaluated, the user ID which performed the operation, the user ID for whom the PassTicket operation was performed, and the application name used. Figure 6-4 shows the XML format of SMF audit records, as provided by the RACF SMF data unload utility, that are relevant to PassTicket generation. <event> <eventType>PTCREATE</eventType> <eventQual>SUCCESS</eventQual> <timeWritten>09:39:59.53</timeWritten> <dateWritten>2008-06-30</dateWritten> <details> <evtUserId>SRVRUSER</evtUserId> <evtGrpId>SYS1</evtGrpId> <term>093831A6</term> <jobName>SERVER7</jobName> <application>OMVSAPPL</application> <targetUser>TESTUSER</targetUser> <userName>USER NAME</userName> </details> </event>
Figure 6-4 XML output from SMF Unload showing an audit record generated when a PassTicket is generated
Note that these additional audit records are not created when standard z/OS logon processing is used to log on with a PassTicket. They are only created when a PassTicket is generated or evaluated.
3
Refer to 6.8, Miscellaneous PassTicket considerations on page 88 for more information about scoping.
87
In addition, audit records may be cut when authorization to the PassTicket services is checked, depending on the audit setting set in the IRRPTAUTH profiles in the PTKTDATA class.
SAF Trace
The Java native code calls SAF R_ticketserv or R_gensec callable services. These calls may need to be traced in order for IBM support to debug problems. These services are traced with the SAF Trace facility. R_ticketserv is service number 43. R_gensec is service number 50. SAF Trace can also be used to help diagnose problems when PassTickets are used to logon to z/OS. Trace of the initACEE callable service (number 38) will trace some logon invocations. Trace of the RACROUTE REQUEST=VERIFY and VERIFYX (RACROUTE call numbers 4 and 9) will trace call to the lowest level RACF logon service. SAF Trace is documented in z/OS Security Server RACF Diagnosis Guide, GA22-7689. Refer to this document for more detailed information about setting up and using SAF Trace.
88
Client 1
key=0x1111111111111111
Both clients and server itself may generate and then logon with userID and PassTicket
Client 2
Key=0x2222222222222222
APPL1
z/OS server
APPL1.GROUP1
Evaluate using keys
key=0x1111111111111111
APPL1.FRED
Key=0x2222222222222222
Figure 6-5 illustrates that Client 2 is only able to create a PassTicket for user FRED for APPL1 because it only has the key for APPL1.FRED. Client 1 may create a PassTicket for APPL1, but only for users connected to RACF group GROUP1. The server has access to all keys and may create PassTickets for all users to access APPL1. Note that the client must take care in selecting the proper key for the proper user. For example, if FRED belongs to GROUP1, Client 1 is unable to generate a PassTicket for FRED because user FRED most closely matches the APPL1.FRED and this key will be used when
89
the PassTicket is evaluated. There is no fallback to less-specific profiles during the PassTicket evaluation process. Even more confusing is that this profile matching mechanism is only used during the evaluation during logon of the PassTicket. The z/OS services that are used to generate a PassTicket only use the secret key stored in the 'applicationName' profile, and never the group or user qualified profiles. So, to make use of this feature, the key generation must take place on a different system from the one where the PassTicket is evaluated.
90
Chapter 7.
91
Enterprise identity
John N Smith
Windows User
iSeries User
AIX user
Kerberos Principal
Notes User
DCE User
Enterprise User
z/OS User
Smith
JOHNS
JohnSM
JSmith
JOHN
Typically, these multiple user registries have a design and implementation specific to each type of platform or even application, because some of them may have been implemented at the application level. They have grown over time, along with the user population and the introduction of new systems and applications. This can result in significant administrative challenges that affect users, administrators, and application developers when it comes to keeping track of a single entity and its many representations in the installation. In addition, system-specific local user IDs and registries, with their underlying mechanisms, are not going to unify in a common format across all vendors, at least for the foreseeable future. A user authenticates to an installation using a network identity, which would be John N Smith in this example. It would then be left to the involved applications to map this network identity to the locally meaningful representation (user ID) of this user.
92
Enterprise Identity Mapping has been introduced as part of the IBM On Demand Initiative. It is an IBM system infrastructure technology that allows administrators and application developers to address this problem more easily and inexpensively than previously possible. By providing centralized and protected identification facilities, it also contributes to enabling products and applications to run in a more secure way in todays extremely open environments, as expected for the On Demand operating infrastructure. EIM accomplishes this by providing a central place to store mappings between user IDs that are defined in different registries in an installation. These mappings indicate: A relationship between user IDs, that is, user IDs that belong to the same person or entity within the enterprise, or A transformation of one or more user IDs to an application-specific user ID In EIM terminology, the unique name given at an enterprise level for a user or entity is the EIM Identifier. EIM actually defines associations between an EIM identifier and user IDs in registries that are part of operating system platforms, applications, and middleware. Applications, typically servers, can then use an EIM API to find a mapping that transforms the installation-level user ID initially used for authentication to a local user ID. The local user ID can, in turn, be used to access local resources. Important: As the name implies, EIM is used to provide identity mapping only. EIM is not used to provide user authentication itself, which must be performed ahead of identity mapping. It is the application deployment strategys responsibility to decide on how user authentication should be performed and how interapplication trust can be implemented. Kerberos is an authentication mechanism that may nicely fit the authentication needs in an EIM environment.
93
94
EIM client
et rg Ta
Target
Targ e
EIM client
DomServer
Key Distribution Center (KDC)
Ik
AS
TGS
no w, t
r Sou ce
EIM client
et rg Ta
John
EIM client
SysA
This is the code that implements the EIM lookup APIs and the administrative APIs that can be used for creating, modifying, displaying, and removing information from an EIM domain. The EIM client uses the EIM API that is provided with the IBM systems operating systems or which are downloadable from the Internet.
95
The EIM client APIs are available for the following operating systems: OS/400, i5/OS z/OS AIX Windows Linux Note that the Windows and Linux clients have to be downloaded from:
http://www-1.ibm.com/servers/eserver/security/eim/availability.html
EIM identifier
This is the name that represents the unique name of an individual or entity within the enterprise. It can be a name or number or some combination of the two that represent a person or entity in the company. The EIM identifier is the anchor point for all mappings. This is the logical representation of a user registry that exists on one of the systems in the network. Examples of user registries are RACF (or equivalent), LDAP (which contains bind IDs and passwords), Lotus Notes, and so on. An EIM registry only contains user IDs and EIM information needed for mappings with EIM identifiers. It does not contain any of the other information, such as passwords or user attributes, that normally exist in a user registry.
EIM registry
EIM associations
These are the relationships between a use rID and an EIM identifier. There are three kinds of associations: source association - The registry user ID can be used as a source, that is a starting point, for a lookup operation. (It is assumed here that the source identity was properly authenticated by the application.) target Association - The registry user ID can be returned as the target value for a lookup operation. It is expected that this user ID is intended to be used for access control by the application. The EIM domain controller also provides fields for application-specific information that can be used to refine the lookup results. administrative association - the user ID is kept in the EIM Domain Controller for administration purpose only. However, it is not recognized as a source or target user ID in a mapping lookup. It is also not returned as a result of a mapping lookup. User IDs can be defined with both source and target, and if desired, with administrative associations.
EIM policies
These are a special kind of association that can be used by an EIM lookup operation. If the EIM lookup API cannot locate a specific EIM association, the API will look for a policy. The policy acts as a default or many-to-one mapping between a source registry and a target registry.
96
There are three kinds of policies: A certificate filter policy associated with an x.509 registry A registry policy A domain policy EIM lookup operations These retrieve a mapping from the specified EIM domain. There are three kinds of lookups: Get Target From Source returns a user ID in the target registry when a source registry and source user ID is provided. Get Target From Identifier returns a user ID in the target registry when only the EIM identifier is provided. Get Associated Identifier returns the EIM identifier that has an association with the given registry and user ID.
97
The subtrees to the EIM domain entry contain: EIM identifiers - A source user ID points to an EIM identifier. Therefore, all existing source associations are represented at the EIM identifier level. registries - These are the representations of the IBM identifier local to a system of application. The lookup target associations are represented at the registry level. groups - These are EIM access control groups. These directory entries can be built and maintained via the Java APIs. Users should not try to manage them directly using their own LDAP operations.
o=itso,c=us
Ibm-eimDomainName=myJavaDomain
cn=Identifiers
cn=registries
cn=groups
Cn=myJavaIdentifiers
Ibm-eimRegistryName= myJavaSysReg_RACF
Ibm-eimRegistryName= myJavaAppReg_RACF
Ibm-eimRegistryName= myJavaSysReg_LDAP
cn=users
cn=TargetMappings
Ibm-eimTargetAssoc:=idUUID
98
A client digital certificate, over an SSL connection, that contains the client distinguished name. The SSL protocol itself ensures proper authentication of the client. Note: Much information, such as the LDAP bind and authentication data and the domain to be used can be entered, for security and information management purposes, in RACF profiles used when connecting to the EIM Domain Controller. For more information about this topic, refer to 7.4, Writing EIM Java applications on page 104.
99
* There is also a registry admin group for each registry. ** Available with z/OS 1.6.
EIM schemas
In z/OS, the EIM LDAP object classes and attributes definitions are delivered in the schema.IBM.ldif file in /usr/lpp/ldap/etc/. At the time of writing, they are:
Objectclasses
ibm-eimDomain ibm-eimIdentifier ibm-eimRegistry ibm-eimSystemRegistry ibm-eimApplicationRegistry ibm-eimRegistryUser ibm-eimSourceRelationship ibm-eimTargetRelationship ibm-eimDefaultPolicy ibm-eimDomainName ibm-eimFilterPolicy ibm-eimPolicyListAux
100
Attributes
ibm-eimDomainName ibm-eimAdditionalInformation ibm-eimAdminUserAssoc ibm-eimDomainVersion ibm-eimRegistryAliases ibm-eimRegistryEntryName ibm-eimRegistryName ibm-eimRegistryType ibm-eimSourceUserAssoc ibm-eimTargetIdAssoc ibm-eimTargetUserName ibm-eimUserAssoc ibm-eimFilterType ibm-eimFilterValue ibm-eimPolicyStatus
7.2.4 RACF profiles to keep EIM default parameters for LDAP bind information
Several profiles can be used to store in RACF an LDAP URL, the bind distinguished name, and the bind password, which can then be retrieved by the EIM services to bind to the EIM Domain Controller. The choice of the profile is dictated by the intent to either establish a system default that is used for EIM only, or that can be used by other functions (such as the z/OS PKI Services), or to establish a default IRR.EIM.DEFAULTS profile in the LDAPBIND class or IRR.PROXY.DEFAULTS profile in the FACILITY class. These profiles are searched in the following order, as shown in Figure 7-4 on page 102, by EIM services which have been invoked without specifying the Domain Controller or Domain in their parameter list: 1. Application user ID specific default The user-specific default is in a profile in the LDAPBIND class, with an arbitrary name that should also appear in the EIM segment of the USER profile. An example of definition of this profile is: RDEFINE LDAPBIND BUCKSDOMAIN + EIM(DOMAINDN('ibm-eimDomain=Bucks Domain.o=ibm.c=us')) + OPTIONS(ENABLE)) + PROXY(LDAPHOST(ldap://another.big.host) + BINDDN('cn=EIM Application Lookups') BINDPW('secret')) To establish this profile as a default for a the specific user SERVERID, the EIM segment in the USER profile can be updated as follows: ALTUSER SERVERID EIM(LDAPPROF(BUCKSDOMAIN)) 2. System-wide default The IRR.EIM.DEFAULTS profile in the LDAPBIND class establishes a default. An example of definition of this profile is: RDEFINE LDAPBIND IRR.EIM.DEFAULTS + EIM(DOMAINDN('ibm-eimDomain=Joes Domain.o=ibm.c=us')) + OPTIONS(ENABLE)) + PROXY(LDAPHOST(ldap://some.big.host) + BINDDN('cn=EIM Lookup') BINDPW('secret'))T
Chapter 7. z/OS Enterprise Identity Mapping for Java applications
101
3. System-wide default IRR.PROXY.DEFAULTS profile in the FACILITY class. An example of definition of this profile is: RDEFINE FACILITY IRR.PROXY.DEFAULTS + EIM(DOMAINDN('ibm-eimDomain=Joes Domain.o=ibm.c=us')) + OPTIONS(ENABLE)) + PROXY(LDAPHOST(ldap://some.big.host) + BINDDN('cn=EIM Lookup') BINDPW('secret'))
USER class
FACILITY class
IRR.PROXY.DEFAULTS
LDAPBIND class
profile_name
IRR.EIM.DEFAULTS
Figure 7-4 Keeping EIM LDAP and domain information in RACF profiles
The EIM and PROXY segment keywords and options combine to define the EIM domain, the LDAP host it resides on, and the bind information required by the EIM services to establish a connection with an EIM domain. The EIM services will attempt to retrieve this information when it is not explicitly supplied via invocation parameters.
7.2.5 RACF profiles to keep EIM default parameters for the local registry name
The assumption here is that the registry name is also specified in the EIM Domain controller, presumably by using the administrative API, or the eimadmin utility. The local registry name can be set in the FACILITY IRR.PROXY.DEFAULTS profile by the RACF administrator for retrieval by the following methods, when the local registry is not indicated in the parameter list: findTarget findTargetFromSource getAssociations getAssociatedEids
102
The local registry name can be set with the following commands: RALTER FACILITY IRR.PROXY.DEFAULTS EIM(LOCALREGISTRY('registry_name')) A local registry name can be removed from storage with the following commands: RALTER FACILITY IRR.PROXY.DEFAULTS EIM(NOLOCALREGISTRY)
EIM Java Application EIM Java Interface Code JNI Layer C/C++ glue EIM C/C++ APIs LDAP C/C++ client
Figure 7-5 The z/OS EIM Java API
LDAP
The documentation is available in the z/OS HFS at /usr/lpp/eim/lib/eimzOS_DOC.jar. Like any jar file, it contains ASCII data and should be transferred as a binary image to a workstation for unjarring and then browsing the HTML pages.
Java classpath
The following two jar files must be in the user classpath: /usr/lpp/eim/lib/eim.jar /usr/lpp/eim/lib/eimzOS.jar
103
RACF setup for a Java application running with the identity TSOUSER
The FACILITY class of resources should be made active in RACF and RACLISTed with the following commands: SETR CLASSACT(FACILITY) SETR RACLIST(FACILITY) The proper profiles have to be defined in the FACILITY class: RDEFINE RDEFINE RDEFINE RDEFINE FACILITY FACILITY FACILITY FACILITY IRR.RGETINFO.EIM UACC(NONE) IRR.RDCEKEY UACC(NONE) IRR.RAUDITX UACC(NONE) IRR.RADMIN UACC(NONE)
The user TSOUSER must have permission to the profiles: PERMIT PERMIT PERMIT PERMIT IRR.RGETINFO.EIM CLASS(FACILITY) ID(TSOUSER) ACCESS(READ) IRR.RDCEKEY CLASS(FACILITY) ID(TSOUSER) ACCESS(READ) IRR.RAUDITX CLASS(FACILITY) ID(TSOUSER) ACCESS(READ) IRR.RADMIN CLASS(FACILITY) ID(TSOUSER) ACCESS(READ)
Finally, the RACLISTed profiles should be refreshed to take into account the new definitions in the FACILITY class: SETR RACLIST(FACILITY) REFRESH
104
105
// Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); // Build the ldap url String ldapServer = "9.12.4.18"; String domainName = "myJavaDomain"; String baseDn = "o=itso,c=us"; String ldapUrl = "ldap://" + ldapServer + "/ibm-eimdomainname=" + domainName + "," + baseDn; // Create the domain Domain myJavaDomain = domainMgr.createDomain(ldapUrl, connectInfo, "description");
Figure 7-7 Creating an EIM Domain
Existing domains may be retrieved to perform lookups or administration. The user can retrieve a single domain by specifying the domain name, or can retrieve several domains by specifying only the server address and root. Figure 7-8 shows how to retrieve a single EIM domain. // Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); // Retrieve a single domain String ldapUrl = "ldap://9.12.4.18/ibm-eimdomainname=myJavaDomain,o=itso,c=us"; Domain myJavaDomain = domainMgr.getDomain(ldapUrl, connectInfo); // Display the domain System.out.println("domain: " + myJavaDomain.getName());
106
// Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); // Retrieve all domains (notice that no domain is specified in the ldap url) String ldapUrl = "ldap://9.12.4.18,o=itso,c=us"; Set myJavaDomains = domainMgr.getDomains(ldapUrl, connectInfo); // Display the domains Iterator iter = myJavaDomains.iterator(); while(iter.hasNext()) System.out.println("domain: " + iter.next());
Figure 7-9 Retrieving multiple domains
Note again that the LDAP URL is optional for creating and retrieving the default domain. Instead, a null value can be passed, which results in the EIM Defaults being used. Refer to 7.4, Writing EIM Java applications on page 104 for more information about this topic. Figure 7-10 shows the retrieval of a default domain. The relevant RACF profile definition is as follows: RALTER FACILITY IRR.PROXY.DEFAULTS + EIM(DOMAINDN('ibm-eimDomainname=myJavaDomain.o=itso.c=us')) + OPTIONS(ENABLE)) + PROXY(LDAPHOST(ldap://some.big.host) + BINDDN('cn=ldap_administrator,o=itso,c=us') BINDPW('secret'))
// Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); // Retrieve the default domain (notice that null is specified in the ldap url) Set myJavaDomains = domainMgr.getDomains(null, connectInfo);
Although the DomainManager class can create and retrieve domains, the Domain class provides both administrative and lookup functionality.
107
Users can perform the following administrative functions: Add system and application registries, policy associations, identifiers List associations, identifiers, registries Remove policy associations Delete the domain Disconnect or reconnect the domain Users can also perform the following lookup function: Get target users from source Domain usage samples are provided in steps 3 to 7.
108
The Registry object that is returned on the call to addSystemRegistry or addApplicationRegistry can be cast to either a SystemRegistry or an ApplicationRegistry object. This is referred as the kind of registry which will always be either EIM_APPLICATION_REGISTRY or EIM_SYSTEM_REGISTRY. Steps 4 and 5 shows how to add users to these registries by creating identifiers and associations. Figure 7-11 shows how to add registries. // Add a system registry Registry ldapSysReg = myJavaDomain.addSystemRegistry("myJavaSysReg_LDAP", Registry.EIM_REGTYPE_LDAP, "description", "uri"); // Add an application registry Registry racfSysReg = myJavaDomain.addSystemRegistry("myJavaSysReg_RACF", Registry.EIM_REGTYPE_RACF, "description", "uri"); Registry racfAppReg = myJavaDomain.addApplicationRegistry("myJavaAppReg_RACF", Registry.EIM_REGTYPE_RACF, "description", racfSysReg.getName()); // List the registries Set regs = myJavaDomain.getRegistries(); // Display the registries Iterator iter = regs.iterator(); while(iter.hasNext()){ Registry reg = ((Registry) iter.next()); System.out.println("registry: " + reg.getName() + " kind: " + reg.getKind()); }
Figure 7-11 Adding registries
109
// Add a user identifier Eid identifier = myJavaDomain.addEid("myJavaIdentifier", "description"); // List the identifiers Set identifiers = myJavaDomain.getEids(); // Display the identifiers Iterator iter = identifiers.iterator(); while(iter.hasNext()){ Eid eid = ((Eid) iter.next()); System.out.println("identifier: " + eid.getName()); }
Figure 7-12 Adding an identifier
// Associate the identifier with the users in various registries identifier.addAssociation(Association.EIM_SOURCE, ldapSysReg.getName(), "javauser@us.ibm.com"); identifier.addAssociation(Association.EIM_TARGET, racfAppReg.getName(), "javausr"); // List associations Set srcAssoc = identifier.getAssociations(Association.EIM_SOURCE); Set tgtAssoc = identifier.getAssociations(Association.EIM_TARGET); // Display associations Iterator iter = srcAssoc.iterator(); while(iter.hasNext()){ Association assoc = ((Association) System.out.println("association: " } iter = tgtAssoc.iterator(); while(iter.hasNext()){ Association assoc = ((Association) System.out.println("association: " }
Figure 7-13 Adding an association
iter.next()); + assoc.getUid());
iter.next()); + assoc.getUid());
// Display target users Iterator iter = ldapUsers.iterator(); while(iter.hasNext()){ RegistryUser regUser = ((RegistryUser) iter.next()); System.out.println("registry=" + regUser.getRegistryName() + " user=" + regUser.getTargetUserName()); } iter = racfUsers.iterator(); while(iter.hasNext()){ RegistryUser regUser = ((RegistryUser) iter.next()); System.out.println("registry=" + regUser.getRegistryName() + " user=" + regUser.getTargetUserName()); }
Figure 7-14 Listing registry users
111
Using the target registry is optional for retrieving the local registry. Instead, a null value can be passed in which results in the EIM Defaults be used. For more information about this topic,
112
refer to 7.2.5, RACF profiles to keep EIM default parameters for the local registry name on page 102. If the defaults are defined using the following RACF commands: RALTER FACILITY IRR.PROXY.DEFAULTS EIM(LOCALREGISTRY('myJavaSysReg_RACF')) SETROPTS EIMREGISTRY then the lookup operation can be invoked as shown in Figure 7-17. // Use EIM to map the off-platform user id to a RACF user id // Note that the target registry is null Set regUsers = myJavaDomain.findTargetFromSource("javauser@us.ibm.com", "myJavaSysReg_LDAP", null); // List the user RegistryUser regUser = ((RegistryUser) regUsers.iterator().next()); String mappedUser = regUser.getTargetUserName(); // Display the user System.out.println("mappedUser: " + mappedUser);
Figure 7-17 Lookup operations using the default definitions
113
The components of the eimjavademo application are shown In Figure 7-18, with an indication of which z/OS Java APIs are exploited.
Java Demo
A P I
Java EIM
A P I
Java PassTicket
A P I
JSec
114
javauser@us.ibm.com secret
Step 2: Authenticate the Java user javauser@us.ibm.com demoSysReg_JAVADEMO demoSysReg_RACF Step 3: Map the Java user to z/OS user
racfuser
racfuser racfpassticket
justjava
115
o=itso,c=us
Ibm-eimDomainName=myJavaDomain
cn=Identifiers
cn=registries
cn=groups
Cn=demoIdentifiers
Ibm-eimRegistryName= demoSysReg_RACF
Ibm-eimRegistryName= demoSysReg_JAVADEMO
cn=users
cn=TargetMappings
Ibm-eimTargetAssoc:=idUUID
Java setup
The following jar files must be in the java classpath in order to try the demo. For the EIM API /usr/lpp/eim/lib/eim.jar /usr/lpp/eim/lib/eimzOS.jar For the Passticket API /usr/include/java_classes/IRRRacf.jar For the JSec API /usr/include/java_classes/RACFuserregistry.jar /usr/include/java_classes/userregistry.jar
EIM setup
EIM administration is performed via the EIM Java APIs. The relevant administrative functions calls are included in the demo code.
PassTicket setup
Refer to Chapter 6, RACF PassTicket generation and evaluation by z/OS Java applications on page 77 for basic setup information. The PassTicket you obtain will be used to logon to the JSec API, that is, to perform an LDAP authenticated bind (actually verified by RACF through the SDBM back-end). 116
Java Security on z/OS - The Complete View
The application name to be used to qualify the PTKTDATA profile in RACF is, in that case, the job name of the LDAP server started task (ITDS1, in our case). Furthermore, the z/OS user associated with the PassTicket is JAVAUSR, which is the mapped-to user in EIM. The RACF PTKTDATA profile should therefore be defined as follows: RDEFINE PTKTDATA IRRPTAUTH.ITDS1.JAVAUSR UACC(NONE) PERMIT IRRPTAUTH.ITDS1.JAVAUSR CLASS(PTKTDATA) ID(TSOUSER) ACCESS(UPDATE) SETR RACLIST(PTKTDATA) REFRESH
117
118
Part 3
Part
119
120
Chapter 8.
121
8.1 Introduction
Enterprise security is crucial to the success of any organization. System z has a long-standing reputation for being an extremely secure and reliable system. It features a security-rich holistic design in which security-relevant controls are enforced on all levels of the computer including the processor hardware level, the operating system level, and the application level. In this environment, cryptography is the most suitable technique for handling the many security concerns that enterprises face today, including impersonation or having sensitive data stolen or compromised. It is assumed, in the following chapters, that readers are already familiar with cryptographic techniques and the use of cryptographic algorithms to implement functions such as: Encryption (symmetric or asymmetric encryption) Keys Digital signature Digests and hashing Familiarity with their specific executions, such as padding, cipher chaining and so on, is also assumed. For readers who are unfamiliar with these techniques and concepts, refer to a summary of these topics in Appendix F, Basics of cryptography on page 259. Prior to leveraging System z cryptographic capabilities from Java applications, you must properly configure System z hardware and z/OS software. Appendix A, z/OS integrated hardware cryptography setup details on page 199, explains the steps required to configure the hardware cryptography infrastructure on System z. The appendix includes detailed information about setting up and using proper RACF protections for the hardware cryptography-related z/OS resources. After System z, z/OS, and the Java JVM have been configured to operate the hardware cryptographic devices, Java applications can be written that transparently exploit System z hardware cryptography. However, application developers must thoroughly understand the standard application framework provided by the Java SDK. Java Cryptographic Extension (JCE) is a framework that Java applications can invoke to get cryptographic functions to be performed on data. Chapter 9, Introduction to Java Cryptographic Extension Framework and API on page 125, provides a detailed description of the JCE framework, the related provider concept, and how the JCE framework can be exploited to interact with ICSF and the cryptographic hardware devices CPACF and the Crypto Express2 Coprocessor. Cryptographic keys are required for most cryptographic functions. They are installation assets which must be duly secured and managed. z/OS provides strongly secure cryptographic key management functions that can not only be exploited for cryptographic workloads running on the platform itself, but also make z/OS a central hub in an installation for managing cryptographic keys to be used by other platforms. This topic is addressed in Chapter 11, Java and key management on z/OS on page 157. Subsequent chapters explain how Java applications can interact with the z/OS key management facilities and use the secure keys mechanism implemented in ICSF and the Crypto Express2 Coprocessor. Two use cases are used to provide examples of actual implementations of z/OS Java cryptography. Appendix G, Case study: IBM Encryption Key Manager on page 267 stresses how the Java-based EKM exploits the z/OS key management facilities to support the critical
122
function of providing cryptographic keys to be used to secure data that is backed-up on the IBM TS1120 encrypting tape drives. The second use case, as discussed in Appendix H, Performance case study: IBM Encryption Facility for z/OS OpenPGP support on page 275, addresses the Java-based OpenPGP support for the IBM Encryption Facility for z/OS. Here the focus is on how System z-specific hardware components such as the zAAP specialty engine and the CPACF cryptographic device work together to significantly enhance Java cryptographic performance.
123
124
Chapter 9.
125
The JVM can be set up so that a list of providers will be searched in preference order, to find an implementation of a particular type of object (for example, a Signature object using the DSA algorithm.) The provider search order can also be dynamically altered by a Java application, or the provider can be explicitly specified as a parameter on some of the engine classes. The following example will obtain a signature object for the DSA algorithm from the IBMJCECCA provider. Signature sign = Signature.getInstance("DSA","IBMJCECCA");
An engine class defines the interface for a cryptographic service. This is the API that Java applications will use to access the cryptographic services. For each engine class, there is an abstract Service Provider Interface (SPI) class. This interface class defines the abstract methods that every provider must implement if it is to support that cryptographic service. Therefore, if a provider supports a cryptographic service, it would have had to subclass the SPI for that engine class and provide a concrete implementation of all the abstract methods declared in the SPI. When a Java application needs to use the cryptographic service, it must first invoke the getInstance method for that engine class. The getInstance class will create an instance of that engine class and encapsulate an instance of the corresponding SPI class from the provider that is supplying the concrete implementation of the SPI abstract methods. This
Chapter 9. Introduction to Java Cryptographic Extension Framework and API
127
linkage ensures that the correct provider implementation for the cryptographic service is used whenever methods from that instance of the engine class are invoked.
128
To register a new provider, an entry must be added to specify the provider subclass name and the preference order for that provider. The entry has the following format: security.provider.<n>=<className> Note that n specifies the preference order. 1 is the most preferred provider. className specifies the name of the subclass that is implementing the Provider class. Providers registered via the java.security file are instantiated when the JVM is initialized. The provider settings will be in effect for any JVM that is created using that Java installation configuration. Careful planning may be necessary to ensure that the provider precedence behavior will be as expected. If the first provider in the list supplies every service and algorithm that applications will use, then this provider will always be the one selected, unless the Java application code explicitly specifies another particular provider in the list
129
Security.insertProviderAt(new IBMJCE(), 2); To change the precedence order of an installed provider, you must remove the provider and then reinsert it at the desired precedence order. The removeProvider method is used to remove a provider from the provider list. When a provider is removed from the provider list, all providers lower in precedence to the removed provider will move up one position in precedence order. The following code example can be used to change the precedence order of the IBMJCE provider to position 2: Security.removeProvider("IBMJCE"); Security.insertProviderAt(new IBMJCE(), 2);
Querying providers
Because all providers extend the java.security.Provider class, a Java application has the option of programmatically querying all installed providers and the services that they support. The Java application shown in Figure 9-2 will query all installed providers and display each of them, as well as the services they provide. import java.security.Provider; import java.security.Security; public class Example3 { public static void main(String[] args) { Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { System.out.println(providers[i].getInfo()); } } }
Figure 9-2 Querying providers
130
9.5.1 IBMJCE
The IBMJCE provider is a multiplatform software implementation of the JCE. This provider should be used if platform compatibility is a concern for the specific Java application to be run on z/OS.
131
The IBMJCE provider supports the following algorithms: Cipher RSA encryption/decryption Blowfish DES Triple DES Mars RC2 RC4 Seal PBE with MD2 and DES PBE with MD2 and Triple DES PBE with MD2 and RC2 PBE with MD5 and DES PBE with MD5 and Triple DES PBE with MD5 and RC2 PBE with SHA1 and DES PBE with SHA1 and TripleDES PBE with SHA1 and RC2 PBE with SHA1 and 40-bit RC2 PBE with SHA1 and 128-bit RC2 PBE with SHA1 and 40-bit RC4 PBE with SHA1 and 128-bit RC4 PBE with SHA1 and 2-key Triple DES PBE with SHA1 and 3-key Triple DES
Signature RSA/SHA1, RSA/MD5, RSA/MD2 signatures DSA/SHA1 signature Message Digest SHA1 MD5 MD2 Message Authentication code Hmac/SHA1 Hmac/MD2 Hmac/MD5
Key agreement algorithms DiffieHellman Random number generation Secure Random It also supports the following keystores: JCEKS JKS PKCS12KS
9.5.2 IBMJCE4578
The IBMJCE4578 provider is specific to z/OS and exploits cryptographic hardware. The IBMJCE4578 provider has been replaced with the compatible IBMJCECCA provider. For
132
more details about the IBMJCECCA provider, refer to 9.6, The IBM providers - IBMJCECCA on page 136.
133
SHA1withRSA Key Agreement DiffieHellman (This is a non-approved algorithm, but is allowed for use in exchanging keys.) Key(pair) generation DSA AES TripleDES HmacSHA1 RSA DiffieHellman
Message authentication code (MAC) HmacSHA1 Message digest SHA-1 SHA-256 SHA-384 SHA-512 MD5 (This is a non-approved algorithm. It can only be used if the user is implementing the TLS protocol for Secure Sockets. Any other use will cause the application to be non-compliant to FIPS 140-2 Level 1.)
Algorithm parameter generator DiffieHellman DSA Algorithm parameter AES DiffieHellman TripleDES DSA
Key Factory DiffieHellman DSA RSA Secret Key Factory AES TripleDES Certificates X.509 Random number generation IBMSecureRandom which is also known as FIPSPRNG The following are the supported cipher suites for the IBM JSSE FIPS provider. This provider supports only the TLS protocol. SSL_RSA_WITH_DES_CBC_SHA SSL_RSA_FIPS_WITH_DES_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA
134
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_AES_128_CBC_SHA SSL_RSA_WITH_AES_256_CBC_SHA SSL_DHE_RSA_WITH_AES_128_CBC_SHA SSL_DHE_RSA_WITH_AES_256_CBC_SHA SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_AES_128_CBC_SHA SSL_DHE_DSS_WITH_AES_256_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA SSL_DH_anon_WITH_AES_128_CBC_SHA SSL_DH_anon_WITH_AES_256_CBC_SHA SSL_DH_anon_WITH_DES_CBC_SHA SSL_DH_anon_WITH_3DES_EDE_CBC_SHA SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
9.5.5 IBMJAAS
The Java Authentication and Authorization Service (IBMJAAS) provider allows you to: Authenticate users - That is, reliably and securely validate the identity of the user who is executing the Java code Authorization - That is, ensure that an authenticated user has the permissions to do the action that is being requested JAAS gives Java the capability to provide access controls based on the identity of an authenticated user. This capability complements the imbedded Java capability to provide access controls based on the executing code's code source and code signer. The IBMJAAS provider is multiplatform and provides the same functionality on all supported platforms. The IBMJAAS reference guide is available at the following Web site: http://www.ibm.com/developerworks/java/jdk/security/60/secguides/JaasDocs/api.html
9.5.6 IBMJGSS
The IBMJGSS provider is a Java-implemented Generic Security Service Application Programming Interface (GSSAPI) framework with Kerberos V5 as the underlying default security mechanism. GSSAPI is a standardized abstract interface under which can be plugged different security mechanisms based on security technologies that use either symmetric or asymmetric cryptographic algorithms. GSSAPI shields secure applications from the complexities and peculiarities of the different underlying security mechanisms. GSSAPI provides identity and message origin authentication, message integrity, and message confidentiality. The IBMJGSS user's guide is available at the following Web site: http://www.ibm.com/developerworks/java/jdk/security/60/secguides/jgssDocs/users_gu ide.jgss.ibm.html
135
The IBMJGSS application developer's guide is available at the following Web site: http://www.ibm.com/developerworks/java/jdk/security/60/secguides/jgssDocs/develope rs_guide.jgss.ibm.html
9.5.7 IBMSASL
The IBMSASL provider provides an implementation of the Simple Authentication and Security Layer (SASL) framework that the Java SASL APIs can use. SASL is an Internet standard (RFC 2222) that specifies a protocol for authentication and optional establishment of a security layer between client and server applications. SASL defines how authentication data is to be exchanged, but does not specify the contents of that data. SASL is a framework into which specific authentication mechanisms that specify the contents and semantics of the authentication data can fit. The IBMSASL provider guide is available at the following Web site: http://www.ibm.com/developerworks/java/jdk/security/60/
136
The IBMJCECCA provider interfaces with the hardware cryptographic devices through the Integrated Cryptographic Service Facility (ICSF) component of z/OS. For more information about ICSF, refer to Appendix A, z/OS integrated hardware cryptography setup details on page 199. The IBMJCECCA provider uses a Java Native Interface (JNI) module to interface with the ICSF API. If the ICSF API returns a non-zero return code, the Java service will throw an exception that will contain the ICSF return and reason code. The IBMJCECCA provider supports the following: Signature algorithms SHA1withDSA* SHA1withRSA MD5withRSA MD2withRSA DES TripleDES AES PBEWithMD2AndDES PBEWithMD2AndTripleDES PBEWithMD5AndDES PBEWithMD5AndTripleDES PBEWithSHA1AndDES PBEWithSHA1AndTripleDES PBEWithSHAAnd2KeyTripleDES PBEWithSHAAnd3KeyTripleDES RSA
Cipher algorithms
Message authentication code (MAC) HmacSHA1 HmacMD2 HmacMD5 Key (pair) generator DSA (supported on machines prior to the IBM 2084 eServer zSeries 900 only) DES TripleDES HmacMD2 HmacMD5 HmacSHA1 RSA
Message digest MD2 MD5 SHA-1 Algorithm parameter generator DSA (supported on machines prior to the IBM 2084 eServer zSeries 900 only) Algorithm parameter DES TripleDES DSA (supported on machines prior to the IBM 2084 eServer zSeries 900 only)
Chapter 9. Introduction to Java Cryptographic Extension Framework and API
137
AES PBEwithMD5AndDES Key factory DSA (Only supported on machines prior to the IBM 2084 eServer zSeries 900) RSA Secret key factory DES TripleDES AES PKCS5Key PBKDF1 PBKDF2(PKCS5DerivedKey)
Certificate X.509 Secure random IBMSecureRandom The IBMJCECCA also supports the following keystores JCECCAKS JCECCARACFKS JCA4758KS
Certificate objects to store certificates Key objects to store keys (which can be public, private, or secret keys) A token can contain multiple data, certificate, or key objects. The objects are classified according to their lifetime and visibility. Token objects are visible to all applications connected to the token (a session is defined as the connection that an application makes to a token), provided that the applications have sufficient permission and the objects are persistent on the token, even after the sessions are closed or the token is removed from the card reader. The session objects are temporary in nature. When a session is closed, all session objects created by that session are automatically deleted. Session objects are only visible to the application that created them. Token and session objects can also be assigned attributes. Attributes give specific properties to the objects, such as whether their contents are of a public or private nature.
139
Only the configuration of the Java environment is discussed in this chapter. Configuration of ICSF and RACF are discussed in Appendix A, z/OS integrated hardware cryptography setup details on page 199. You can also refer to other relevant IBM documentation, including: z/OS Cryptographic Services Integrated Cryptographic Service Facility Writing PKCS #11 Applications, SA23-2231 The IBM Redbooks publication System z Cryptographic Services and z/OS PKI Services, SG24-7470 Configuration changes to the Java environment for the IBMPKCS11Impl provider entail adding the IBMPKCS11Impl provider to the list of security providers in the java.security file and creating an IBMPKCS11Impl configuration file. An IBMPKCS11Impl configuration file contains the following information: name - a string to append to IBMPKCS11Impl- to create the provider's instance name. For example, using the configuration file in the following example, a Java application will use the following String value to reference this provider: IBMPKCS11Impl-ATMAPP library - the HFS full path name of the PKCS#11 DLL library. For 31-bit addressing mode, this will be /usr/lpp/pkcs11/lib/csnpcapi.so. For 64-bit addressing mode, this will be /usr/lpp/pkcs11/lib/csnpca64.so. description - a string to describe the configuration. tokenLabel - the name of the token. Access to the token and the objects it contains is controlled via profiles in the RACF CRYPTOZ class of resources. Example 9-1 shows a sample IBMPKCS11Impl configuration. It assumes that the name of the file is atmapp.cfg.
Example 9-1 IBMPKCS11Impl configuration file
name = ATMAPP library= /usr/lpp/pkcs11/lib/csnpcapi.so description=ATM Application tokenLabel=CUSTOMER1 This IBMPKCS11Impl configuration file must reside in an HFS directory. Before using the provider, it must be initialized. The following methods can be used to initialize the provider: The provider can be specified in the java.security file. As part of specifying the IBMPKCS11Impl provider, the configuration file is also specified, as shown in Example 9-2.
Example 9-2 The java.security file with the IBMPKCS11Impl provider
140
The provider can be programmatically initialized with the Init method: com.ibm.crypto.pkcs11impl.provider.IBMPKCS11Impl.Init(String, char[]) The String parameter is the full directory path and name of the configuration file. The char[] parameter is the password and is ignored. The provider can be programmatically initialized when the provider object instance is created com.ibm.crypto.pkcs11impl.provider.IBMPKCS11Impl(String fullFileName) The String parameter is the name of the IBMPKCS11Impl configuration file. The recommendation is to initialize the provider programmatically via the Init method or when the provider object is created. Updating the java.security file sets the provider for all instances of the JVM. A PKCS#11 session is created when a JVM loads and initializes the IBMPKCS11Impl provider. Note the following points in regard to the PKCS#11 support on z/OS: Only clear keys are supported in the ICSF TKDS. There is no Java PKCS#11 secure key support. If secure key support is needed, the user should consider using the IBMJCECCA provider instead. Creation of a new empty token is required before a Java IBMPKCS11Impl application can be run. Token creation can be done using the RACF RACDCERT command or the System SSL gskkyman UNIX program. Refer to z/OS Security Server RACF Command Language Reference, SA22-7687, and z/OS Security Server RACF Security Administrator's Guide, SA22-7683, for information about the RACDCERT command. Refer to z/OS Cryptographic Services System Secure Sockets Layer Programming, SC24-5901, for information about gskkyman. In addition, a token can be created using ICSF ISPF panels for PKCS#11. Refer to z/OS Cryptographic Services Integrated Cryptographic Services Facility Administrator's Guide, SA22-7521, for more information about this topic. Support is not available in the IBMPKCS11Impl provider for PKCS#11 hardware exploitation by the IBMJSSE2 provider. If hardware cryptographic devices exploitation by the IBMJSSE2 provider is needed, the user should consider using the IBMJCECCA provider instead. If a com.ibm.pkcs11.PKCS11Exception is thrown that includes the string Vendor defined error, the code displayed is an ICSF return code and reason code. It is in the format 0x'pxxxyyyy' where xxx is the ICSF return code and yyyy is the ICSF reason code (the p value can be ignored). To determine the meaning of these codes, refer to z/OS Cryptographic Services ICSF Application Programmer's Guide, SA22-7522, Appendix A. If a java.security.NoSuchAlgorithmException is thrown when running an IBMPKCS11Impl application and the algorithm is one that is supported, this may be due to the z/OS hardware cryptography not being in operation in the system. We strongly recommend that a call to com.ibm.crypto.pkcs11impl.provider.IBMPKCS11Impl.removeSession() method be included at the end of every Java IBMPKCS11Impl application to remove and close the session that is currently associated with the provider. This avoids a build-up of a large
141
amount of session objects in the TDKS because all the session objects created by that session are destroyed when it is closed. Calling the com.ibm.crypto.pkcs11impl.provider.IBMPKCS11Impl.logout() method is not required because it has no effect on the PKCS#11 session state in the z/OS implementation. Logout and login are not needed (and actually will be null operations, if invoked) because access to the token and the objects it contains is controlled by RACF profiles only. When an IBMPKCS11Impl key is stored into the PKCS11IMPLKS key store using the KeyStore.setKeyEntry method, the key object is copied to the TKDS and the token attribute is set to true. The IBMPKCS11Impl key passed into setKeyEntry is no longer valid. A call to the KeyStore.getKey method must be done to retrieve the valid key object from the TKDS. It is strongly recommended that separate tokens be used if the Java PKCS#11 application runs in multiple JVMs or processes and adds and deletes objects in the TKDS. For example, suppose the Java PKCS#11 application on JVM#1 creates a new RSA public and private key pair using TOKEN1. It then does a KeyStore.load, followed by a Keystore.setKeyEntry for the new RSA private key, followed by a Keystore.deleteEntry of that RSA private key. On JVM #2, if the Java PKCS11 application does a Keystore.load also using TOKEN1 prior to the KeyStore.deleteEntry being done in JVM #1, unpredictable results may occur. When using the TokenLabel specification in the IBMPKCS11Impl configuration file, better performance is achieved for the IBMPKCS11Impl instance initialization when the CRYPTOZ profiles qualifiers match, or tend to be specific to, the TokenLabel value. For example, assume that TokenLabel specifies DAN1 and we define CRYTPOZ profiles defined as SO.DAN* and USER.DAN* (these are generic RACF profiles granting Security Officer and User privileges to tokens with a label name beginning with DAN) to give permission to the user DAN. The IBMPKCS11Impl instance initialization will complete faster in such a case than if we had defined the CRYPTOZ profiles as SO.* and USER.*. Tracing for the IBMPKCS11Impl provider can be enabled by adding the following line to the Java command: -Djava.security.auth.debug=all Details for enabling the z/OS PKCS#11 DLL are described in z/OS Cryptographic Services ICSF Writing PKCS11#11 Applications, SA23-2231. Tracing for the Java PKCS#11 JNI layer for z/OS can be enabled by issuing the command: export HJV_PKCS11_TRACE=ON Note that tracing should only be enabled when requested by an IBM service representative due to the volume of output that might be produced.
RSA/SSL/NoPadding RSAforSSL DES/CBC/NoPadding DES/CBC/Pad DES/ECB/NoPadding DESede/CBC/NoPadding DESede/CBC/Pad DESede/ECB/NoPadding AES/CBC/NoPadding AES/CBC/Pad AES/ECB/NoPadding
KeyPairGenerator RSA KeyGenerator DES DESede AES MessageDigest MD5 SHA1 SHA-256 KeyFactory RSA SecretKeyFactory DES DESede AES KeyStore PKCS11IMPLKS
143
144
10
Chapter 10.
145
10.1.1 SecureRandom
The random number generation as provided in Java is, in fact, not fully random. Instead, pseudo random number generation techniques are used. Knowledge of what is the initialization value provided to a pseudo random number generator (the seed) eventually allows identical numbers to be generated. Because one of the main purposes of random number generation is the creation of unpredictable secret keys values, it is of paramount importance to have access to a pseudo random number generation facility that introduces the proper level of entropy in the generation process. The SecureRandom engine class provided in Java is such a strong pseudo random number generator. Note: The IBMJCECCA provider exploits the generation of true random numbers as implemented in the Crypto Express2 Coprocessor. This capability is provided to applications that invoke the SecureRandom class. A SecureRandom object is created as follows: SecureRandom random = SecureRandom.getInstance("IBMSecureRandom"); where the IBM implementation SecureRandom is specified. To exploit the hardware support for random number generation, you must specify: SecureRandom random = SecureRandom.getInstance("IBMSecureRandom", IBMJCECCA); The generation of random numbers can the be invoked as follows: byte[] randomBytes = new byte[16]; random.nextBytes(bytes);
146
Note that the SecureRandom object does not need to be provided with an initialization value before being invoked.
10.1.2 MessageDigest
MessageDigest, which is part of the one-way hash algorithms, is used for generating checksums (also called fingerprints) to verify message integrity. Hash algorithms are also commonly used in the generation of digital signatures (see Digital signatures on page 263, for an explanation of digital signatures). As with the other engine classes, MessageDigest objects are obtained using the getInstance() method: MessageDigest sha1Digest = MessageDigest.getInstance(SHA-1); A MessageDigest does not need specific initialization data and comes ready to hash the input message. All parts of the message that need to be hashed are passed through the object using the update() method: String messagePart1 = Secret 1; String messagePart2 = Secret 2; sha1Digest.update(messagePart1.getBytes()); sha1Digest.update(messagePart2.getBytes()); etc.. After all the data has been passed through the object, the final result can be obtained by a call to digest(): byte[] theDigest = messageDigest.digest(); As long as the message parts are passed through the object in the same order, it does not make any difference how long each part is on the update(); the resulting digest value would end up being the same. Note: The update() method provided by the MessageDigest, Signature, and Cipher classes operates on byte arrays. In the preceding example, the strings messagePart1 and messagePart2 are converted to bytes using the getBytes() method. This triggers an implicit codepage conversion to the systems default character set. Use care to ensure that the expected codepages are in use. If needed, it is still possible to specify a specific codepage on the getBytes() method like: String message = Some text byte[] messageUTF8bytes = message.getBytes(UTF-8) // Convert to UTF-8 String message2 = new String(messageUTF8bytes, UTF-8); // Converting back
10.1.3 Signature
The Signature engine class is used for generating digital signatures. See Digital signatures on page 263 for an explanation of digital signatures. The Signature objects are generated using the getInstance() method as follows: Signature signature = Signature.getInstance("MD5withRSA"); 147
In this case the signature is based on the MD5 message digest combined with the RSA asymmetric algorithm. Before use, the signature object is initialized with the signers private key: signature.initSign(privateRsaKey); After this, the complete message to sign is passed through the object: signature.update(messagePart1.getBytes()); signature.update(messagePart2.getBytes()); etc. After all the required data has been passed though the signature object, the actual signature is created using: byte[] messageSignature = signature.sign(); If somebody wants to verify the signature, it can be done using the same signature object initialized for verification, using the signers public key: signature.initVerify(publicRsaKey); signature.update(messagePart1.getBytes()); signature.update(messagePart2.getBytes()); etc. After passing the complete signed message through the signature object, the verify() method is called, along with the original signature, to test if the signature is verified: boolean validSignature = signature.verify(messageSignature);
10.1.4 Cipher
The Cipher engine class is the class that implements encryption and decryption of data. The Cipher object can be instantiated by just specifying the encryption algorithm on the getInstance() call, as follows: Cipher aesCipher = Cipher.getInstance("AES) However, additional parameters are often needed for specifying additional properties of the encryption algorithm. The following statement is the instantiation of an AES cipher with cipher block-chaining (CBC) and the padding scheme PKCS5Padding: Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "IBMJCECCA"); Note: Even though a provider, in essence, supports a specific encryption algorithm, it might not support all possible combinations of such additional options. After a cipher has been instantiated, it needs to be initialized for one of the following four modes: ENCRYPT_MODE DECRYPT_MODE WRAP_MODE UNWRAP_MODE This is used for encryption. This is used for decryption. This is used when encrypting other keys (for example, session keys with hybrid encryption). This is used for decrypting encrypted keys.
Depending on the kind of algorithm chosen, several variations of the initialization method may be used. 148
Java Security on z/OS - The Complete View
As an example, the initialization of the AES cipher can be: aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, ivSpec); where aesKey is a symmetric key and ivSpec is a random initialization vector (see Encryption modes on page 261 for an explanation of the initialization vector). After initialization, the cipher can be used for encryption or decryption using the update() and doFinal() methods: byte[] encryptedData1 = aesCipher.update(dataToEncypt1); byte[] encryptedData2 = aesCipher.update(dataToEncypt2); ... byte[] encryptedDataN = aesCipher.doFinal(dataToEncyptN); where doFinal() is used with the last block of data to be processed. This ensures that proper padding is performed, if required.
10.1.5 KeyGenerator
KeyGenerator is used for generating new random symmetric keys. Like all other engine classes, a KeyGenerator object is instantiated through the getInstance() method: KeyGenerator generator = KeyGenerator.getInstance("AES", "IBMJCECCA"); When initializing the generator, the key size, in bits, is specified. It is also possible to provide a SecureRandom generator that should be used when generating keys: generator.init(256, random); After initialization, a key is generated using the generateKey() method: SecretKey aesKey = generator.generateKey();
10.1.6 KeyPairGenerator
KeyPairGenerator is similar to KeyGenerator, but is used for asymmetric algorithm keys and therefore produces key pairs. A KeyPairGenerator is instantiated as follows: KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA","IBMJCECCA"); It is initialized in a similar way to KeyGenerator: generator.initialize(2048, random); A key pair is generated with: KeyPair rsaKeyPair = generator.generateKeyPair(); Each key can then be obtained as a private or public key: PublicKey publicRsaKey = rsaKeyPair.getPublic(); PrivateKey privateRsaKey = rsaKeyPair.getPrivate();
149
Cryptographic service providers on page 128, for an explanation of providers and the providers list. There is nothing else needed, beside proper specification of the providers, in order to run these examples. All encryption keys used in these examples are generated when needed by the program, instead of using a key management scheme that would involve using keystores. For more information about keystores, refer to Chapter 11, Java and key management on z/OS on page 157. The examples provided here cover the execution of the following cryptographic functions: Random number generation (SecureRandom) Message Digest Signature Symmetric encryption Asymmetric encryption
import java.security.SecureRandom; import java.util.Random; public class IBMSecureRandom1 { public static void main(String[] args) { try { // get a real random generator SecureRandom reallyRandom = SecureRandom.getInstance("IBMSecureRandom", "IBMJCECCA"); System.out.print("Some really random numbers: "); for (int i = 0; i < 3; i++) { System.out.print(reallyRandom.nextInt() + " "); } System.out.println(); // make a pseudo random generator seeded by the real random generator Random pseudoRandom = new Random(reallyRandom.nextLong()); System.out.print("Some pseudo random numbers: "); for (int i = 0; i < 3; i++) { System.out.print(pseudoRandom.nextInt() + " "); } System.out.println(); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } }
150
Example 10-1 on page 150 yields the following output: Some really random numbers: -1057432571 -302680133 97550332 Some pseudo random numbers: 826547108 74718224 1007937281
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MessageDigest1 { public static void doDigest(String digestName, String message) { try { MessageDigest messageDigest = MessageDigest.getInstance(digestName); messageDigest.update(message.getBytes()); byte[] digest = messageDigest.digest(); System.out.println("Name: " + digestName + "\t" + "Provider: " + messageDigest.getProvider() + "\t" + "Digest len: " + digest.length + " bytes\t" + "\n Digest (hex): " + toHex(digest)); } catch (NoSuchAlgorithmException e) { System.out.println(digestName + " not supported by any providers"); e.printStackTrace(); } } public static String toHex(byte[] bytes) { final String hexDigits = "0123456789ABCDEF"; char[] res = new char[bytes.length * 2]; for (int i res[(i * res[(i * } return new } public static void main(String[] args) { String message = "This is the string to digest ..."; System.out.println("Digesting the message: <" + message + ">"); = 0; i < bytes.length; i++) { 2) ] = hexDigits.charAt((bytes[i] & 0xff) / 16); 2) + 1] = hexDigits.charAt((bytes[i] & 0xff) % 16); String(res);
151
doDigest("MD2", message); doDigest("MD5", message); doDigest("SHA-1", message); doDigest("SHA-256", message); doDigest("SHA-384", message); doDigest("SHA-512", message); } }
When running this example with a provider list with IBMJCECCA in the first position and IBMJCE in the second one, the program produced the following output. Because the IBMJCECCA provider does not implement, as of the time of writing, the SHA-256, SHA-384, and SHA-512 algorithms, these are provided by the IBMJCE provider via a pure software implementation.
Digesting the message: <This is the string to digest ...> Name: MD2 Name: MD5 Name: SHA-1 Provider: IBMJCECCA version 1.2 Digest len: 16 bytes Provider: IBMJCECCA version 1.2 Digest len: 16 bytes Provider: IBMJCECCA version 1.2 Digest len: 20 bytes Digest len: 32 bytes Digest (hex): BACAAA6DAA0BC8BE463EB53E22A4F6EA Digest (hex): 26B2276F5EC4D5CAC6410E78C8878D00 Digest (hex): 0B71DA7625AA8F69D02C3F86E03606C7FA5C56AF Name: SHA-256 Provider: IBMJCE version 1.2 Digest (hex): 05DE3A8E1BBA281B6BA826B87D8F5938A4985EB389090ECAABE8EBB9E3D82B 33 Name: SHA-384 Provider: IBMJCE version 1.2 Digest len: 48 bytes Digest (hex): 2687CBDAB89C9BC2CD785700D278D3C4C6202C0A6014D6D1C618F2CAE0979E 13828850A66FCD7AD356F15BD02A9775C6 Name: SHA-512 Provider: IBMJCE version 1.2 Digest len: 64 bytes Digest (hex): F387E7A79684CD085D50B437D11121C7EFD6B6B092C2C50AFBBF9D27FCF02F E997F7BEFAC753992B4CA2AD480CFECAF665E5C319998A6D46D5F4F4E62DB3E60E
10.2.3 Signature
Example 10-3 demonstrates how to create a digital signature for a message, using a private key, and then shows how to verify the created signature by using the corresponding public key. Lastly, it shows a verification that fails because of an altered message.
Example 10-3 Digital signature generation.
public static byte[] makeSignature(String message, PrivateKey privateRsaKey) throws Exception { Signature signature = Signature.getInstance("MD5withRSA", "IBMJCECCA"); signature.initSign(privateRsaKey); signature.update(message.getBytes()); byte[] messageSignature = signature.sign(); return messageSignature; } public static boolean verifySignature(byte[] messageSignature, String message, PublicKey publicRsaKey) throws Exception { Signature signature = Signature.getInstance("MD5withRSA", "IBMJCECCA"); signature.initVerify(publicRsaKey); signature.update(message.getBytes()); boolean validSignature = signature.verify(messageSignature); if (validSignature) { System.out.println("Signature is valid with message: " + message); } else { System.out.println("Signature is NOT valid with message: " + message); } return validSignature; } public static void main(String[] args) { try { SecureRandom rnd = SecureRandom.getInstance("IBMSecureRandom", "IBMJCECCA"); KeyPairGenerator generator =KeyPairGenerator.getInstance("RSA","IBMJCECCA"); // make random RSA keys with KeyPairGenerator generator.initialize(2048, rnd); KeyPair rsaKeyPair = generator.generateKeyPair(); PublicKey publicRsaKey = rsaKeyPair.getPublic(); PrivateKey privateRsaKey = rsaKeyPair.getPrivate(); String message = "Please send $100"; String fakeMessage = "Please send $500"; System.out.println("Making signature on message: " + message); byte[] messageSignature = makeSignature(message, privateRsaKey); System.out.println("Signature created. Signature length: " + messageSignature.length + " bytes"); System.out.println("Verifying signatures on messages"); verifySignature(messageSignature, message, publicRsaKey); verifySignature(messageSignature, fakeMessage, publicRsaKey); } catch (Exception e) {
153
Example 10-3 on page 152 yields the following output: Making signature on message: Please send $100 Signature created. Signature length: 256 bytes Verifying signatures on messages Signature is valid with message: Please send $100 Signature is NOT valid with message: Please send $500
import java.security.SecureRandom; import import import import javax.crypto.Cipher; javax.crypto.KeyGenerator; javax.crypto.SecretKey; javax.crypto.spec.IvParameterSpec;
public class Symmetric1 { public static void main(String[] args) { try { SecureRandom rnd = SecureRandom.getInstance("IBMSecureRandom", "IBMJCECCA"); KeyGenerator generator = KeyGenerator.getInstance("AES", "IBMJCECCA"); Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "IBMJCECCA"); // make random AES key with KeyGenerator generator.init(256, rnd); SecretKey aesKey = generator.generateKey(); // generate a random initialization vectore byte[] ivData = new byte[16]; rnd.nextBytes(ivData); IvParameterSpec ivSpec = new IvParameterSpec(ivData); String secretMessage = "This is the secret"; 154
Java Security on z/OS - The Complete View
System.out.println("Clear text: " + secretMessage); // init cipher for encrypt & do the encrypt aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, ivSpec); byte[] encryptedData = aesCipher.doFinal(secretMessage.getBytes()); // print encrypted data System.out.print("Encrypted: "); for (int i = 0; i < encryptedData.length; i++) { System.out.print(encryptedData[i] + " "); } System.out.println(); // init cipher for decrypt & do the decrypt aesCipher.init(Cipher.DECRYPT_MODE, aesKey, ivSpec); String decryptedMessage = new String(aesCipher.doFinal(encryptedData)); System.out.println("Decrypted: " + decryptedMessage); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } }
The program produces the output shown below. The 18-byte original clear text message ends up being 32 bytes of encrypted data, because padding was implicitly performed to meet the AES 256 block length requirement. Clear text: This is the secret Encrypted: 31 57 83 -19 -94 71 33 53 60 52 -69 -19 -100 13 38 -61 -92 -100 6 -27 -72 43 -55 82 -115 78 -106 71 -52 44 -61 107 Decrypted: This is the secret
import java.security.SecureRandom; import javax.crypto.Cipher; public class Asymmetric1 { public static void main(String[] args) { try { SecureRandom rnd = SecureRandom.getInstance("IBMSecureRandom", "IBMJCECCA"); KeyPairGenerator generator =KeyPairGenerator.getInstance("RSA","IBMJCECCA"); Cipher rsaCipher = Cipher.getInstance("RSA", "IBMJCECCA"); // make random RSA keys with KeyPairGenerator generator.initialize(2048, rnd); KeyPair rsaKeyPair = generator.generateKeyPair(); PublicKey publicRsaKey = rsaKeyPair.getPublic(); PrivateKey privateRsaKey = rsaKeyPair.getPrivate(); String secretMessage = "This is the secret"; System.out.println("Clear text: " + secretMessage); // init cipher for encrypt & do the encrypt rsaCipher.init(Cipher.ENCRYPT_MODE, publicRsaKey); byte[] encryptedData = rsaCipher.doFinal(secretMessage.getBytes()); System.out.println("Encrypted len: " + encryptedData.length + " bytes"); // init cipher for decrypt & do the decrypt rsaCipher.init(Cipher.DECRYPT_MODE, privateRsaKey); String decryptedMessage = new String(rsaCipher.doFinal(encryptedData)); System.out.println("Decrypted: " + decryptedMessage); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } }
Example 10-5 on page 155 produces the following output. Note that even through the clear text is only 18 byte long, the encrypted data ends up being 256 bytes in length. This is due to the RSA key size of 2048 bits that we use and which requires a data block size of 256 bytes. Clear text: This is the secret Encrypted len: 256 bytes Decrypted: This is the secret
156
11
Chapter 11.
157
11.1 Introduction
As previously mentioned, cryptographic systems provide support to achieve the following security services in a very robust and reliable manner: Authentication - the capability of verifying the trustworthiness of a presented identity. Data confidentiality - making the meaning of data appear only to authorized users. Data integrity - providing the capability of detecting unwanted modification of data. Cryptographic key material is essential for any cryptographic system intended to be used as a support to these services. As it stands today, many cryptographic algorithms in use in the industry are publicly known; that is, the processes they trigger during their execution are freely documented. However, how these processes are actually executed and chained depends on the value of the key provided, along with the data, as an input to the algorithm. As a result the strength of a cryptography-based modification of data, when facing attempts to retrieve original data or misuse the modification, is mainly quantified by the strength of the cryptographic key used when performing the modification. The metric commonly used to quantify the strength of a key and algorithm is the mean time for the key to be correctly guessed in a brute force attack. In this context, mathematical principles and the use of random numbers are the foundation for ensuring the generation of strong keys. Note that there might be several inhibitors to the generation and use of very strong cryptographic keys, such as laws and regulations or unacceptable duration of the cryptographic process time. The execution of cryptographic algorithms by specialized hardware devices provides most of the time that the required acceleration to help solving the execution time concerns, if any. Because cryptographic system strength is quantifiable via the properties of the cryptographic keys, the real burden of ensuring the effectiveness of such a system's ability to provide these services becomes how to securely manage the cryptographic keys intended to be used. z/OS has a long tradition of providing facilities to securely manage cryptographic keys in an enterprise. This section discusses how Java and z/OS can make Java-based cryptographic services and their exploiting applications leverage the z/OS strong key management services. Before moving forward, however, it is important to highlight how keys help provide the services described in the introduction, and to review key management concepts.
158
A cryptographic key is a sequence of bytes of pre-determined length that serves as input to cryptographic functions. The keys today can be classified in two categories, depending on the algorithms they are used with: Asymmetric keys are pairs of mathematically bound keys that work in conjunction to perform an associated cryptographic function. For instance, one key can encrypt and the other can decrypt. The most important point regarding asymmetric keys is that if a cryptographic function such as encryption is performed using one key in the pair, then the other key in the pair is the only sequence of bytes that can be used as a key to perform the associated function (decryption, in this example). Generally, one key of the pair is designated as the public key and can be freely distributed. The other key of the pair is designated as the private key and is securely kept secret by the entity that owns the pair. Symmetric key refers to a single secret key that is used to perform both encryption and decryption. Because different parties are expected to be involved in the encryption and decryption processes, the key must be exchanged securely between these parties and also securely kept secret by its users. Digital certificates are used in the context of asymmetric cryptography as a means to: Exchange the public key material they contain. Cryptographically bind information such as the owning entity name (referred to as a subjects or principals name) or what the key material should be used for, to the specific public key material contained in the certificate. Note that this cryptographic binding is actually the foundation on which trust is established between parties exchanging digital certificates.
Authentication
Authentication uses asymmetric keys with a simple encryption/decryption process or with what is called a digital signature process. The entity seeking authentication digitally signs or encrypts data using its private key. The verifying entity uses the public key of the entity seeking authentication to perform the authentication. Analogous to a person signing a legal document, digital signatures establish a form of non-repudiation by cryptographically binding the owner of an asymmetric key pair to the data being signed. In essence, the owner of the key pair cannot repudiate possession and access to data. In return, the signer can be assured that any modification to the data after they have been signed will be detected. The act of signing data requires using the private key of the signer(s). The signature can then be verified by others using the corresponding public key of the signer(s). Securing the private key of a key pair is therefore extremely important. Because the only instance of the private key is available exclusively to its owner, it is the basis for authenticating the owners identity.
Data confidentiality
Asymmetric encryption requires more processing power than symmetric encryption. As a result, cryptographic systems that must be scalable and must meet transaction rate requirements typically do not perform their encryption using asymmetric algorithms. They rely instead on symmetric algorithms to achieve their performance objectives when encrypting or decrypting data.
159
Data integrity
Cryptographic systems can be used as the underlying mechanism for verifying the integrity of data. Data integrity can be achieved using the so-called secure hash and modification detection code algorithms. Note that these algorithms do not use secret keys. Digital signature is another method, although more sophisticated, of insuring data integrity. Digital signature not only establishes the integrity of data, but also provides an unforgeable proof of who originated the signed data (to the extent that the signers private key is not compromised). Note that detection of unauthorized modification of data, unintentional or malevolent, as a result of data integrity checking is not a preventative measure. Proper access control to the data remains crucial to achieving data integrity.
160
Key This is the top level interface for all keys. Many of the JCE objects that perform cryptographic function (for instance, Cipher) require key implementations as parameters. All Java key objects have at least three characteristics: Algorithm Encoded Form Format
Sun Javadoc URL http://java.sun.com/javase/6/docs/api/java/security/Key.html KeySpec A key specification contains information about a key. For example, an implementation of this interface is used to describe key material managed by ICSF, such as keys stored in the PKDS. Sun Javadoc URL: http://java.sun.com/javase/6/docs/api/java/security/spec/KeySpec.html KeyFactory A key factory translates a KeySpec into a key implementation and vice versa. The key implementation can then be used in other JCE classes. Sun Javadoc URL: http://java.sun.com/javase/6/docs/api/java/security/KeyFactory.html PublicKey This is the interface used by all public key implementations. Sun Javadoc URL: http://java.sun.com/javase/6/docs/api/java/security/PublicKey.html PrivateKey This is the interface used by all private key implementations. Sun Javadoc URL: http://java.sun.com/javase/6/docs/api/java/security/PrivateKey.html AlgorithmParameterSpec This is an algorithm specification that contains information about a particular cryptographic algorithm. For example, an implementation of this interface is used to describe different parameters to generate and store an asymmetric key pair that will be stored in the ICSF PKDS. Sun Javadoc URL: http://java.sun.com/javase/6/docs/api/java/security/spec/AlgorithmParameterS pec.html
161
162
JKS
JKS is the Sun original keystore proprietary implementation. This is a z/OS UNIX flat file, Keys in the JKS can be managed using the keytool Java utility. For further information about the keytool utility, refer to: http://www-128.ibm.com/developerworks/java/jdk/security/142/secguides/keytoolDocs/ KeyToolUserGuide-142.html)
JCEKS
JCEKS is the IBM implementation of the Sun keystore concept; that is, the class java.security.KeyStore class. It is implemented in a z/OS UNIX file with the strong protection of the private keys it contains, using Triple-DES password-based encryption. Keys in the JCEKS are managed by the keytool utility, as well. Users can upgrade their keystore of type JKS to the type JCEKS by changing the password of the private key entry in the keystore. Note that after the keystore has been upgraded this way, then it can be used via the IBMJCE provider only.
JCERACFKS
JCERACFKS is backed up by key rings in RACF. RACF key rings are used to aggregate RSA or DSA key pairs and certificates, so that they can be used by an application that owns the
Chapter 11. Java and key management on z/OS
163
key rings. If needed, a RACF key ring can also be shared between several authorized applications. Note that in order to comply with the keystore concept, access to keys kept in the JCERACFKS is still protected with a key entry password and a keystore password. However, these passwords are not used because access to the key ring is under the control of RACF resource profiles set up by the RACF administrator or delegated administrator. The RACF RACDCERT command is the administrative interface used to manage the RACF key rings and the keys and certificates they contain. The certificates and key management in RACF, as well as the RACDCERT command syntax, are discussed in z/OS Security Server RACF Security Administrators Guide, SA22-7683 and z/OS Security Server RACF Command Language Reference, SA22-7687. Starting with z/OS V1R9, the RACF key rings can also be managed by applications using the API provided by the RACF callable service R_datalib. Refer to z/OS Security Server RACF Callable Services, SA22-7691, for a description of the R_datalib RACF callable service. In SDK 6 SR1 and in SDK 5 SR8, the keytool utility has been updated to exploit this facility so that it can write certificates and keys to a RACF key ring.
JCECCAKS
This IBM implementation of a Java keystore is primarily intended to store RSA asymmetric keys that are to be used with the cryptographic hardware coprocessors only. It can also be used to access symmetric keys kept in the ICSF CKDS (that is DES, Triple-DES and AES keys). Keys in the JCECCAKS are managed using the hwkeytool utility. For more information about hwkeytool, refer to: ftp://ftp.software.ibm.com/s390/java/jce4758/hwkeytool.html The RSA asymmetric keys kept in the JCECCAKS can actually exist in three different forms, depending on the options taken when they have been generated. They can be retained keys, PKDS keys, or clear keys, as explained here: Retained keys - The private key of the retained key pair is kept inside the cryptographic coprocessor itself and is never exposed outside of the coprocessor. Important: IBM does not recommend using retained keys with z/OS ICSF. PKDS keys - The RSA key pair is kept in the ICSF Public Key Data Set, with the private key encrypted with the cryptographic coprocessors asymmetric Master Key. 164
Java Security on z/OS - The Complete View
Clear keys - The RSA key pair is packaged as an ICSF key token, without encryption of the private key by the cryptographic coprocessors asymmetric Master Key. When using JCECCAKS, the clear keys reside in the z/OS UNIX Java keystore, with the additional protection of a password. Retained keys and PKDS keys are only pointed at by a label which itself is kept in a keystore. All key information in the JCECCAKS is pointed at by the application using a keystore entry alias. Note that only clear keys are returned to applications in order to be used. PKDS resident keys are directly picked up and sent to the coprocessor by ICSF itself. Retained keys, by definition, already reside inside the coprocessor. Important: Clear key pairs may be exported in a PKCS#12 file. It is not possible to export PKDS or retained key pairs.
JCECCARACFKS
JCECCARACFKS is a variation of JCERACFKS, where the keys still appear as aggregated in a RACF key ring. However, the key ring does not contain the key material itself. Instead, it contains a PKDS label and the actual key is kept, encrypted with the coprocessor Master Key, in the PKDS.
11.3.3 IBMPKCS11Impl
The implementation of PKCS#11 tokens and how they can be exploited by z/OS Java applications is explained in 9.7, The IBM providers - IBMPKCS11Impl on page 138. This section discusses the fact that using the IBMPKCS11Impl provider entails adding the IBMPKCS11Impl provider to the list of security providers in the java.security file and creating a IBMPKCS11Impl configuration file. The IBMPKCS11Impl configuration file contains the following information: name - a string to append to IBMPKCS11Impl- to create the provider's instance name. For example, using the following example configuration file, a Java application will use the following String value to reference this provider: IBMPKCS11Impl-ATMAPP library - the HFS full path name of the PKCS#11 DLL library. For 31-bit mode, this will be /usr/lpp/pkcs11/lib/csnpcapi.so. For 64-bit mode, this will be /usr/lpp/pkcs11/lib/csnpca64.so. description - a string to describe the configuration tokenLabel - the name of the token (access is controlled via profiles in the SAF.CRYPTOZ class) Here is an example of a IBMPKCS11Impl configuration file (assume that the name of the file is atmapp.cfg): name = ATMAPP library= /usr/lpp/pkcs11/lib/csnpcapi.so description=ATM Application tokenLabel=CUSTOMER1 The IBMPKCS11Impl provider supports a keystore type of PKCS11IMPLKS, where the PKCS#11 objects are stored in z/OS PKCS#11 tokens. The z/OS PKCS#11 tokens are
Chapter 11. Java and key management on z/OS
165
actually records in the ICSF TKDS. Access to these keystore objects is done through java.security.KeyStore class. Important: When using the IBMPKCS11Impl provider, certificate objects, private key objects, secret key objects, and so on are stored as z/OS PKCS#11 tokens in the ICSF managed TKDS data set. Access to the tokens is controlled by RACF profiles in the CRYPTOZ class of resources. In addition, ICSF will perform access control checks on underlying PKCS#11 callable services if the CSFSERV class is active in RACF.
CKDS
Information necessary to access the key token in the CKDS is stored in a keystore file in z/OS UNIX. To retrieve or add symmetric keys in CKDS, the KeyStore type set in the KeyStore.getInstance method must be JCECCAKS.
A com.ibm.crypto.hdwrCCA.provider.KeyLabelKeySpec instance with the CKDS label is passed to KeyGenerator to generate the Key instance that can be set in a JCECCAKS keystore. By setting this generated Key instance in a JCECCAKS keystore, a key is generated and set in the CKDS.
166
z/OS-specific repository
Other
PKDS
X.509 certificates. Note: The PKDS itself only contains RSA public and private keys. It does not contain certificates. The certificate itself and the information necessary to access the PKDS key material are stored in a keystore file in z/OS UNIX. KeyStore type set in the KeyStore.getInstance method must be JCECCAKS.
The private key material is kept encrypted with the cryptographic coprocessor. Master Key, and its clear value cannot be retrieved. The PKDS cannot be used if the private key has to be exported out of the keystore.
RETAINED KEY
com.ibm.crypto.hdwrCCA . provider.IBMJCECCA
Only X.509 certificates. Note: The coprocessor only contains the private key material. Certificate and information necessary to access the RETAINED key material are stored in a keystore file in z/OS UNIX. KeyStore type set in the KeyStore.getInstance method must be JCECCAKS.
com.ibm.crypto.hdwrCCA . provider.IBMJCECCA
Only X.509 certificates. Note: ICSF handles the key material itself, not the certificate. Certificate and information necessary to access the CLEAR keys are stored in a keystore file in z/OS UNIX. KeyStore type set in the KeyStore.getInstance method must be JCECCAKS.
The private key material is kept in its clear value (that is, not encrypted with the coprocessor Master Key). This is useful if the key pair must be exported. The PKCS#12 format is then supported for the exportable file.
167
z/OS-specific repository
First Providers in Provider List (order must be as listed) com.ibm.crypto.pkcs11im pl. provider.IBMPKCS11Impl
Other
Only X.509 certificates. The certificates are stored in the ICSF TKDS PKCS#11 tokens. No z/OS UNIX keystore file to maintain KeyStore type set in the KeyStore.getInstance method must be PKCS11IMPLKS.
The IBMPKCS11Impl configuration file path is specified with the provider in the list.
RACF
com.ibm.crypto.provider.I BMJCE
Only X.509 Certificates The certificates and keys are stored in the RACF database and connected to RACF key rings. No z/OS UNIX keystore file maintained. KeyStore type set in the KeyStore.getInstance method must be JCERACFKS.
You must set the InputStream for the KeyStore.load method to a com.ibm.crypto.hdwrCCA.provider.RACFInputStream instance.
You must set the OutputStream for the KeyStore.save method to a com.ibm.crypto.hdwrCCA.provider.RACFOutputStream instance. .
RACF + PKDS
com.ibm.crypto.hdwrCCA . provider.IBMJCECCA
Only X.509 Certificates The certificates are stored in the RACF database and connected to RACF key rings. The related keys are kept in the PKDS with the private key encrypted with the coprocessor Master Key. No z/OS UNIX keystore file maintained. KeyStore type set in the KeyStore.getInstance method must be JCECCARACFKS.
You must set the InputStream for the KeyStore.load method to a com.ibm.crypto.hdwrCCA.provider.RACFInputStream instance.
You must set the OutputStream for the KeyStore.save method to a com.ibm.crypto.hdwrCCA.provider.RACFOutputStream instance.
168
APF Authorization
The Authorized Program Facility of z/OS is discussed in 1.5.1, Authorized programs on page 18. This section explains further the APF authorization requirements for executing Java applications on z/OS. As indicated here, a z/OS Java library requires APF authorization for zAAP dispatching to operate. The ICSF load library hlq.SCSFMOD0 data set must be APF authorized and reside in the LINKLIST.
169
Administrative accesses
The RACF RACDCERT command is the primary administrative interface used to manage the key rings. The command is documented in z/OS Security Server RACF Command Language Reference, SA22-7687, along with the permissions it requires. Refer to Chapter 12, Usage examples - using Java keystores on z/OS on page 179, for usage examples. Accesses to the many functions available with the RACDCERT command are controlled with profiles in the FACILITY class of resources. The profiles names are of the form: IRR.DIGTCERT.<function> where <function> is the function keyword used with the RACDCERT command. Examples of such profiles are: IRR.DIGTCERT.ADD IRR.DIGTCERT.ALTER IRR.DIGTCERT.DELETE IRR.DIGTCERT.LIST IRR.DIGTCERT.ADDRING etc....
Programmatic access
Programmatic access to key rings and certificates is also protected by the IRR.DIGTCERT.<function> profiles in the FACILITY class, where <function> addresses the function invoked by the R_datalib RACF callable service, which is actually the API used for programmatic access to RACF key rings and certificates. Refer to z/OS Security Server RACF Callable Services, SA22-7691, for a description of the R_datalib RACF callable service.
PERMIT IRR.DIGTCERT.LIST CLASS(FACILITY) ID(<KROWNER>) ACC(READ) Alternatively, the installation can elect to use the more granular access control (ring-specific access control) with profiles in the RDATALIB class with a name of the form: <KROWNER>.<KEYRING>.<function> where <KROWNER> is the RACF user ID of the owner of the key ring, <KEYRING> is the name of the RACF key ring, and <function> is the type of access to the key ring. The following setup example uses the RDATALIB profiles for giving read (function LST) and write (function UPD) access to key rings to the <KRACCESSID> userID. RDEFINE RDATALIB <KRWONER>.<KEYRING>.UPD UACC(NONE) RDEFINE RDATALIB <KRWONER>.<KEYRING>.LST UACC(NONE) PERMIT <KRWONER>.<KEYRING>.LST CLASS(RDATALIB) ID(<KRACCESSID>) ACCESS(CONTROL) PERMIT <KRWONER>.<KEYRING>.UPD CLASS(RDATALIB) ID(<KRACCESSID>) ACCESS(CONTROL)
171
strictly control updates to that keystore, so that the trustworthiness of their content is preserved. The Java Secure Socket Extension (IBMJSSE2) providers use a trusted keystore concept to provide SSL/TLS services. Refer to the following site for more information about the way JSSE manages trust: http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
try { String provider = "com.ibm.crypto.hdwrCCA.provider.IBMJCECCA"; Class providerClass = null; providerClass = Class.forName(provider); Provider p = (Provider)providerClass.getConstructor(new Class[]{}).newInstance(new Object[]{}); Security.removeProvider(provider); //ensure provider is moved to the top Security.insertProviderAt(p,1); }catch (Throwable e){ .... }
172
X500Signer issuer; X509CertImpl cert; Date lastDate; X500Name subjectDN,signerDN; //Key pair to encapsulate/self sign cert KeyPair pair = ; // Number of Days Valid long validity = ; try { // SUBJECT of this certificate subjectDN = new X500Name("cn=self sign,ou=ITSO,o=IBM,c=US"); //Certificate's SIGNER DN - since self signed, use subjectDN signerDN = subjectDN; //Issuer is the signer issuer = new X500Signer(Signature.getInstance("SHA1withRSA","IBMJCECCA"),signerDN); //Establish validity period lastDate = new Date (); //1 second = 1 000 milliseconds long todaysDate = lastDate.getTime() / 1000; //todays date in seconds // 1 day = 86400 seconds long validTime = (long)(validity * 86400) ; //valid time in seconds long totalTime = todaysDate + validTime; //today + days valid lastDate.setTime (totalTime * 1000); //Convert back to milliseconds CertificateValidity interval = new CertificateValidity(firstDate,lastDate); X509CertInfo info = new X509CertInfo(); // Add all mandatory attributes // Note here that V1 = 0, V2 = 1, V3 = 2 info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber( (int)(firstDate.getTime()/1000))); AlgorithmId algID = issuer.getAlgorithmId(); info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algID)); info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(subjectDN)); info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublicKey()));
173
// PKDS label of key to reuse String keyLabel = ; // keystore alias that can be reused to retrieve the key object String keystore_alias = ; //The password to the JCECCAKS keystore file where the key will be inserted. String keystore_password = ; KeyLabelKeySpec keyLabelKeySpec = new KeyLabelKeySpec(keyLabel); //KeyFactory used to generate Key objects KeyFactory kf = KeyFactory.getInstance("RSA","IBMJCECCA"); //KeyPair object used to store in keystore KeyPair pair = new KeyPair(kf.generatePublic(keyLabelKeySpec), kf.generatePrivate(keyLabelKeySpec)); //Load the keystore and insert the key generated above into the keystore. KeyStore ks = KeyStore.getInstance(keystore_type,"IBMJCECCA"); FileInputStream fis = null; try { fis = new FileInputStream(keystore_file); } catch ( java.io.FileNotFoundException e ) { //It is ok if the file does not exist. We will create the keystore. } 174
Java Security on z/OS - The Complete View
ks.load(fis, keystore_password.toCharArray()); // See "GENERATE X.509 CERTIFICATE" example for generating an X.509 cert Certificate cert = ; ks.setKeyEntry(keystore_alias, pair.getPrivateKey(), keystore_password.toCharArray(), cert ); //Save the keystore. ks.store(new FileOutputStream(keystore_file), keystore_password.toCharArray());
// The keystore type. String keystore_type = new String("JCECCAKS"); //The key type inside of the CKDS. //Valid values are DESede and AES. String algorithm = new String("AES"); //The JCECCAKS keystore file name. String keystore_file = ; //The password to the JCECCAKS keystore file where the key will be inserted. String keystore_password = ; //The keystore alias that the key entry is inserted with in the JCECCAKS keystore file. // It must be 21 characters // The first 3 characters must be alphabetic // The remaining characters must be hexadecimal. String keystore_alias = ; //The CKDS label to be associated with this key entry in the JCECCAKS keystore file. //The label cannot be larger than 64 characters. String ckds_label = ; //Generate the secret key object corresponding to the label passed in. SecretKeyFactory myKeyFactory = SecretKeyFactory.getInstance(algorithm, "IBMJCECCA"); KeyLabelKeySpec spec = new KeyLabelKeySpec(ckds_label); SecretKey key = myKeyFactory.generateSecret(spec);
//Load the keystore and insert the key generated above into the keystore. KeyStore ks = KeyStore.getInstance(keystore_type,"IBMJCECCA");
Chapter 11. Java and key management on z/OS
175
FileInputStream fis = null; try { fis = new FileInputStream(keystore_file); } catch ( java.io.FileNotFoundException e ) { //It is ok if the file does not exist. We will create the keystore. } ks.load(fis, keystore_password.toCharArray()); ks.setKeyEntry(keystore_alias, key, keystore_password.toCharArray(),
null);
11.6.5 Generate a RACF RSA key pair with the private key in the PKDS
Example 11-5 demonstrates how you would generate an RSA key pair with the certificate stored in the RACF database and the private key stored in the PKDS. This is equivalent to using the RACDCERT command with the ICSF keyword. Note that the code refers to Example 11-2 on page 173 for generating an X.509 V3 certificate which, in this case, is kept in the RACF database. The RACFOutputStream and RACFInputStream used in this example are coming with the package com.ibm.crypto.hdwrCCA.provider. When generating certificates and keys stored in RACF, only the RACFOutputStream and RACFInputStream classes from the com.ibm.crypto.provider package should be used.
Example 11-5 RACF and PKDS key generation
// RACF User ID to use to load/store keyring String racf_user_id = ; // The keystore type. String keystore_type = new String("JCERACFKS");
//The RACF key ring name. String keystore_name = ; //The password to the RACF key ring (can be anything, but key password must match keystore password. String keystore_password = ; //The keystore alias the key entry is inserted with in the JCECCAKS keystore file. String keystore_alias = ; //Generate Hardware RSA key byte type = KeyHWAttributeValues.PKDS; byte usage = KeyHWAttributeValues.KEYMANAGEMENT; RSAKeyParameterSpec spec; spec = new RSAKeyParameterSpec(keySize,type,usage);
176
KeyPairGenerator generator = new RSAKeyPairGenerator(); generator.initialize(spec); pair = generator.genKeyPair(); //Load the keystore and insert the key generated above into the keystore. KeyStore ks = KeyStore.getInstance(keystore_type,"IBMJCECCA"); RACFInputStream fis = null; fis = new RACFInputStream(racf_user_id,keystore_file,keystore_password.toCharArray()); ks.load(fis, keystore_password.toCharArray());
// See "GENERATE X.509 CERTIFICATE" example for generating an X.509 cert Certificate cert = ; ks.setKeyEntry(keystore_alias, key, keystore_password.toCharArray(), RACFOutputStream fout = null; fout = new RACFOutputStream (racf_user_id,keystore_file,keystore_password.toCharArray()); //Save the keystore, i.e. set key ring in RACF. ks.store(fout, keystore_password.toCharArray()); cert);
177
178
12
Chapter 12.
179
12.1 JCEKS
Example 12-1 shows how to read keys out of a JCEKS keystore. The keystore were created with the keytool utility, as shown here. When using the JCEKS, both the certificate and the private key are stored in the file referred to by the keystore option.
Example 12-1 Generating an RSA key pair in a JCEKS with keytool
keytool -genkeypair \ -alias AliceRSA \ -dname "CN=IBM" \ -keystore testkeys.jcks \ -provider IBMJCE \ -keyalg RSA \ -keysize 2048 \ -keypass passw0rd \ -storepass passw0rd \ -storetype JCEKS \ -validity 999 Example 12-2 reads the public and private key generated in Example 12-1. Then the keys are used for a simple asymmetric encryption followed by decryption.
Example 12-2 RSA encryption and decryption using a JCEKS key pair
import javax.crypto.Cipher; public class JceksExample1 { public KeyPair readKeys() throws Exception { try { KeyStore jceks = KeyStore.getInstance("JCEKS", "IBMJCE"); InputStream is = new FileInputStream("/u/ebbemp/ks/testkeys.jcks"); jceks.load(is, "passw0rd".toCharArray()); Certificate aliceCertificate = jceks.getCertificate("AliceRSA"); PublicKey alicePublicKey = aliceCertificate.getPublicKey(); PrivateKey alicePrivateKey = (PrivateKey) jceks.getKey("AliceRSA", "passw0rd".toCharArray()); KeyPair keyPair = new KeyPair(alicePublicKey, alicePrivateKey); return keyPair; } catch (Exception e) { System.err.println("Could not read the keystore"); throw new Exception(e); } }
180
public byte[] encrypt(String clearText, PublicKey publicKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA", "IBMJCE"); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = rsaCipher.doFinal(clearText.getBytes()); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(byte[] encryptedData, PrivateKey privateKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA", "IBMJCE"); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedMessageBytes = rsaCipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedMessageBytes); return decryptedMessage; } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { JceksExample1 example = new JceksExample1(); String secretMessage = "Hi Alice, please don't tell anyone, but .."; try { System.out.println("Reading keys from Keystore"); KeyPair keys = example.readKeys(); System.out.println("Keys read"); System.out.println("Encrypting: " + secretMessage); byte[] encrypted = example.encrypt(secretMessage, keys.getPublic()); System.out.println("Message encrypted"); System.out.println("Decrypting:"); String decrypted = example.decrypt(encrypted, keys.getPrivate()); System.out.println("Message decrypted: " + decrypted); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } }
This program issues the messages shown in Figure 12-1 on page 182.
181
Reading keys from Keystore Keys read Encrypting: Hi Alice, please don't tell anyone, but .. Message encrypted Decrypting: Message decrypted: Hi Alice, please don't tell anyone, but ..
Figure 12-1 Messages issued by the JCEKS use example
12.2 JCECCAKS
This example uses the hwkeytool to generate a JCECCAKS keystore with two RSA key pairs. The first key pair is created with the hardwaretype option CLEAR, as shown in Example 12-3. This means that the key pair will be stored in clear in an ICSF key token. However, the certificate itself is stored in the file referred to by the keystore option.
Example 12-3 Generating a clear key pair with the hwkeytool utility hwkeytool -genkeypair \ -alias AliceRSAclear \ -dname "CN=IBM" \ -keystore testkeys.cca \ -provider IBMJCECCA \ -keyalg RSA \ -keysize 2048 \ -storetype JCECCAKS \ -keypass abc123 \ -storepass abc123 \ -hardwaretype CLEAR
The second RSA key pair is generated with the hardwaretype PKDS option, as shown in Example 12-4. The private key is encrypted with the hardware coprocessor asymmetric Master Key and is kept in the PKDS. Note: hwkeytool allows the specification of a key label for the key kept in the PKDS. If this option is not used, hwkeytool generates a random value given as a key label to the key in the PKDS.
Example 12-4 Generating a PKDS RSA key pair with the hwkeytool utility hwkeytool -genkeypair \ -alias AliceRSApkds \ -dname "CN=IBM" \ -keystore testkeys.cca \ -provider IBMJCECCA \ -keyalg RSA \ -keysize 2048 \ -storetype JCECCAKS \ -keypass abc123 \ -storepass abc123 \ -hardwaretype PKDS \ -keylabel ALICE.RSA.TEST1
182
The program in Example 12-5 is run next, which performs the RSA encryption and decryption sequence twice, the first time using the RSA clear key pair and the second time using the PKDS key pair.
Example 12-5 RSA encryption and decryption using the JCECCAKS clear and PKDS key pairs
import javax.crypto.Cipher; public class JceccaksExample1 { private KeyPair readKeys(String keyLabel) throws Exception { try { KeyStore jceccaks = KeyStore.getInstance("JCECCAKS", "IBMJCECCA"); InputStream is = new FileInputStream("/u/ebbemp/ks/testkeys.cca"); jceccaks.load(is, "abc123".toCharArray()); Certificate aliceCertificate = jceccaks.getCertificate(keyLabel); PublicKey alicePublicKey = aliceCertificate.getPublicKey(); PrivateKey alicePrivateKey = (PrivateKey) jceccaks.getKey(keyLabel, "abc123".toCharArray()); KeyPair keyPair = new KeyPair(alicePublicKey, alicePrivateKey); return keyPair; } catch (Exception e) { System.err.println("Could not read the keystore"); throw new Exception(e); } } private byte[] encrypt(String clearText, PublicKey publicKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA", "IBMJCECCA"); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = rsaCipher.doFinal(clearText.getBytes()); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } private String decrypt(byte[] encryptedData, PrivateKey privateKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA", "IBMJCECCA"); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedMessageBytes = rsaCipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedMessageBytes); return decryptedMessage; } catch (Exception e) {
Chapter 12. Usage examples - using Java keystores on z/OS
183
e.printStackTrace(); return null; } } public void encryptDecryptTest(String keyLabel) { String secretMessage = "Hi Alice, please don't tell anyone, but .."; try { System.out.println("Reading " + keyLabel + " keys from Keystore"); KeyPair keys = readKeys(keyLabel); System.out.println("Keys read"); System.out.println("Encrypting: " + secretMessage); byte[] encrypted = encrypt(secretMessage, keys.getPublic()); System.out.println("Message encrypted"); System.out.println("Decrypting:"); String decrypted = decrypt(encrypted, keys.getPrivate()); System.out.println("Message decrypted: " + decrypted); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } public static void main(String[] args) { JceccaksExample1 example = new JceccaksExample1(); System.out.println("Clear key test"); example.encryptDecryptTest("AliceRSAclear"); System.out.println(); System.out.println("PKDS key test"); example.encryptDecryptTest("AliceRSApkds"); } }
When executing correctly, the program issues the messages shown in Figure 12-2 on page 185.
184
Clear key test Reading AliceRSAclear keys from Keystore Keys read Encrypting: Hi Alice, please don't tell anyone, but .. Message encrypted Decrypting: Message decrypted: Hi Alice, please don't tell anyone, but .. PKDS key test Reading AliceRSApkds keys from Keystore Keys read Encrypting: Hi Alice, please don't tell anyone, but .. Message encrypted Decrypting: Message decrypted: Hi Alice, please don't tell anyone, but ..
Figure 12-2 Messages issued by the JCECCAKS use example
12.3 JCERACFKS
This example uses a JCERACFKS keystore. The content of the keystore is generated using the RACDCERT RACF command. The example generates an RSA key pair and a self-signed certificate that are connected to a new key ring in RACF with the USAGE(PERSONAL) option of the RACDCERT CONNECT command. Using this option allows you to also keep the private key that corresponds to the certificate in the RACF database. Figure 12-3 shows the RACF RACDCERT commands issued to perform these tasks: Create the key pair and the self-signed certificate with a label AliceRSA1; this is the RACDCERT GENCERT command. Create a key ring with a label ALICE_JCERACFKS, owned by the RACF userID EBBEMP; this is the RACDCERT ADDRING command. Connect the certificate and the key pair to the key ring with the USAGE(PERSONAL) option; this is the RACDCERT CONNECT command. RACDCERT ID(EBBEMP) GENCERT SUBJECTSDN(CN('Alice Self Signed Cert JCERACFKS')) SIZE(1024) WITHLABEL('AliceRSA1') RACDCERT ID(EBBEMP) ADDRING(ALICE_JCERACFKS) RACDCERT ID(EBBEMP) CONNECT(ID(EBBEMP) LABEL('AliceRSA1') RING(ALICE_JCERACFKS) USAGE(PERSONAL))
Figure 12-3 Setup of the JCERACFKS example
To be able to access the key pair and certificate created, users need to have at least READ access to the IRR.DIGTCERT.LIST RACF resource in the RACF FACILITY class of resources, as shown in Figure 12-4 on page 186.
185
The example program is shown in Example 12-6. Note that this program uses com.ibm.crypto.provider.RACFInputStream. This is an InputStream implementation that allows Java applications to access RACF key rings.
Example 12-6 RSA encryption and decryption using a JCERACFKS key pair
import javax.crypto.Cipher; import com.ibm.crypto.provider.RACFInputStream; public class JceracfksExample1 { public KeyPair readKeys() throws Exception { try { KeyStore jceracfks = KeyStore.getInstance("JCERACFKS", "IBMJCE"); InputStream is = new RACFInputStream("EBBEMP", "ALICE_JCERACFKS", null); jceracfks.load(is, null); // no password Certificate aliceCertificate = jceracfks.getCertificate("AliceRSA1"); PublicKey alicePublicKey = aliceCertificate.getPublicKey(); PrivateKey alicePrivateKey =(PrivateKey) jceracfks.getKey("AliceRSA1",null); KeyPair keyPair = new KeyPair(alicePublicKey, alicePrivateKey); return keyPair; } catch (Exception e) { System.err.println("Could not read the keystore"); throw new Exception(e); } } public byte[] encrypt(String clearText, PublicKey publicKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA"); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = rsaCipher.doFinal(clearText.getBytes()); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(byte[] encryptedData, PrivateKey privateKey) { 186
Java Security on z/OS - The Complete View
try { Cipher rsaCipher = Cipher.getInstance("RSA"); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedMessageBytes = rsaCipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedMessageBytes); return decryptedMessage; } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { JceracfksExample1 example = new JceracfksExample1(); String secretMessage = "Hi Alice, please don't tell anyone, but .."; try { System.out.println("Reading keys from Keystore"); KeyPair keys = example.readKeys(); System.out.println("Keys read"); System.out.println("Encrypting: " + secretMessage); byte[] encrypted = example.encrypt(secretMessage, keys.getPublic()); System.out.println("Message encrypted"); System.out.println("Decrypting:"); String decrypted = example.decrypt(encrypted, keys.getPrivate()); System.out.println("Message decrypted: " + decrypted); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } }
12.4 JCECCARACFKS
This example uses the JCECCARACFKS keystore. The setup for this example is similar to the one used for the JCERACFKS example, with the exception that the PCICC option of the RACDCERT command is used when generating the key pair and certificate. This option results in the key pair being generated by the hardware cryptographic coprocessor and the private key to be stored in the PKDS encrypted with the coprocessor asymmetric Master Key. Figure 12-5 on page 188 shows the sequence of RACDCERT commands used to: Create an RSA key pair and a self-signed certificate with a label AliceRSA2. The private key is kept in the PKDS with a label ALICE.RSA.TEST2. Create a RACF key ring with a label ALICE_JCECCARACFKS. Connect the key pair and certificate to the key ring owned by EBBEMP.
187
RACDCERT ID(EBBEMP) GENCERT SUBJECTSDN(CN('Alice Self Signed Cert JCECCARACFKS')) SIZE(1024) WITHLABEL('AliceRSA2') PCICC(ALICE.RSA.TEST2) RACDCERT ID(EBBEMP) ADDRING(ALICE_JCECCARACFKS) RACDCERT ID(EBBEMP) CONNECT(ID(EBBEMP) LABEL('AliceRSA2') RING(ALICE_JCECCARACFKS) USAGE(PERSONAL))
Figure 12-5 Setup of the JCECCARACFKS example
The example program is shown in Figure 12-6 on page 190. com.ibm.crypto.hdwrCCA.provider.RACFInputStream is used again, which allows the program to access RACF key rings and get the private key PKDS label.
Example 12-7 RSA encryption and decryption using a JCECCARACFKS key pair
import javax.crypto.Cipher; import com.ibm.crypto.hdwrCCA.provider.RACFInputStream; public class JceccaracfksExample1 { public KeyPair readKeys() throws Exception { try { KeyStore jceracfks = KeyStore.getInstance("JCECCARACFKS"); InputStream is = new RACFInputStream("EBBEMP", "ALICE_JCECCARACFCCAKS", null); jceracfks.load(is, null); // no password Certificate aliceCertificate = jceracfks.getCertificate("AliceRSA2"); PublicKey alicePublicKey = aliceCertificate.getPublicKey(); PrivateKey alicePrivateKey = (PrivateKey) jceracfks.getKey("AliceRSA2", null); KeyPair keyPair = new KeyPair(alicePublicKey, alicePrivateKey); return keyPair; } catch (Exception e) { System.err.println("Could not read the keystore"); throw new Exception(e); } } public byte[] encrypt(String clearText, PublicKey publicKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA"); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); 188
byte[] encryptedData = rsaCipher.doFinal(clearText.getBytes()); return encryptedData; } catch (Exception e) { e.printStackTrace(); return null; } } public String decrypt(byte[] encryptedData, PrivateKey privateKey) { try { Cipher rsaCipher = Cipher.getInstance("RSA"); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedMessageBytes = rsaCipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedMessageBytes); return decryptedMessage; } catch (Exception e) { e.printStackTrace(); return null; } } public static void main(String[] args) { JceccaracfksExample1 example = new JceccaracfksExample1(); String secretMessage = "Hi Alice, please don't tell anyone, but .."; try { System.out.println("Reading keys from Keystore"); KeyPair keys = example.readKeys(); System.out.println("Keys read"); System.out.println("Encrypting: " + secretMessage); byte[] encrypted = example.encrypt(secretMessage, keys.getPublic()); System.out.println("Message encrypted"); System.out.println("Decrypting:"); String decrypted = example.decrypt(encrypted, keys.getPrivate()); System.out.println("Message decrypted: " + decrypted); } catch (Exception e) { System.err.println("Something went wrong ..."); e.printStackTrace(); } } }
12.5 PKCS11IMPLKS
This example shows a program that reads RSA keys from a PKCS#11 token, and then uses them for a simple encryption followed by decryption.
189
Before you can use z/OS PKCS#11 tokens in a Java application, you must complete several preliminary setup steps, as explained in 9.7, The IBM providers - IBMPKCS11Impl on page 138. The steps needed before you run the example are summarized here: Setting up a token with a signed certificate in it Creating a configuration file for the PKCS11Impl provider Properly setting up a local security property file
Note, however, that the following permissions should be granted in RACF for these commands to operate: The class of resources CRYPTOZ should be activated and RACLISTed with the following RACF commands: SETROPTS CLASSACT(CRYPTOZ) GENERIC(CRYPTOZ) RACLIST(CRYPTOZ) SETROPTS RACLIST(CRYPTOZ) REFRESH The Security Officer and User authority should be given to the user who is issuing the RACDCERT commands. Our approach is to prevent everyone except the user EBBEMP from having this authority: RDEF CRYPTOZ SO.EBBE.* UACC(NONE) RDEF CRYPTOZ USER.EBBE.* UACC(NONE)
190
PERMIT SO.EBBE.* CLASS(CRYPTOZ) ID(EBBEMP) ACC(CONTROL) SETROPTS RACLIST(CRYPTOZ) REFRESH Notice that we elected here to give these permissions for all z/OS PKCS#11 tokens with a label name beginning with the qualifier EBBE. Authority should also be granted for executing the RACDCERT BIND command. We use the same approach here of denying this authority to everyone except the user EBBEMP: RDEF FACILITY IRR.DIGTCERT.BIND UACC(NONE) PERMIT IRR.DIGTCERT.BIND CLASS(FACILITY) ID(EBBEMP) ACC(UPDATE) RDEF FACILITY IRR.DIGTCERT.LIST UACC(NONE) PERMIT IRR.DIGTCERT.LIST CLASS(FACILITY) ID(EBBEMP) ACC(CONTROL) Note: We illustrate here the RACF commands that we used in our specific setup. However, many possible variations of these commands can be used, depending on the intended granularity of permissions that are to be granted. Refer to z/OS Security Server RACF Command Language Reference, SA22-7687, to determine the commands that best fit your use case. After creating the z/OS PKCS#11 token in the TKDS, its contents can be listed with the RACF command: RACDCERT LISTTOKEN(EBBE.TEST1) The token contents, that is, the two certificates and their keys, is displayed as shown in Figure 12-7. Notice that the token contains the private key for the certificate EBBE_pkcs11_cert because it was bound, by default, as USAGE(PERSONAL). Token: EBBE.TEST1 Seq Num Attributes -------- ---------------------------00000001 Default: NO Priv Key: NO Usage: CERTAUTH Pub Key: YES Owner: CERTAUTH 00000003 Default: NO Priv Key: YES Usage: PERSONAL Pub Key: YES Owner: ID(EBBEMP) Labels -------------------------------------TKDS: EBBE_pkcs11_certauth RACF: EBBE_pkcs11_certauth
191
192
import javax.crypto.Cipher; public class Pkcs11Example1 { public static void main(String[] args) { try { KeyStore pkcs11ks = KeyStore.getInstance("PKCS11IMPLKS", "IBMPKCS11Impl-ebbe"); pkcs11ks.load(null, null); // no stream or password needed Certificate cert = pkcs11ks.getCertificate("EBBE_pkcs11_cert"); PublicKey publicKey = cert.getPublicKey(); PrivateKey privateKey = (PrivateKey) pkcs11ks.getKey("EBBE_pkcs11_cert", null); String secretMessage = "A very secret message ..."; System.out.println("Encrypting: " + secretMessage); Cipher rsaCipher = Cipher.getInstance("RSA", "IBMPKCS11Impl-ebbe"); rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedData = rsaCipher.doFinal(secretMessage.getBytes()); System.out.println("Decrypting"); rsaCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedDataBytes = rsaCipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedDataBytes); System.out.println("Message decrypted: " + decryptedMessage); } catch (Exception e) { System.err.println("Something went wrong .."); e.printStackTrace(); } } }
193
import java.security.SecureRandom; import import import import javax.crypto.Cipher; javax.crypto.SecretKey; javax.crypto.SecretKeyFactory; javax.crypto.spec.IvParameterSpec;
import com.ibm.crypto.hdwrCCA.provider.KeyLabelKeySpec; public class CkdsExample1 { public void encryptDecryptTest(String ckdsLabel) { try { System.out.println("Encrypt/decrypt test with label: " + ckdsLabel); SecureRandom rnd = SecureRandom.getInstance("IBMSecureRandom", "IBMJCECCA"); byte[] ivData = new byte[8]; rnd.nextBytes(ivData); IvParameterSpec ivSpec = new IvParameterSpec(ivData); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESEde", "IBMJCECCA"); // get a key object from the CKDS label KeyLabelKeySpec spec = new KeyLabelKeySpec(ckdsLabel); SecretKey tdesKey = keyFactory.generateSecret(spec); // Get a DESede cipher for encryption (DESede = Triple DES) Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "IBMJCECCA"); String secretMessage = "CC No: 371234567890"; System.out.println("Encrypting: " + secretMessage); cipher.init(Cipher.ENCRYPT_MODE, tdesKey, ivSpec); byte[] encryptedData = cipher.doFinal(secretMessage.getBytes()); System.out.println("Decrypting"); cipher.init(Cipher.DECRYPT_MODE, tdesKey, ivSpec); 194
Java Security on z/OS - The Complete View
byte[] decryptedBytes = cipher.doFinal(encryptedData); String decryptedMessage = new String(decryptedBytes); System.out.println("Decrypted data: " + decryptedMessage); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { CkdsExample1 example = new CkdsExample1(); example.encryptDecryptTest("SG24.CLEAR.TDES"); System.out.println(); example.encryptDecryptTest("SG24.PROT.TDES"); } }
When properly executed, the test program issues the messages shown in Figure 12-10. Encrypt/decrypt test with label: SG24.CLEAR.TDES Encrypting: CC No: 371234567890 Decrypting Decrypted data: CC No: 371234567890 Encrypt/decrypt test with label: SG24.PROT.TDES Encrypting: CC No: 371234567890 Decrypting Decrypted data: CC No: 371234567890
Figure 12-10 Output of test program
195
196
Part 4
Part
Appendixes
197
198
Appendix A.
199
Cryptographic coprocessors
The hardware coprocessor technologies available on the IBM zSeries and System z models differ, depending on the models they have been implemented on. Also note that some of the features referred to here are no longer available. Table A-2 on page 206 and Table A-3 on page 206 list the technologies discussed in this section. The details provided in this appendix mainly relate to the coprocessor technology used in IBM Server z10.
The following section briefly explains the different coprocessor models that are referred to in the figure.
asymmetric algorithms, along with miscellaneous cryptographic services. The CCF supports secure key operations and has been certified to FIPS 140-1 Level 4. There are up to two CCF in a zSeries server, which requires a system power-on Reset (POR) to be activated. The CCF can be shared by up to 16 logical partitions.
201
Security officers
Data to encrypt Encrypted data Data to encrypt
Encrypted data
202
Note that the logical partitions image profile can have more than one domain specified for the partition. In that case, the single domain to be actually assigned to the partition is then specified in the Options Dataset of the ICSF instance executing in the partition.
203
TSO terminal
CEX2C
Symmetric-keys Master Key Asymmetric-keys Master Key Domain 3 Domain 2 Domain 1 Domain 0
RACF
Plaintext Ciphertext Crypto instruction
CPACF
Or instructions in the application
CKDS
PKDS
TKDS
Options dsn
204
Hardware setup
It is required to set up and enable the hardware cryptography facilities in zSeries or System z. This section describes the operations to be performed to make the hardware devices available for use. The steps in these operations may differ, depending on which system family the hardware devices belong to.
205
Table A-2 Cryptographic coprocessors by system family and model Model CCF PCICC PCICA PCIXCC CEX2C CPACF ZAAP (with CPACF) No Yes Yes Yes
Yes No No No
Yes No No No
Yes Yes No No
No Yes No No
Table A-3 indicates the maximum number of installed features by system family and model. Note that some features contain more than one coprocessor (for example, the CEX2C feature contains two coprocessors).
Table A-3 Number of features by system family and models Type of Coprocessor (coprocessor number per feature) PCICC (2) PCICA (2) PCIXCC (1) CEX2C-1P (1) b CEX2C (2) ZAAP (1) z800 z900 8 6 z890 z990 2a/6 4 8 16 z9 BC z9 EC z10 EC z10 BC
8 27
8 32 8 5 8
a. For a z890, there is a maximum of two PCICA features. b. The CEX2C-1P can be installed in z9 BC and z10 BC servers only.
Hardware installation
CCF and CPACF come as a standard orderable feature and are not required to be installed in the system. However, they are required to be enabled because they are delivered in a non-operational state. CCF is enabled by installing the IBM provided enablement diskette, followed by a system power-on Reset (POR). Enabling CCF is a prerequisite for enabling the other coprocessor types that coexist in a system with the CCF. CPACF is enabled by installing the LICC FC 3863. Enabling CPACF does not disrupt system operations. Enabling CPACF is a prerequisite for enabling the other coprocessor types that coexist in a system with the CPACF. PCICC requires an enablement diskette of its own, but enabling PCICC does not disrupt system operations. The other coprocessor types do not require a specific enablement process to be run as long as the CCF or CPACF in the system has been enabled.
206
3. From the Systems Management section on the left side of the screen, locate and click the target CPC and select the CPC detail, as shown in Figure A-5 on page 208.
207
Notice the information CP Assist for Cryptographic Functions: Installed, which indicates that FC 3863 is installed in the system.
208
2. Select the Crypto tab in the image profile. The list box for assignment of cryptographic coprocessors is displayed, as shown in Figure A-8.
209
The selections to be made address the following: Usage Domain Index - This is the selection of the cryptographic coprocessor domain(s) assigned to the partition in all cryptographic coprocessors that the partition has access to. If more than one usage domain is specified for the partition, only one of these domains should be used after the partition has been activated. This is the domain indicated in the Options Dataset of ICSF. The same usage domain index can be used by multiple partitions regardless of which LCSS they are defined to. However, the combination cryptographic coprocessor number and usage domain index number must be unique across all partitions planned to be active at the same time. Although it is possible to define duplicate combinations of cryptographic coprocessor number(s) and usage domain index(es) for different partitions image profiles, only one of these logical partitions can be active at any time. This is a valid definition, however, for backup configurations. Control Domain Index - This is the selection of the cryptographic coprocessors domain index(es) that can be administered from this logical partition being set up as the TCP/IP host for the TKE workstation. The usage domain index specified for this partition should also be part of the selected control domains. PCI Cryptographic Coprocessor Candidate List - This is the selection of the cryptographic coprocessors that are eligible to be accessed by this logical partition. From the scrollable list, select the coprocessor number(s), from 0 to 15, that identifies the coprocessor(s) to be accessed by this partition. Unless the coprocessor is also specified in the Online List, you must configure the coprocessor on in the Crypto Service Operations task list to make it accessible to the partition. PCI Cryptographic Coprocessor Online List - This is the selection of the cryptographic coprocessors that are automatically brought online to the partition during the logical partition activation. The coprocessor numbers selected in the Online List must also be part of the Candidate List. If the cryptographic coprocessor number and usage domain index combination for the coprocessor selected in the partition Online List is already in use by another active logical partition, the activation of the logical partition will fail.
zAAP definition
As for the cryptographic coprocessors, zAAPs are selected for access by logical partition. Select the target CPC in the HMC Servers list. Then, in the Operational Customization list, select the Customize/Delete Activation Profiles task. Select the target image profile and click the Customize selected Profile action. Select Processor in the image profile tab, as shown in Figure A-9 on page 211.
210
Select the appropriate number of zAAPs and save the configuration. Repeat this operation for each logical partition that needs to be customized for access to a zAAP specialty engine.
Software setup
This section explains how to set up the ICSF component of z/OS and how to start it. The steps to follow are presented here in their typical sequence order when performed at most installations.
Customizing SYSx.PARMLIB
The load library for ICSF (hlq.SCSFMOD0) must be in the LINKLIST and APF lists of libraries. This can be achieved by dynamically changing these lists using the SETPROG APF and SETPROG LNKLST commands. The two members PROGxx and LNKSLSTxx of the PARMLIB also must be updated for a persistent change. The modules CSFDAUTH and CSFDPKDS must be added to the sections AUTHPGM and AUTHTSF of the IKJTSOxx member, as shown in Figure A-10 on page 212.
211
Menu
Utilities
Compilers
Help
------------------------------------------------------------------------------BROWSE SYS1.PARMLIB(IKJTSOxx) - 01.15 Line 00000000 Col 001 080 Command ===> ********************* Top of Data ******************************************** AUTHPGM NAMES ( /* AUTHORIZED PROGRAMS */ + . CSFDAUTH /* ICSF */ + CSFDPKDS /* ICSF */ + . AUTHTSF NAMES ( /* PROGRAMS TO BE AUTHORIZED */ + . CSFDAUTH /* ICSF */ + CSFDPKDS /* ICSF */ + . ********************** Bottom of Data *****************************************
Figure A-10 View of the IKJTSOxx PARMLIBs member
For ease of use and maintenance, we recommend that you create a system symbol for each logical partition in the system &LPNUMn. These symbols are added in the IEASYMxx member as shown in Figure A-11. Menu Utilities Compilers Help
------------------------------------------------------------------------------BROWSE SYS1.PARMLIB(IEASYMnn) - 01.05 Line 00000000 Col 001 080 Command ===> ********************** Top of Data ******************************************** , SYSDEF SYMDEF(&LPNUMA=x), SYSDEF SYMDEF(&LPNUMB=x), SYSDEF SYMDEF(&LPNUMC=x), . *********************** Bottom of Data ****************************************
Figure A-11 View of the IEASYMxx PARMLIB member
ICSF requires run-time parameters to be specified in the Options Dataset. It is common practice to use the CSFPRMxx member of the PARMLIB as the Options Dataset to contain such parameters as the domain to use in the coprocessors and the dataset name of the ICSF CKDS, PKDS and TKDS. Figure A-12 on page 213 illustrates the contents of the Options Dataset.
212
Menu Utilities Compilers Help ------------------------------------------------------------------------------BROWSE SYS1.PARMLIB(CSFPRMx0) - 01.06 Line 00000000 Col 001 080 Command ===> ************************* Top of Data ***************************************** CKDSN(SYS1.&SYSNAME..SCSFCKDS) PKDSN(SYS1.&SYSNAME..SCSFPKDS) TKDSN(SYS1.&SYSNAME..SCSFTKDS) PKDSCACHE(64) COMPAT(NO) SSM(YES) DOMAIN(&LPNUMx) KEYAUTH(YES) CHECKAUTH(YES) SYSPLEXTKDS(YES/NO) SYSPLEXTKDS(YES/NO) TRACEENTRY(1000) USERPARM(USERPARM) COMPENC(DES) REASONCODES(ICSF) *************************** Bottom of Data ************************************
Figure A-12 View of the CSFPRMx0 PARMLIB member
ISPF panels
The ISPF options must be customized to make the ICSF ISPF panels selectable and operating. Figure A-13 shows a modified primary ISPF panel to offer the ICSF option. Menu Utilities Compilers Help
------------------------------------------------------------------------------BROWSE hlq.PANELS(ISR@PRIM) - 01.27 Line 00000000 Col 001 080 Command ===> ************************ Top of Data ****************************************** )PANEL KEYLIST(ISRSAB,ISR) )ATTR DEFAULT(...) FORMAT(MIX) ..... )BODY CMD(ZCMD) ..... ICSF For ICSF panels selection ..... )PROC ..... ICSF,'CMD(%$ICSF)' ..... )END ************************* Bottom of Data **************************************
Figure A-13 Modified ISPF primary menu
213
Add the datasets shown in Figure A-14 in the TSO logon procedure. If an alternate TSO procedure is developed for the ICSF users, make sure that these users have proper access to the new procedure. Menu Utilities Compilers Help
------------------------------------------------------------------------------BROWSE SYS1.PROCLIB(<tso_proc>) - 01.06 Line 00000000 Col 001 080 Command ===> ********************* Top of Data ********************************************* //tso_proc EXEC PGM=IKJTSO01, .. //SYSPROC DD DSN=hlq.SCSFCLI0,DISP=SHR // DD DSN= //ISPPLIB DD DSN=hlq.SCSFPNL0,DISP=SHR // DD DSN= //ISPMLIB DD DSN=hlq.SCSFMSG0,DISP=SHR // DD DSN= //ISPSLIB DD DSN=hlq.SCSFSKL0,DISP=SHR // DD DSN= //ISPTLIB DD DSN=hlq.SCSFTLIB,DISP=SHR ********************** Bottom of Data *****************************************
Figure A-14 ICSF libraries in the TSO logon procedure
not enabled for dataset migration. Also, protect access to the datasets with the appropriate
RACF profiles. Figure A-15 on page 215 shows the JCL provided in the SAMPLIB for allocating a CKDS.
214
Menu
Utilities
Compilers
Help
------------------------------------------------------------------------------BROWSE SYS1.SAMPLIB(CSFCKDS) - 01.00 Line 00000000 Col 001 080 Command ===> ********************* Top of Data ********************************************* //CSFCKDS JOB <job card parameter> //DEFINEEXEC PGM=IDCAMS,REGION=4M //SYSPRINTDD SYSOUT=* //SYSINDD * DEFINE CLUSTER (NAME(hlq.CFSCKDS) VOLUMES(xxxxxx) RECORDS(100 50) RECORDSIZE(252,252) KEYS(72 0) FREESPACE(10,10) SHAREOPTIONS(2)) DATA (NAME(hlq.CFSCKDS.DATA) BUFFERSPACE(100000) ERASE WRITECHECK INDEX (NAME(hlq.CFSCKDS.INDEX)) /* ********************** Bottom of Data *****************************************
Figure A-15 JCL to allocate the CKDS
------------------------------------------------------------------------------BROWSE SYS1.PROCLIB(<CSF>) - 01.04 Line 00000000 Col 001 080 Command ===> *********************** Top of Data ******************************************* //CSF PROC MEMBER=CSFPRMx0 // EXEC PGM=CSFMMAIN,REGION=0M,TIME=NOLIMIT //STEPLIB DD DSN=hlq.SCSFMOD0,DISP=SHR //CSFLIST DD SYSOUT=*,DCB=(LRECL=132,BLKSIZE=132),HOLD=YES //CSFPARM DD DSN=SYS1.PARMLIB(&MEMBER.),DISP=SHR ************************ Bottom of Data ***************************************
Figure A-16 ICSF STC
We recommend that you define the started task name in the RACF STARTED class of resources, associated to a protected userID. A protected userID is a userID without a password, so that the userID cannot be misused to logon to the system.
215
216
HCR7750 -------------- Integrated Cryptographic Service Facility-------OPTION ===> Enter the number of the desired option. 1 2 3 4 5 6 7 8 9 COPROCESSOR MGMT MASTER KEY OPSTAT ADMINCNTL UTILITY PPINIT TKE KGUP UDX MGMT Management of Cryptographic Coprocessors Master key set or change, CKDS/PKDS Processing Installation options Administrative Control Functions ICSF Utilities Pass Phrase Master Key/CKDS Initialization TKE Master and Operational Key processing Key Generator Utility processes Management of User Defined Extensions
The installed coprocessors are displayed in the panel shown in Figure A-18. ------------------------- ICSF Coprocessor Management -------- Row 1 to 4 of 4 COMMAND ===> SCROLL ===> PAGE Select the coprocessors to be processed and press ENTER. Action characters are: A, D, E, K, R and S. See the help panel for details. COPROCESSOR SERIAL NUMBER STATUS ---------------------------s E01 94000264 ONLINE s E02 95001434 ONLINE s E03 95001437 ONLINE . F00 ACTIVE ******************************* Bottom of data ********************************
Figure A-18 Coprocessor Management panel
To select a coprocessor, enter s. ICSF displays the status of some internal registers in the domain the logical partition has access to, as shown in Figure A-19 on page 218. The status displayed in Figure A-19 on page 218 shows that both the symmetric and asymmetric Master Keys in the coprocessor domain are empty and therefore need to be initialized.
217
---------------------- ICSF - Coprocessor Hardware Status -------------------CRYPTO DOMAIN: 1 REGISTER STATUS + Crypto Serial Number Status Symmetric-Keys Master Key New Master Key register Verification pattern Hash pattern : 94000264 : ONLINE COPROCESSOR E01 More:
: EMPTY : : : Old Master Key register : EMPTY Verification pattern : Hash pattern : : Current Master Key register : EMPTY Verification pattern : Hash pattern : : Asymmetric-Keys Master Key New Master Key register : EMPTY Hash pattern : : Old Master Key register : EMPTY Hash pattern : : : Current Master Key register : EMPTY Hash pattern :
Figure A-19 Coprocessor hardware status panel showing empty Master Keys
To initialize the Master Keys with the Passphrase Initialization method, select option 6 PPINIT in the ICSF main panel, as shown in Figure A-20 on page 219.
218
HCR7750 -------------- Integrated Cryptographic Service Facility-------OPTION ===> Enter the number of the desired option. 1 2 3 4 5 6 7 8 9 COPROCESSOR MGMT MASTER KEY OPSTAT ADMINCNTL UTILITY PPINIT TKE KGUP UDX MGMT Management of Cryptographic Coprocessors Master key set or change, CKDS/PKDS Processing Installation options Administrative Control Functions ICSF Utilities Pass Phrase Master Key/CKDS Initialization TKE Master and Operational Key processing Key Generator Utility processes Management of User Defined Extensions
The Passphrase Initialization panel is displayed and the passphrase can be entered as shown in Figure A-21, along with the CKDS and PKDS dataset names so that these data sets can also be initialized with the Master Keys. ------------------- ICSF - Pass Phrase MK/KDS Initialization ---------------COMMAND ===> Enter your pass phrase and the names of the CKDS and PKDS: Pass Phrase (16 to 64 characters) ===> Enter the pass phrase here CKDS ===> hlq.csfckds' PKDS ===> hlq.csfpkds' Initialize the CKDS and PKDS? (Y/N) ===> Y Initialize new online coprocessors only ? (Y/N) ===> N
After the successful passphrase initialization, the status of the coprocessor domain is changed as shown in Figure A-22 on page 220.
219
---------------------- ICSF - Coprocessor Hardware Status -------------------CRYPTO DOMAIN: 1 REGISTER STATUS + Crypto Serial Number Status Symmetric-Keys Master Key New Master Key register Verification pattern Hash pattern : 94000264 : ACTIVE EMPTY COPROCESSOR E01 More:
: : : : Old Master Key register : Verification pattern : Hash pattern : : Current Master Key register : Verification pattern : Hash pattern : : Asymmetric-Keys Master Key New Master Key register : Hash pattern : : Old Master Key register : Hash pattern : : : Current Master Key register : Hash pattern : :
EMPTY
EMPTY
Figure A-22 Coprocessor hardware status panel showing valid Master keys initialized
220
Appendix B.
221
Sample code
Example: B-1 SAF sample
import com.ibm.os390.security.*; public class SAFClassesTest { public static void main(String[] args) { // check if Security Server is active if (PlatformSecurityServer.isActive()) System.out.println("Security Server is active."); else { System.out.println("Error: Security Server is not active."); return; } // check if resource type 'FACILITY' is active if (PlatformSecurityServer.resourceTypeIsActive("FACILITY")) System.out.println("FACILITY is active"); else { System.out.println("Error: FACILITY is not active"); return; } // find out current user String currentUser = PlatformThread.getUserName(); System.out.println("CurrentUser is:"+currentUser); // find out if current user has has READ access to the resource named // BPX.SERVER of resource type FACILITY PlatformReturned pr = PlatformAccessControl.checkPermission("FACILITY","BPX.SERVER", PlatformAccessLevel.READ ); if (pr == null) System.out.println("User has READ access to the resource named BPX.SERVER of resource type FACILITY"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success + "\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } pr = PlatformUser.authenticate(currentUser,"secret"); if (pr == null) { System.out.println("Password check was successful"); } else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success +
222
"\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } boolean isMember = PlatformUser.isUserInGroup(currentUser,"SYS1"); if (isMember) { System.out.println(currentUser + " is a member of SYS1"); } else { System.out.println(currentUser + " is not a member of SYS1"); } pr = PlatformUser.changePassword(currentUser,"secret","passwd"); if (pr == null) System.out.println("Password change successful.\n"); else { System.out.println("An error ocurred ..."); System.out.println( "success: " + pr.success + "\nerrno: " + pr.errno + "\nerrno2: " + pr.errno2 + "\nerrnoMsg: " + pr.errnoMsg ); } } }
223
224
Appendix C.
225
import com.ibm.eserver.zos.racf.userregistry.*; import com.ibm.security.userregistry.*; import javax.naming.directory.*; public class CreateTSOUserid { public static void main(String[] args) { SecAdmin racfAdmin = null; User catuser = null; // Instantiate RACF_remote object with connection data: RACF_remote remote = new RACF_remote("ldap://wtsc60.itso.ibm.com:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); // Create a new RACF_SecAdmin object. This will create connection to RACF // database with authority of userid provided in RACF_remote object. try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } // Define the user attributes and create the user try { BasicAttributes ba = new BasicAttributes(); BasicAttribute pwd = new BasicAttribute("base_password"); pwd.add("meow"); // cat simply has to enter meow to log on pwd.add("noexpired"); ba.put(pwd); ba.put(new BasicAttribute("TSO")); catuser = (User)racfAdmin.createUser("cat", ba); System.out.println("You have successfully created TSO user cat."); } catch (SecAdminException e) { System.out.println("Unable to create user 'cat'. "+e.getMessage()); return; } // Get the user attributes of the recently created user and display the // BASE_PASSWORD attribute try { BasicAttributes u_at = catuser.getAttributes(); System.out.println(u_at.get("BASE_PASSWORD"));
226
import com.ibm.eserver.zos.racf.userregistry.*; import com.ibm.security.userregistry.*; import javax.naming.directory.*; public class CreateProtectedUserid { public static void main(String[] args) { SecAdmin racfAdmin = null; User protect = null; // Instantiate RACF_remote object with connection data: RACF_remote remote = new RACF_remote("ldap://wtsc60.itso.ibm.com:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); // Create a new RACF_SecAdmin object. This will create connection to RACF // database with authority of userid provided in RACF_remote object. try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } // Define the user attributes and create the user try { BasicAttributes ba = new BasicAttributes(); BasicAttribute pwd = new BasicAttribute("base_password"); pwd.add("nopassword"); ba.put(pwd); protect = racfAdmin.createUser("protect", ba); System.out.println("Successfully created userid 'protect'."); } catch (SecAdminException e) { System.out.println("Unable to create user 'protect'. "+e.getMessage()); return; }
227
// Get the user attributes of the recently created user and display the // BASE_PASSWORD attribute try { BasicAttributes prot_at = protect.getAttributes(); System.out.println(prot_at.get("BASE_PASSWORD")); } catch (SecAdminException e) { System.out.println("Error retrieving attributes "+e.getMessage()); return; } } }
Deleting a user ID
Example C-3 illustrates how to delete a user from the security repository. It refers to the TSO RACF command REMOVE. To match with Example C-1 on page 226 and Example C-2 on page 227, users cat and protect are deleted here.
Example: C-3 DeleteUserid
public class DeleteUserid { public static void main(String[] args) { SecAdmin racfAdmin = null; User protect = null; // Instantiate RACF_remote object with connection data: RACF_remote remote = new RACF_remote("ldap://wtsc60.itso.ibm.com:389", "simple", "IBMUSER", "SECRET", // password during testing "o=itsoracf"); // Create a new RACF_SecAdmin object. This will create connection to RACF // database with authority of userid provided in RACF_remote object. try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } // Now delete the userids we just created, so the testcase can be run // repeatedly. try { racfAdmin.deleteUser("protect"); System.out.println("Successfully deleted userid 'protect'."); racfAdmin.deleteUser("cat"); 228
Java Security on z/OS - The Complete View
System.out.println("Successfully deleted userid 'cat'."); } catch (Exception e) { System.out.println("Exception deleting user protect: "+e.getMessage()); } } }
Showing attributes
Example C-4 refers to the TSO RACF command LISTUSER. This code will extract the user attributes for user Martina and the group attributes and membership attributes for group SYS1. The output is a string containing an HTML table that should be displayed in a Web browser.
Example: C-4 ShowAttributes
import com.ibm.eserver.zos.racf.userregistry.*; import com.ibm.security.userregistry.*; public class ShowAttributes { public static void main(String[] args) { SecAdmin racfAdmin = null; User ibmuser = null; UserGroup ibmgroup = null; // Instantiate RACF_remote object with connection data: RACF_remote remote = new RACF_remote("ldap://9.12.4.18:389", "simple", "IBMUSER", "secret", // password during testing "o=itsoracf"); // Create a new RACF_SecAdmin object. This will create connection to RACF // database with authority of userid provided in RACF_remote object. try { racfAdmin = new RACF_SecAdmin(remote); } catch (SecAdminException e) { System.out.println("Unable to connect to specified RACF database. "+e.getMessage()); return; } try { ibmuser = racfAdmin.getUser("MARTINA"); ibmgroup = racfAdmin.getGroup("SYS1"); } catch (SecAdminException e) { e.printStackTrace(); } System.out.print(" RACF_User.attributesHTML, RACF_Group.attributesHTML and RACF_Group.membershipAttributesHTML. ");
229
System.out.println(" The output should be displayed in a web browser."); System.out.println(" "); System.out.println("------------- Start of output from RACF_User.attributesHTML------------\n"); System.out.println(((RACF_User) ibmuser).attributesHTML()); System.out.println("------------- End of output from RACF_User.attributesHTML------------\n"); System.out.println("------------- Start of output from RACF_Group.attributesHTML------------"); System.out.println(((RACF_Group) ibmgroup).attributesHTML()); System.out.println("------------- End of output from RACF_Group.attributesHTML------------"); System.out.println("------------- Start of output from RACF_Group.membershipAttributesHTML------------"); System.out.println(((RACF_Group) ibmgroup).membershipAttributesHTML()); System.out.println("------------- End of output from RACF_Group.membershipAttributesHTML------------"); } }
public class SearchUsersAndGroups { public static void main(String[] args) { String search_string; InitialDirContext ctx = null; NamingEnumeration answer = null; if (args.length > 0)
230
{ search_string = args[0]; } else search_string = ""; // // // // // We define a RACF_remote object not to get a RACF_SecAdmin object, but simply because this is how we have defined our connection information in all the other samples. We use the RACF_remote object in such a way that the rest of the code could be cut and pasted into code that was using JSec.
RACF_remote remote = new RACF_remote("ldap://9.12.4.18:389", "simple", "IBMUSER", "secret", // password during testing "o=itsoracf"); // The following code is using LDAP/SDBM to connect to RACF String ldap_suffix = remote.getConnect_suffix(); // diff for each system
try { SecAdmin racfAdmin = new RACF_SecAdmin(remote); if (racfAdmin != null) { Hashtable hashtable = new Hashtable(7); hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); hashtable.put(Context.PROVIDER_URL, remote.getConnect_url() ); // if second parm to RACF_REMOTE is 'secure' then use 'ssl' here hashtable.put(Context.SECURITY_AUTHENTICATION, "simple"); String dn = "racfid=" + remote.getConnect_principal() + ",profiletype=user," + remote.getConnect_suffix(); hashtable.put(Context.SECURITY_PRINCIPAL, dn); hashtable.put(Context.SECURITY_CREDENTIALS, remote.getConnect_credentials()); try { // Create initial context ctx = new InitialDirContext(hashtable); } catch (NamingException e) { System.out.println("Error initially connecting to LDAP/SDBM."+e.getMessage()); } // Initialize some parameters we'll need String[] attrIDs = {"racfid"}; SearchControls ctls = new SearchControls(); ctls.setReturningAttributes(attrIDs); // Specify the search scope ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
231
String filter = "racfid="+search_string+"*"; System.out.println("filter looks like: "+filter); // the specific code for searching for users try { answer = ctx.search("profiletype=user,"+ldap_suffix, filter,ctls); } catch (javax.naming.NamingException ne) { String e_text = ne.getMessage(); if (e_text.toUpperCase().indexOf("NO ENTRIES MEET SEARCH CRITERIA") > -1) answer = null; else throw ne; } // Display any userids we find if (answer != null) { while (answer.hasMoreElements()) { SearchResult sr = (SearchResult)answer.next(); System.out.println("Userid: " + deLDAP(sr.getName())); } } else System.out.println("System didn't find matching user"); // the specific code for searching for groups try { answer = ctx.search("profiletype=group,"+ldap_suffix, filter,ctls); } catch (javax.naming.NamingException ne) { String e_text = ne.getMessage(); if (e_text.toUpperCase().indexOf("NO ENTRIES MEET SEARCH CRITERIA") > -1) answer = null; else throw ne; } // Display any groupnames we find if (answer != null) { while (answer.hasMoreElements()) { SearchResult sr = (SearchResult)answer.next(); System.out.println("Group: " + deLDAP(sr.getName())); } } else System.out.println("System didn't find matching group"); } // end if racf_admin is not null } catch (Exception e) { System.out.println("Exception in SearchUsersAndGroups.java " + e.getMessage() + "\n"); e.printStackTrace();
232
} } /** * * @param in String that may or may not be a userid or groupname in LDAP DN * format * @return String that is striped of any LDAP stuff * * example: in: "racfid=IBMUSER,profiletype=USER,o=racfdb,c=us" * returns "IBMUSER" */ protected static String deLDAP(String in) { if (in == null) return in; // protect against bad input
String out; String lower_in = in.toLowerCase(); String racfid = "racfid="; int pos = lower_in.indexOf("racfid="); if (pos > -1) { int comma = in.indexOf(',',pos); if (comma > -1) out = in.substring(pos+racfid.length(),comma); else out = in.substring(pos+racfid.length()); return out; } else return in; } }
233
234
Appendix D.
JSec attributes
This appendix provides an overview of all Java Security Administration API (JSec) attributes that can be returned for a user, a group, or for membership in a group by RACF. It also includes a description of each attribute.
235
User attributes
Table D-1 lists and describes the 135 user attributes that can be returned from RACF using the JSEC API.
Table D-1 User attributes Attribute name Description Modifiable Segment Boolean attribute Yes Multi-val ue attribute No
BASE_ADSP
All permanent tape and DASD data sets created by user are automatically RACF-protected by discrete profiles. Indicates user has full responsibility for auditing the use of system resources, and is able to control the logging of detected accesses to any RACF-protected resources during RACF authorization checking and accesses to the RACF database. Names of installation-defined security categories, which must be defined as members of the CATEGORY profile in the SECDATA class. Classes in which user is allowed to define profiles to RACF for protection. Classes can be USER, and any resource classes defined in the class descriptor table. The date this user was defined to RACF. Up to 255 characters of installation-defined data. Days of week user is allowed access system from a terminal Allowed values: ANYDAY, WEEKDAYS, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY. Name of RACF group that is the default group for user. Indicates that any group data sets protected by DATASET profiles defined by this user are automatically accessible to other users in the group.
Yes
No
BASE_AUDITOR
Yes
No
Yes
No
BASE_CATEGORY
Yes
No
No
Yes
BASE_CLAUTH
Yes
No
No
Yes
BASE_CREATED
No Yes Yes
No No No
No No No
No No Yes
BASE_DATA
BASE_DAYS
BASE_DFLTGRP
Yes Yes
No No
No Yes
No No
BASE_GRPACC
236
Attribute name
Description
Modifiable
Segment
Boolean attribute No No
Multi-val ue attribute No No
BASE_LAST-ACCESS
The date and time the user last entered the system. Name of discrete data set profile used as model when new data set profiles are created that have this user ID as the high-level qualifier. User's name - a name associated with user ID - maximum of 20 characters. User has OPERATIONS segment. RACF user ID or groupname of owner of this user ID. The password change interval (in number of days). The date the user's password was last updated. When setting, value is new password. When getting, simply indicates if user has password or is restricted user ID (no password). User's password, encrypted in PKCS#7 envelope. Only returned if password enveloping has been set up and user ID that authenticated in RACF_SecAdmin constructor has digital certificate on IRR.PWENV.KEYRING keyring. The user's pass phrase. A text string of 14-100 characters. Date user's pass phrase was last changed. Indicates global access checking is bypassed when resource access checking is performed for this user, and neither ID(*) on the access list or the UACC will allow access. Date when RACF will resume allowing the user access to the system. Date in format mm/dd/yy.
No Yes
No No
BASE_MODEL
BASE_NAME
Yes
No
No
No
BASE_OPERATIONS
No No No No No
Yes No No No No
No No No No No
BASE_OWNER
BASE_PASS-INTERVAL
BASE_PASSDATE
BASE_PASSWORD
BASE_PASSWORD_ENV
No
No
No
No
BASE_PHRASE
Yes No Yes
No No No
No No Yes
No No No
BASE_RESUME
Yes
No
No
No
237
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
BASE_REVOKE
Date when RACF will stop allowing the user access to the system. Date in format mm/dd/yy. User's access to the system is currently revoked. Installation-defined security label that is user's default security label. User's security level, where seclevel-name is an installation-defined name that must be a member of the SECLEVEL profile in the SECDATA class. Indicates user is allowed to issue all RACF commands with all operands except operands that require AUDITOR attribute. Time of day user is allowed access system from a terminal. Format is start-time:end-time and each time's format is hhmm, where hh is the hour (00-23) and mm is the minutes (00-59). But 0000 is not a valid time value. If start-time is greater than end-time, interval spans midnight. Indicates RACF is to log all RACROUTE REQUEST=AUTH and RACROUTE REQUEST=FASTAUTH services eligible for logging, and all RACROUTE REQUEST=DEFINE services issued for the user, and all RACF commands (except SEARCH, LISTDSD, LISTGRP, LISTUSER, and RLIST) issued by user. User ID. User has CICS segment. Numbers 1-24, representing classes assigned to this operator to which basic mapping support (BMS) messages are to be routed. A 1-3 character identification of the operator for use by BMS.
Yes
No
BASE_REVOKED
No Yes
No No
Yes No
No No
BASE_SECLABEL
BASE_SECLEVEL
Yes
No
No
No
BASE_SPECIAL
Yes
No
Yes
No
BASE_TIME
Yes
No
No
No
BASE_UAUDIT
Yes
No
Yes
No
No Yes Yes
No Yes No
No Yes No
No No Yes
CICS_OPIDENT
Yes
No
No
No
238
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
CICS_OPPRTY
Number from 0-255 that represents the priority of the operator. Specifies the resource security level (RSL) keys assigned to the user. Numbers from 1 - 24 or 0 (meaning no RSL keys are assigned to the user) or 99 (meaning 1 through 24 are assigned to the user). Time, in hours and minutes, that the operator is allowed to be idle before being signed off. The value for TIMEOUT can be entered in the form m, mm, hmm, or hhmm, where the value for m or mm is 00-59, or 00-60 if h or hh is not specified or is specified as 0 or 00. Specifies the transaction security level (TSL) keys assigned to the user. Numbers from 1 - 64 or 0 (meaning no TSL keys are assigned to the user) or 99 (meaning 1 through 64 are assigned to the user). Indicates whether the user is signed off by CICS when an XRF takeover occurs. Valid values 'FORCE', 'NOFORCE'. User has DCE segment. Indicates z/OS UNIX DCE is to log this user into z/OS UNIX DCE automatically. The DCE principal name defined for this RACF user in the DCE registry. 1 - 1023 characters. The DCE cell name defined for this RACF user. 1 - 1023 characters. RACF checks that the HOMECELL name entered has a prefix of either /.../ or /.:/
Yes
No
CICS_RSLKEY
Yes
No
No
Yes
CICS_TIMEOUT
Yes
No
No
No
CICS_TSLKEY
Yes
No
No
Yes
CICS_XRFSOFF
Yes
No
No
No
DCE DCE_AUTOLOGIN
Yes Yes
Yes No
Yes Yes
No No
DCE_DCENAME
Yes
No
No
No
DCE_HOMECELL
Yes
No
No
No
239
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
DCE_HOMEUUID
The DCE universal unique identifier (UUID) for the cell that this user is defined to. The UUID is a 36-character string that consists of numeric and hexadecimal characters. This string must have the delimiter character (-) in positions 9, 14, 19, and 24. The general format for the UUID string is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx xxxxxx, in which x represents a valid numeric or hexadecimal character. The DCE universal unique identifier (UUID) of the DCE principal defined in DCENAME. The UUID is a 36-character string that consists of numeric and hexadecimal characters. This string must have the delimiter character (-) in positions 9, 14, 19, and 24. The general format for the UUID string is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxx xxxxxx, in which x represents a valid numeric or hexadecimal character. User has DFP segment. An 8-character DFP data application identifier. The default data class. 1-8 characters. The default management class. 1-8 characters. The default storage class. 1-8 characters. User has EIM segment. Name of a profile in the LDAPBIND class. The profile in the LDAPBIND class contains the name of an EIM domain and the bind information required to establish a connection with the EIM domain. 1-246 characters. User has KERB segment.
Yes
No
DCE_UUID
Yes
No
No
No
DFP DFP_DATAAPPL
Yes No No No No Yes No
Yes No No No No Yes No
No No No No No No No
DFP_DATACLAS
DFP_MGMTCLAS
DFP_STORCLAS
EIM EIM_LDAPPROF
KERB
Yes
Yes
Yes
No
240
Attribute name
Description
Modifiable
Segment
Boolean attribute No
KERB_ENCRYPT
ENCRYPT values are used to specify which keys are allowed for use based on the encryption algorithm used to generate them. Default values will be provided for any values not specified. Examples: 'DES','DES3' and 'DESD'. User's local kerberos-principal-name, may contain any characters except '@'. Must not be qualified with a realm name. However, RACF verifies that the local principal name, when fully qualified with the name of the local realm: '/.../local_realm_name/principal_ name' does not exceed 240 characters. Current Network Authentication Service key version. The max-ticket-life in seconds, and is represented by a numeric value between 1 and 2147483647. User has LANGUAGE segment. User's primary language. Specified as either an installation-defined name of a currently active language (maximum of 24 characters) or one of the language codes (three characters in length) for a language installed on your system. User's secondary language. Specified as either an installation-defined name of a currently active language (maximum of 24 characters) or one of the language codes (three characters in length) for a language installed on your system. User has LNOTES segment. Lotus Notes for z/OS short-name of the user. 1-64 characters, consisting of alphanumeric characters or '&', '-', '.', '_', and a blank.
Yes
No
KERB_KERBNAME
Yes
No
No
No
KERB_KEYVERSION
No Yes
No No
No No
No No
KERB_MAXTKTLFE
LANGUAGE LANGUAGE_PRIMARY
Yes Yes
Yes No
Yes No
No No
LANGUAGE_SECONDARY
Yes
No
No
No
LNOTES LNOTES_SNAME
Yes Yes
Yes No
Yes No
No No
241
Attribute name
Description
Modifiable
Segment
Multi-val ue attribute No No
NDS NDS_UNAME
User has NDS segment. Novell Directory Services for OS/390 user-name of the user. 1-246 characters excluding the following characters: '*', '+', '|', '=', ',', '"', '`', '/', ':', ';', '', '[', ']' User has NETVIEW segment. Specifies the default master console station (MCS) console name used for this operator. 1 - 8 character name. Indicates whether a security check is performed for this NetView operator when they try to use a span or try to do a cross-domain logon. Allowed values 'GENERAL','GLOBAL' or 'SPECIFIC'. Specifies the identifiers of NetView programs in another NetView domain where this operator can start a cross-domain session. Each identifier is 1-5 characters, with valid characters being 0-9, A-Z, #, $, or @. The command or command list (up to 255 characters) to be processed by NetView for this operator when this operator logs on to NetView. Indicates this operator is to receive unsolicited messages that are not routed to a specific NetView operator. Indicates a NetView operator has administrator authority to the NetView Graphic Monitor Facility (NGMF). NetView scope classes for which the operator has authority. Each class is a number from 1 to 2040. User has OMVS segment.
Yes Yes
Yes No
NETVIEW NETVIEW_CONSNAME
Yes Yes
Yes No
Yes No
No No
NETVIEW_CTL
Yes
No
No
No
NETVIEW_DOMAINS
Yes
No
No
Yes
NETVIEW_IC
Yes
No
No
No
NETVIEW_MSGRECVR
Yes
No
Yes
No
NETVIEW_NGMFADMN
Yes
No
Yes
No
NETVIEW_OPCLASS
Yes
No
No
Yes
OMVS
Yes
Yes
Yes
No
242
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
OMVS_ASSIZEMAX
The RLIMIT_AS hard limit resource value (maximum address space region size) that processes receive when dubbed a process. Integer value between 10485760 and 2147483647. The RLIMIT_CPU hard limit (maximum) resource value that user's z/OS UNIX processes receive when they are dubbed a process. Numeric value between 7 and 2147483647, indicates the cpu-time in seconds that a process is allowed to use. Maximum number of files this user is allowed to have concurrently active or open. Numeric value between 3 and 524287. User's z/OS UNIX initial directory pathname, 1-1023 characters. Specifies the maximum number of bytes of nonshared memory that can be allocated by the user. The nonshared-memory-size you define to RACF is a numeric value between 0 and 16777215, followed by the letter M, G, or T. The M, G, or T letter indicates the multiplier to be used. (M=Megabyte, G Gigabyte, T=Terabyte, P=Petabyte). Maximum value is 16383P. Maximum amount of data space storage, in pages, that can be allocated by the user for memory mappings of HFS files. Numeric value between 1 and 16,777,216. Maximum number of processes user is allowed to have active at the same time, regardless of how the process became a z/OS UNIX process. Numeric value between 3 and 32767.
Yes
No
OMVS_CPUTIMEMAX
Yes
No
No
No
OMVS_FILEPROCMAX
Yes
No
No
No
OMVS_HOME
Yes Yes
No No
No No
No No
OMVS_MEMLIMIT
OMVS_MMAPAREAMAX
Yes
No
No
No
OMVS_PROCUSERMAX
Yes
No
No
No
243
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
OMVS_PROGRAM
Specifies the PROGRAM pathname (z/OS UNIX shell program). The first program started when TSO/E command OMVS is entered or when a batch job is started using the BPXBATCH program, 1-1023 characters. The maximum number of bytes of shared memory that can be allocated by user. The shared-memory-size you define to RACF is a numeric value between 1 and 16,777,215, followed by the letter M, G, T, or P. The M, G, T, or P letter indicates the multiplier to be used. (M=Megabyte, G Gigabyte, T=Terabyte, P=Petabyte). Maximum value is 16383P. Maximum number of pthread_create threads, including those running, queued, and exited but not detached, that the user can have concurrently active. Numeric value between 0 and 100000. The UID, numeric value between 0 and 2147483647. 'AUTOUID' value can be used when BPX.NEXT.USER profile is defined in the FACILITY class. SHARED value can be used when the SHARED.IDS profile in the UNIXPRIV class is defined. See z/OS Security Server RACF Security Administrator's Guide for details. User has OPERPARM segment. The console group used in recovery. 1-8 characters, with valid characters being 0-9, A-Z, #, $, or @.
Yes
No
OMVS_SHMEMMAX
Yes
No
No
No
OMVS_THREADSMAX
Yes
No
No
No
OMVS_UID
Yes
No
No
Yes
OPERPARM OPERPARM_ALTGRP
Yes Yes
Yes No
Yes No
No No
244
Attribute name
Description
Modifiable
Segment
Boolean attribute No
OPERPARM_AUTH
Authority this console has to issue operator commands. Valid values, 'MASTER', 'ALL', 'INFO' (these three cannot be combined with other values) and 'CONS', 'IO' and 'SYS'. See ALTUSER in z/OS Security Server RACF Command Language Reference for more detailed description. Indicates the extended console can receive messages that have been automated by the Message Processing Facility (MPF) in the sysplex. Indicates the system to which commands issued from this console are to be sent. 1-8 characters, with valid characters being A-Z, 0-9, @ (X'7C'), # (X'7B'), and $ (X'5B'). If * is specified, commands are processed on the local system where the console is attached. Indicates whether this console receives delete operator message (DOM) requests. Allowed values 'NORMAL','ALL','NONE'. Indicates this console is to receive hardcopy messages. Indicates this console is to receive messages directed to console ID 0 (the internal console). A 1-8 byte character name that can be used to display information for all consoles with the specified key by using the MVS command DISPLAY CONSOLES,KEY. Valid characters are A-Z, 0-9, # (X'7B'), $ (X'5B'), or @ (X'7C'). Specifies the messages that this console is to receive. Can be a list of R, I, CE, E, IN, NB or ALL. If you specify ALL, you cannot specify R, I, CE, E, or IN.
Yes
No
OPERPARM_AUTO
Yes
No
Yes
No
OPERPARM_CMDSYS
Yes
No
No
No
OPERPARM_DOM
Yes
No
No
No
OPERPARM_HC
Yes Yes
No No
Yes Yes
No No
OPERPARM_INTIDS
OPERPARM_KEY
Yes
No
No
No
OPERPARM_LEVEL
Yes
No
No
Yes
245
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
OPERPARM_LOGCMDRESP
Indicates if command responses are to be logged. Value of 'SYSTEM' specifies that command responses are logged in the hardcopy log. Value of 'NO' specifies that command responses are not logged. Specifies the format in which messages are displayed at the console. Can be a combination of J, M, S, T, and X. Indicates a 1-byte migration ID is assigned to this console. Specifies which information should be displayed when jobs, TSO sessions, or data set status are being monitored. Allowed values, 'JOBNAMES' OR 'JOBNAMEST' (mutually exclusive), 'SESS' or 'SESST' (mutually exclusive) or 'STATUS'. See ALTUSER in z/OS Security Server RACF Command Language Reference for a more detailed description. Specifies the systems from which this console can receive messages that are not directed to a specific console. Each system-name can be any combination of A-Z, 0-9, #, $, or @. A name of '*' indicates the system on which the console is currently active. Routing codes of messages this console is to receive. Valid values are 'ALL' or one or more routing codes or sequences of routing codes. The routing codes can be list of n and n1:n2, where n, n1, and n2 are integers 1-128, and n2 is greater than n1. Amount of storage in the TSO/E user's address space that can be used for message queuing to this console. Valid values are 1 2000. Indicates that this console is to receive undelivered messages.
Yes
No
OPERPARM_MFORM
Yes
No
No
Yes
OPERPARM_MIGID
Yes Yes
No No
Yes No
No Yes
OPERPARM_MONITOR
OPERPARM_MSCOPE
Yes
No
No
Yes
OPERPARM_ROUTCODE
Yes
No
No
Yes
OPERPARM_STORAGE
Yes
No
No
No
OPERPARM_UD
Yes
No
Yes
No
246
Attribute name
Description
Modifiable
Segment
Multi-val ue attribute No
OPERPARM_UNKNIDS
Indicates this console is to receive messages directed to console ID 0 (the internal console). User has OVM segment. The pathname for the file system root. 1 - 1023 characters. The initial directory pathname. 1 1023 characters. Specifies the PROGRAM pathname. 1 - 1023 characters. First program started when the OPENVM SHELL command is entered. OpenExtensions VM user identifier, UID. Numeric value between 0 and 2147483647. User has PROXY segment. The distinguished name (DN) which the z/OS LDAP Server will use when acting as a proxy on behalf of a requester. 1 - 1023 characters. Password which the z/OS LDAP Server will use when acting as a proxy on behalf of a requester. 1 128 characters. The URL of the LDAP server which the z/OS LDAP Server will contact when acting as a proxy on behalf of a requester. The URL should be in a format such as ldap://123.45.6:389 10-1023 characters. A valid URL must start with either ldap:// or ldaps:// and is not case-sensitive. User has TSO segment. User's default TSO account number when logging on through the TSO/E logon panel (1-39 characters). Command to be run during TSO/E logon (1 - 80 characters).
Yes
No
OVM OVM_FSROOT
Yes No No No
Yes No No No
No No No No
OVM_HOME
OVM_PROGRAM
OVM_UID
Yes
No
No
Yes
PROXY PROXY_BINDDN
Yes Yes
Yes No
Yes No
No No
PROXY_BINDPW
Yes
No
No
No
PROXY_LDAPHOST
Yes
No
No
No
TSO TSO_ACCTNUM
Yes Yes
Yes No
Yes No
No No
TSO_COMMAND
Yes
No
No
No
247
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
TSO_DEST
Default destination to which the user can route dynamically allocated SYSOUT data sets. The specified value must be 1-7 alphanumeric characters, beginning with an alphabetic or national character. User's default hold class. The specified value must be 1 alphanumeric character, excluding national characters. Specifies the user's default job class. The specified value must be 1 alphanumeric character, excluding national characters. Maximum region size user can request at logon. Number of 1024-byte units of virtual storage that TSO can create for the user's private address space. Integer between 0 and 65535 (inclusive) if database is shared with any MVS systems, or 0 through 2096128 if not shared. User's default message class. The specified value must be 1 alphanumeric character, excluding national characters. Name of the user's default logon procedure when logging on through the TSO/E logon panel. The name must be 1-8 alphanumeric characters and begin with an alphabetic character. User's security label if the user specifies one on the TSO logon panel. Region size - number of 1024-byte units of virtual storage available in user's private address space at logon when user does not request a region size at logon. Integer between 0 and 65535 (inclusive) if database is shared with any MVS systems, or 0 through 2096128 if not shared.
Yes
No
TSO_HOLDCLASS
Yes
No
No
No
TSO_JOBCLASS
Yes
No
No
No
TSO_MAXSIZE
Yes
No
No
No
TSO_MSGCLASS
Yes
No
No
No
TSO_PROC
Yes
No
No
No
TSO_SECLABEL
Yes
No
No
No
TSO_SIZE
Yes
No
No
No
248
Attribute name
Description
Modifiable
Segment
Boolean attribute No
Multi-val ue attribute No
TSO_SYSOUTCLASS
User's default SYSOUT class. The specified value must be 1 alphanumeric character, excluding national characters. Default name of a device or group of devices that a procedure uses for allocations. The specified value must be 1-8 alphanumeric characters. Optional installation data, 4 characters where valid characters are 0 through 9 and A through F. User has WORKATTR segment. An account number for APPC/MVS processing. 1 to 255 characters. Address Line 1 that SYSOUT information is to be delivered to. 1 to 60 characters. Address Line 2 that SYSOUT information is to be delivered to. 1 to 60 characters. Address Line 3 that SYSOUT information is to be delivered to. 1 to 60 characters. Address Line 4 that SYSOUT information is to be delivered to. 1 to 60 characters. Building that SYSOUT information is to be delivered to. 1 to 60 characters. Department that SYSOUT information is to be delivered to. 1 to 60 characters. Name of the user that SYSOUT information is to be delivered to. 1 to 60 characters. Room that SYSOUT information is to be delivered to. 1 to 60 characters.
Yes
No
TSO_UNIT
Yes
No
No
No
TSO_USERDATA
Yes
No
No
No
WORKATTR WORKATTR_WAACCNT
Yes Yes
Yes No
Yes No
No No
WORKATTR_WAADDR1
Yes
No
No
No
WORKATTR_WAADDR2
Yes
No
No
No
WORKATTR_WAADDR3
Yes
No
No
No
WORKATTR_WAADDR4
Yes
No
No
No
WORKATTR_WABLDG
Yes
No
No
No
WORKATTR_WADEPT
Yes
No
No
No
WORKATTR_WANAME
Yes
No
No
No
WORKATTR_WAROOM
Yes
No
No
No
249
Group attributes
Table D-2 lists and describes the 18 group attributes that can be returned from RACF using JSEC API.
Table D-2 Group attributes Attribute name BASE_CREATED BASE_DATA BASE_GROUPNAME BASE_MODEL Description The date this group was defined to RACF. Up to 255 characters of installation-defined data. Name of the group. Name of a data set profile that RACF is to use as a model when new data set profiles are created that have groupname as the high-level qualifier. RACF user ID or groupname of owner of this group. Groups that have this group as their superior group. Name of the RACF-defined group that is the superior group for this group. Indicates during terminal authorization checking, RACF is to allow the use of the universal access authority for a terminal when it checks whether a user in the group is authorized to access a terminal. Specifies that this is a universal group that allows an effectively unlimited number of users to be connected to it for the purpose of resource access. Group has DFP segment. An 8-character DFP data application identifier. The default data class. 1-8 characters. The default management class. 1-8 characters. The default storage class. 1-8 characters. Group has OMVS segment. Modifiable No Yes No Yes Segment No No No No Boolean attribute No No No No Multi-value attribute No No No No
Yes No Yes
No No No
No No No
No Yes No
BASE_TERMUACC
Yes
No
Yes
No
BASE_UNIVERSAL
Yes
No
Yes
No
Yes No No No No Yes
Yes No No No No Yes
No No No No No No
250
Description The group ID, GID, numeric value between 0 and 2147483647. 'AUTOGID' value can be used when BPX.NEXT.USER profile is defined in the FACILITY class. SHARED value can be used when the SHARED.IDS profile in the UNIXPRIV class is defined. See z/OS Security Server RACF Security Administrator's Guide for details. Group has OVM segment. OpenExtensions VM group identifier. The GID is a numeric value between 0 and 2147483647.
Modifiable Yes
Segment No
Boolean attribute No
OVM OVM_GID
Yes Yes
Yes No
Yes No
No No
Membership attributes
Table D-3 lists and describes the 14 membership attributes that can be returned from RACF using JSEC API.
Table D-3 Membership attributes Attribute name BASE_ADSP Description Indicates when user is connected to this group, all permanent tape and DASD data sets created by the user are RACF-protected by discrete profiles. Indicates user is to have the group-AUDITOR attribute when connected to this group. Specifies the level of authority user is to have in the group. Valid group authority values are 'USE', 'CREATE', 'CONNECT', and 'JOIN'. Date user was added to group. Number of times user has entered the system with this group as the current connect group. Indicates when user is connected to this group, any group data sets defined by the user are automatically accessible to other users in the group. Modifiable Yes Segment No Boolean attribute Yes Multi-value attribute No
BASE_AUDITOR
Yes
No
Yes
No
BASE_AUTHORITY
No
No
No
BASE_CONNECT-DATE BASE_CONNECTS
No No
No No
No No
No No
BASE_GRPACC
Yes
No
Yes
No
251
Description Date user last entered the system using this group as the current connect group. Indicates user is to have the group-OPERATIONS attribute when connected to this group. The group-OPERATIONS user has authorization to do maintenance operations on all RACF-protected DASD data sets, tape volumes, and DASD volumes within the scope of the group unless the access list for a resource specifically limits the OPERATIONS user to an access authority that is less than the operation requires. RACF-defined user or group to be assigned as the owner of the membership (connect profile). Defaults to the user who added user to group. Date when user's membership in the group will be restored or resumed. Date when user's membership in the group will be revoked. User's membership to the group is currently revoked. User is to have the group-SPECIAL attribute when connected to this group. Default value for the universal access authority for new resource profiles the user defines while connected to the group. Valid values are: ALTER, CONTROL, UPDATE, READ, and NONE.
Modifiable No
Segment No
Boolean attribute No
Multi-value attribute No
BASE_OPERATIONS
Yes
No
Yes
No
BASE_OWNER
No
No
No
BASE_RESUME
Yes
No
No
No
Yes No Yes
No No No
No Yes Yes
No No No
BASE_UACC
Yes
No
No
No
252
Appendix E.
253
public class EimJavaSetup { /** * @param args */ public static void main(String[] args) throws EimException { // Cleanup first delete(); // Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); // Retrieve a domain String ldapUrl = "ldap://9.12.4.18/ibm-eimdomainname=eimJavaDemo,o=itso,c=us"; Domain myJavaDomain = domainMgr.createDomain(ldapUrl, connectInfo, ""); // Add a system registry Registry racfReg = myJavaDomain.addSystemRegistry("demoSysReg_RACF", Registry.EIM_REGTYPE_RACF, "description", "uri"); // Add a system registry Registry javaReg = myJavaDomain.addSystemRegistry("demoSysReg_JAVADEMO", Registry.EIM_REGTYPE_LDAP, "description", "uri"); // Add a user identifier Eid identifier = myJavaDomain.addEid("demoIdentifier", "description"); // Associate the identifier with the users in various registries identifier.addAssociation(Association.EIM_SOURCE, javaReg.getName(), "javauser@us.ibm.com"); identifier.addAssociation(Association.EIM_TARGET, racfReg.getName(), "javausr"); } /** * Ensure that the domain is deleted before creating * @throws EimException */ private static void delete(){
254
// Specify the connection information ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); // Get an instance of the domain manager DomainManager domainMgr = DomainManager.getInstance(); try{ // Retrieve a domain String ldapUrl = "ldap://9.12.4.18/ibm-eimdomainname=eimJavaDemo,o=itso,c=us"; Domain myJavaDomain = domainMgr.getDomain(ldapUrl, connectInfo); // Delete all registries Set regs = myJavaDomain.getRegistries(); Iterator regIter = regs.iterator(); while(regIter.hasNext()) ((Registry) (regIter.next())).delete(); // Delete all identifiers Set eids = myJavaDomain.getEids(); Iterator eidIter = eids.iterator(); while(eidIter.hasNext()) ((Eid) (eidIter.next())).delete(); myJavaDomain.delete(); } catch(EimException e){} // Ignore exception that domain already exists } }
255
package eimjavademo; import java.util.Hashtable; public class EimJavaAuth { private static Hashtable lookupTable = new Hashtable(); // Populate the lookup table with userid/password pairs static { lookupTable.put("javauser@us.ibm.com", "secret"); lookupTable.put("javausr2@us.ibm.com", "secret2"); } /** * Authenticates the off-platfrom userid and password. This API is just a * stub in place of an authentication mechanism. * * @param userid The off-platform userid. * @param password The off-platform password. * @return true, if verifification succeeds and false, if verification fails. */ public static boolean login(String userid, String password){ boolean result = false; // Lookup the userid to retrieve the password String pw = (String) lookupTable.get(userid); // If the passwords match, then login is successful if(pw != null && pw.equals(password)) result = true; return result; } }
256
package eimjavademo; import java.util.Set; import javax.naming.directory.BasicAttributes; import import import import import import import import import import com.ibm.eim.ConnectInfo; com.ibm.eim.Domain; com.ibm.eim.DomainManager; com.ibm.eim.RegistryUser; com.ibm.eserver.zos.racf.IRRPassTicket; com.ibm.eserver.zos.racf.IRRPassTicketGenerationException; com.ibm.eserver.zos.racf.userregistry.RACF_SecAdmin; com.ibm.eserver.zos.racf.userregistry.RACF_remote; com.ibm.security.userregistry.SecAdminException; com.ibm.security.userregistry.User;
public class EimJavaDemo { /** * This method authenticates the specified non-z/OS userid and password. Then * it maps that user to a z/OS user. It creates a passticket for the z/OS user * which is used to bind to JSEC and create the new RACF userid specified. * * @param args args[0]=off-platform userid, args[1]=off-platform password, * args[2]= RACF user to be created */ public static void main(String[] args) throws Exception { // Verify the three arguments are passed in if(args.length != 3){ System.out.println("Usage: java EimJavaDemo [userid] [password] [newRACFuserid]"); System.exit(0); } // Authenticate the off-platform user String userid = args[0]; String password = args[1]; String newRACFuserid = args[2];
257
if(!EimJavaAuth.login(userid, password)){ System.out.println("LOGIN Error: Please re-enter the userid and password"); System.exit(0); } // Connect to the EIM domain ConnectInfo connectInfo = new ConnectInfo("cn=ldap_administrator", "secret"); DomainManager domainMgr = DomainManager.getInstance(); Domain myJavaDomain = domainMgr.getDomain("ldap://9.12.4.18/ibm-eimdomainname=eimJavaDemo,o=itso,c=us", connectInfo); // Use EIM to map the off-platform user id to a RACF user id Set regUsers = myJavaDomain.findTargetFromSource(userid, "demoSysReg_JAVADEMO", "demoSysReg_RACF"); RegistryUser regUser = ((RegistryUser) regUsers.iterator().next()); String racfUser = regUser.getTargetUserName(); // Generate a passticket for the RACF user String racfPassticket = null; String appl = "ITDS1"; // Must match PTKTDATA IRRPTAUTH.ITDS1.JUSTJAVA profile try { IRRPassTicket ticket = new IRRPassTicket(); racfPassticket = ticket.generate(racfUser, appl); } catch (IRRPassTicketGenerationException e) { System.out.println("Passticket ERROR: " + e); e.printStackTrace(); } // Create a new user with JSEC RACF_remote racfConnection = new RACF_remote("ldap://9.12.4.18", "simple", racfUser, racfPassticket, "o=itsoracf"); RACF_SecAdmin admin = new RACF_SecAdmin(racfConnection); try{ // Delete the user if it already exists admin.deleteUser(newRACFuserid); } catch (SecAdminException e){} // Ignore exception that user doesn't already exist try{ BasicAttributes userAttr = new BasicAttributes(); admin.createUser(newRACFuserid, userAttr); User user = admin.getUser(newRACFuserid); // List the user System.out.println(user.getAttributes().toString()); } catch (SecAdminException e){ System.out.println("JSEC ERROR: User already exists or could not create user"); e.printStackTrace(); } } }
258
Appendix F.
Basics of cryptography
This appendix introduces some basic cryptographic concepts. The following topics are covered: Cryptographic algorithms Symmetric key algorithms Asymmetric key algorithms Additional functions Padding Encryption modes Hybrid encryption Digital signature Certificates
259
Introduction to cryptography
The word cryptography originates from the Greek words kryptos, which means hidden and grfo, which means to write or to speak. Cryptography deals with securing information by transforming it using cryptographic algorithms. This transformation is performed so that the real form cannot be revealed without special information. This special information is referred to as the key. The process of transforming data from clear text into a hidden form is called encryption. And the reverse transformation, from a hidden form into clear text, is called decryption.
Cryptographic algorithms
Currently there are two categories of cryptographic algorithms intended for encrypting and decrypting data: symmetric key algorithms and asymmetric key algorithms.
Message in clear
Secret message
Encrypted message
tQ${3Lo9*s42
Message in clear
Secret message
Symmetric key algorithms perform comparatively faster than asymmetric algorithms, but the key management stage can increase rapidly in complexity when several parties are involved, because the secret key needs to be distributed securely to everybody involved. Today, widely used symmetric algorithms include: DES, Triple-DES, Blowfish, and AES. Note: Even though DES is still in use, it is now considered to have too short a key for ensuring proper encryption strength. Currently it is recommended that you migrate to algorithms with longer keys, such as Triple-DES or AES.
260
Message in clear
Secret message
Encrypted message
$9?X+D23-42
Message in clear
Secret message
Compared to symmetric key algorithms, asymmetric algorithms are extremely heavy consumers of computing resources. They are usually reserved for encryption of short bursts of data, and are used in combination with symmetric key algorithms. One of the most widely used asymmetric algorithms today is RSA (Rivest-Shamir-Adleman).
Padding
Many encryption algorithms work by encrypting one block of clear text at a time. The size of these blocks depends on the algorithm used and the size of the keys. If the size of the data that needs to be encrypted does not reach a whole number of blocks, the data needs to be padded. This padding takes place before the data is encrypted, and it is removed at decryption time. Several padding schemes are in use today.
Encryption modes
When encrypting using standard encryption algorithms, two identical data elements that are encrypted with the same key and algorithm would end up looking the same when encrypted. Because normal encryption algorithms work in blocks, repeating patterns in the clear data can end up as repeating patterns in the encrypted data, as well. This would make it easier for someone to break the encryption.
261
One way to avoid this is by using the output of each block encryption to modify the input of the next sequential blocks encryption (for example, by an exclusive OR operation). In this way, all encrypted data blocks contribute to changing the pattern of the next encrypted block. To start up this process, a randomly generated initial value is used to change the encrypted output of the first block of data. This value is called an initialization vector, and it must also be known by the recipient of the encrypted data.
Hybrid encryption
Both symmetric and asymmetric cryptographic algorithms offer advantages and disadvantages. Symmetric algorithms are fast, but securely distributing the symmetric keys to many users may prove to be a very complex and cumbersome process. Conversely, asymmetric algorithms are slow and extremely demanding of computing resources, but they solve the key distribution problem because a public key does not require to be secured. Hybrid encryption attempts to exploit the advantages of both kinds of algorithm classes, while avoiding their disadvantages. Figure F-3 on page 263 shows how hybrid encryption works. When the sender of a message wants to send it encrypted to a recipient, the sender starts up the process by generating a random symmetric key that is used encrypt the secret message. The symmetric key is then encrypted using the recipients asymmetric public key. The final message that is sent to the recipient comprises two parts: the encrypted symmetric data key that will be recovered by the recipient using the recipients asymmetric private key, and the recovered symmetric key that will be used to decrypt the message. Note that this approach allows the exploitation of the symmetric encryption/decryption inherent efficiency for the transmitted data part. It also exploits the much simpler key management processes that asymmetric encryption/decryption offers. The cost of asymmetric encryption is kept to a minimum because it is expected that the symmetric key will be considerably shorter than the secret message itself.
262
Message in clear
Message in clear
Secret message
Encrypted message
KJ&5#%l@s42
Asymmetric encryption algorithm Random symmetric key Key pair Recipients private key
With hybrid encryption, the use of the random symmetric key is not necessarily limited to only encrypting one message. Instead, the key can be reused over the course of a communication session. In that case, the random symmetric key is sometimes referred as a session key. Hybrid encryption techniques are heavily used; a prominent example is the SSL/TLS protocol.
Digital signatures
Digital signature technology aims to provide the same guarantees that you expect from an handwritten signature, but at the scale, distance, and speed that electronics permit. A handwritten signature on a document makes it evidential, and a digital signature provides this same property to a transmitted message. The algorithms used for making up digital signatures are usually a combination of asymmetric cryptographic algorithms and one-way hash algorithms.
263
produce. It may happen that two different messages produce the same hash value. This is called a collision and is unavoidable when using one-way hashes. Cryptographic techniques are therefore used when designing one-way hash algorithms to make it extremely difficult for an attacker to find the necessary modifications to a given message so that it could again, though modified, produce the same hash value. Several families of algorithms aim to produce one-way hashes: Message Authentication Code (MAC), Message Detection Code (MDC), Message Digest (MD), Secure Hash Algorithm (SHA), and so on.
Message to sign
One-way-hash algorithm
Hash code
5BFA812B42
8Y%-@5L/42
264
8Y%-@5L/42
Asymmetric algorithm
Hash code
Received message
One-way-hash algorithm
Hash code
5BFA812B42
Digital signatures also play a key role in the generation of digital certificates as a proof of the integrity and origin of the digital certificate. Digital signatures are therefore a combination of one-way hash and asymmetric algorithms. Widely used combinations include MD2 with RSA, MD5 with RSA, SHA1 with RSA, SHA1 with DSA.
Digital certificates
In large uncontrolled networks, where everybody can publish their own public keys, there is a requirement to certify that the declared identity is actually the key owners identity. The method widely in use today to achieve this certification is to package ones public key in a file called a digital certificate. The digital certificate file contains, among other information, the public key value and the public key owners name, and is digitally signed by a Certificate Authority (CA). Certificate authorities have an administrative process in place to verify the identity of requestor and whether this identity, as it will be shown in the certificate, is unique. After this administrative process is successfully performed, a digital certificate is issued to the requestor. The content of the certificate is digitally signed by the CA with its private key. Because the CA makes its public key public in a CA certificate, all recipients of the certificate can use the CAs public key to verify the certificate digital signature, thus binding the public key value in the certificate to the owners (the subjects) identity, which is also shown in the certificate. Note that a certificate verification is to be performed by software, and the program that verifies certificates is set up to accept certificates of only selected CAs. These are the CAs that are trusted as per the installation trust policy. The prominent format in use today for digital certificates is X.509 V3 format, which is promoted by the IETF PKIX group. X.509 is a full standard for a public key infrastructure. It was originally developed in 1988 as part of the wider X.500 directory standards.
265
An X.509 V3 certificate contains the following information: Certificate fields Version Serial number Algorithm ID Issuer Validity Not before Not after
Subject Subject public key info Public key algorithm Subject public key
Issuer unique identifier Subject unique identifier Extensions Certificate signature algorithm Certificate signature As mentioned, the digital certificate signature is used at verification time to check the integrity of a received certificate and its origin; that is, the CA that signed the certificate.
266
Appendix G.
267
EKM overview
IBM Encryption Key Manager (EKM) is a stand-alone server that is bundled with the IBM JDK. It is written in pure Java and is used as a key server for the IBM TS1120 and TS1040 Tape Units. EKM can therefore execute on any Java-capable platform. These hardware units use the keys that EKM sends to encrypt or decrypt data at the same time as they are written on or read from the tapes. EKM is a lightweight application that reads a keystore into memory and then uses the keys in that keystore to satisfy the drive requests. The tape units communicate with EKM over a TCP/IP connection. In a multi-EKM configuration, EKM instances communicate together, also using TCP/IP connections. EKM instances share mainly configuration information so that tape units get an EKM instance assigned to them, as well as a backup EKM that is able to take over for a failing EKM instance. When starting, an EKM instance binds to two network sockets, reads its keystore into memory, and waits for either a tape unit or another EKM instance to initiate a handshake with it. This is a normal SSL/TLS handshake occurring between EKMs. In contrast, the connection between a tape unit and EKM, although implementing an SSL/TLS-like connection, uses a proprietary protocol.
IBMJCE
When EKM is configured to deal with software keys and keystores, it uses the IBMJCE provider. The keystores that EKM uses on z/OS are therefore JCEKS and JCERACFKS.
IBMJCECCA
The IBMJCECCA provider allows applications that are configured to use it to obtain hardware assistance from z/OS integrated hardware cryptography. If EKM is set up to use a JCECCAKS or JCECCARACFKS keystore, it then implies that it uses the IBMJCECCA provider to exploit the cryptographic hardware coprocessors. The TS1120 tape unit is sent by EKM as a randomly generated AES 256 key to be used for encryption of the data on the tape. When on z/OS, EKM can be configured to generate that key as a clear key or, if the IBMJCECCA provider is specified, to generate and use the key as an ICSF secure key. In that case, a Triple-DES secure key is randomly generated by ICSF, using the cryptographic hardware coprocessor because, at the time of writing, there is no support for AES secure keys in ICSF. This Triple-DES key never appears in clear in the z/OS platform, and it is sent to the tape unit encrypted by the tape units RSA public key. The Triple-DES key is then recovered in the tape unit hardware cryptography facility and is properly padded to meet the 256-bit length of an AES key.
268
IBMJSSE
The IBMJSSE provider is used for SSL/TLS-protected communications, such as the communications established between different instances of EKM. As mentioned, the JSSE provider itself does not perform any encryption. It calls either the IBMJCE or IBMJCECCA provider, depending on the specification in the java.security file. This is an important consideration to keep in mind when FIPS compliance settings for the EKM are discussed.
IBMJCEFIPS
The IBMJCEFIPS provider is a subset of the IBMJCE provider that has a stabilized codebase that was approved for FIPS certification. Some customers have a requirement to use only FIPS-certified cryptographic applications. Because EKM itself does not perform any cryptographic operations, it does not need to be FIPS-certified. However, it should then use the IBMJCEFIPS provider. This provides FIPS-certified algorithm implementations for securing EKM-to-EKM SSL/TLS communications, EKM - tape units SSL/TLS-like communications, and the generation and wrapping of the data key used by the tape unit. Note, however, that the IBMJCCECCA provider is not FIPS-certified and cannot therefore be used with EKM on z/OS when the use of a FIPS-certified provider is required.
EKM-to-EKM SSL/TLS
SSL/TLS communication is initiated by an EKM instance (the SSL/TLS client) that needs to synchronize another instance (the SSL/TLS server) with a set of information to be shared. EKM SSL/TLS communication can be set up so that SSL/TLS client authentication is performed during the handshake. By default, there is no client authentication during the handshake. EKM can therefore act as an SSL/TLS client or server. When acting as a client, EKM can provide a digital certificate for client authentication. As a consequence, an EKM instance would need four keystores to support SSL/TLS communication. It would need a keystore and truststore (that is, a keystore hosting trusted certificates only) when acting as a client, and another keystore and truststore when acting as a server. If we include the keystore that is holding the keys exploited for tape unit encryption, this brings the total number of configurable keystores for an EKM instance up to five. In practice, however, EKM users often use a single keystore to host all keys and certificates in order to simplify the keystore.
269
When initializing, a tape unit initiates a connection to EKM and sends to EKM a public key signed by the tape unit certificates private key. EKM will verify that the tape units certificate is signed by the IBM root certificate. If that verifies, EKM generates an AES 256 data key (unless EKM executes on z/OS with secure key specified, as explained in IBMJCECCA on page 268). The data key is sent to the tape unit encrypted with the public key that the same tape unit sent previously. The drive has the corresponding private key, and is able to decrypt the public key encrypted data key. It can then use that data key to encrypt data sent to the tape.
JCEKS
Entries of the JCEKS keystore are encrypted with Triple-DES. This is a UNIX file-based keystore, and its access is protected by UNIX permission bits or ACL. This keystore is a purely software implementation and does not support secure keys. This keystore allows keys to be exported and transmitted in files in the PKCS#12 format. JCEKS hosts both symmetric and asymmetric keys.
JCERACFKS
JCERACFKS is the externalization of the z/OS external security manager, RACF for IBM, as a Java keystore. It allows Java users to store their keys and certificates in RACF key rings or an equivalent. Access to JCERACFKS contents is more strongly protected than JCEKS. This keystore is a purely software implementation and does not support secure keys. It hosts asymmetric keys only (DSA or RSA). It also allows keys to be exported in a PKCS#12 format file if required.
JCECCARACFKS
JCECCARACFKS is similar to JCECRACFKS in that it uses the external security manager repository to store certificates. However, the keys themselves are stored in the ICSF PKDS and secure keys are supported.This keystore only hosts RSA asymmetric keys.
JCECCAKS
JCECCAKS is similar to the JCEKS keystore in that it supports both symmetric keys and asymmetric keys. The difference is that this keystore also supports secure keys that are stored in the ICSF CKDS or PKDS. Currently, the EKM Installation Planning and Usage Guide states that this keystore supports secure asymmetric keys and clear symmetric keys only.
270
JCERACFKS
Keeping keys synchronized between different RACF databases through JCERACFKS is again a very standard practice. Users simply export RSA or DSA keys in a PKCS#12 file from one RACF database and then import the file into another RACF database.
JCECCARACFKS
The JCECCARACFKS keystore does not allow the exportation of RSA private keys in a PKCS#12 file because those private keys are actually kept encrypted with the coprocessor asymmetric Master Key in the PKDS. Sharing private keys between different JCECCARACFKS requires exchanging the encrypted private keys between z/OS instances using the same coprocessor asymmetric Master Key. The KEYXFER utility, which can be downloaded from the IBM tools and toys Web site (at ftp://ftp.software.ibm.com/s390/zos/tools/keyxfer/keyxfer.rexx.txt), is a REXX-based program that allows the user to pull a private key by label out of the PKDS. The key is in the Master Key encrypted format and put into a dataset. From there, the private key can be moved to another system and put into that other systems PKDS. Again, this target system would need to be set up with the same asymmetric Master Keys as the source system. After the private key has been entered into the destination PKDS, then the public key and certificate associated with the private key can be exported out of the RACF database and imported using the regular RACF RACDCERT command options. It is useful to first generate the RSA asymmetric keys in software, export them in a PKCS#12 format, and then import them into the target JCECCARACFKS instances. However, if the keys are generated first by software and later migrated into a format where they are kept encrypted with the coprocessor asymmetric Master Key, they cannot be given a true status of secure key because they were first created as clear keys.
JCECCAKS
The capability of sharing keys in a JCEKS by exporting them to other JCEKSs depends on whether the keys are kept as secure keys (no export possible) or clear keys (export possible).
271
The process would be as follows: Create an ICSF secure Triple-DES key in the ICSF CKDS. Use Java APIs to achieve mapping the keys CKDS key label to a JCECCAKS key store. Set up the EKM with the property zOSCompatability = true. Start the EKM, list the keys it has access to, and then try to encrypt a tape using the secure key.
9. Press PF3 to save. 10.At the ICSF Key Administration menu, select 3 to submit your KGUP job. 11.At the Set KGUP JCL Job Card panel, set Special Security Mode (at the bottom of the screen) to YES, and change the job card information to be valid in your environment. 12.On the Set KGUP JCL Job Card panel, at the command prompt, enter S to submit. 272
Java Security on z/OS - The Complete View
13.Check the KGUP job SYSOUT to make sure you get a zero return code. If a nonzero return code is received, an explanation of why such a return code was received is displayed after the offending statement in the CSFDIAG DD file. 14.At the ICSF Key Administration menu (the KGUP main menu), select 4 to refresh the cryptographic key data set. At the Refresh in-storage CKDS panel, for New CKDS, enter your CKDS name and press Enter. REFRESH SUCCESSFUL should display at the upper right corner of the screen. Refresh only updates the in-storage CKDS on the LPAR where the request is made. If the key value is required on other LPARs sharing this CKDS, a refresh must also be performed at the ICSF instances executing in those LPARs.
273
274
Appendix H.
Performance case study: IBM Encryption Facility for z/OS OpenPGP support
IBM Encryption Facility for z/OS is a program product (Program Product 5655-P97) that implements the OpenPGP encryption protocol for the encryption and decryption of data in datasets or z/OS UNIX files, with the optional compression of data prior to encryption. Because OpenPGP (RFC 2440) is widely supported on many systems, the Encryption Facility for z/OS OpenPGP support can be used to securely exchange data between z/OS and numerous non-z/OS, including non-IBM, systems. The OpenPGP support has been implemented as a set of Java programs in the Encryption Facility for z/OS program product. Because the support could be invoked to handle a large amount of data in a limited time, it is of prime importance to understand how its performance could be optimized and what product features can be exploited to achieve this objective. This appendix discusses the capabilities offered by the OpenPGP support for performance optimization as typical examples of possible approaches to improve the performance of any Java program executing on z/OS.
275
Introduction
The following two performance metrics are used to discuss the performance-related implications of deploying the IBM Encryption Facility for z/OS OpenPGP support: The execution time, measured by a standard watch or clock and the amount of work accomplished within that time The cost, measured by the CPU consumption on general purpose processors Applications written in Java on z/OS require the IBM Java Runtime Environment for z/OS (JRE) for their execution environment. This environment consists of an address space where the JRE executes. The JRE interprets compiled Java byte code that serves here as the OpenPGP support's program code. Given the additional layer of execution and Java's interpretive nature, the amount of CPU time consumed and the amount of execution time to complete a task are immediately impacted. Moreover, the cryptographic nature of the Encryption Facility products requires the completion of computationally-intensive operations that could further increase the amount of CPU time consumed and expand the execution time. Finally, OpenPGP's main purpose is to provide data integrity services on datasets and z/OS UNIX files. This involves I/O-intensive operations that may result in inefficient utilization of the CPU. To address these issues, performance enhancing options in the following three areas should be considered: 1. IBM Java 6 SDK Runtime Environment for z/OS 2. z/OS specialized hardware devices: zAAP and CPACF specialized processors 3. OpenPGP support code performance options
with 128-bit keys encryption algorithm) that heavily uses the CPACF feature, the performance characteristics may be affected if the PUs happen to compete for an available CPACF. The System z Application Assist Processor (zAAP) is a specialized PU (a System z Specialty Engine) that only executes Java workloads. When Java workloads are dispatched on a zAAP processor, no general CP service units are consumed by these workloads. That is, the general CPs capacity, which is usually the basis for charging for the use of licensed programs, is unaffected by these workloads.
Appendix H. Performance case study: IBM Encryption Facility for z/OS OpenPGP support
277
Notes on the performance data: The performance data presented in this appendix was obtained in a controlled environment with specific performance benchmarks and tools. This information is presented along with general recommendations to assist reader understanding of IBM products. Results obtained in other environments may vary significantly. The data presented here does not predict performance in a specific installation's environment. In addition, readers should be aware of the following: All tests were run on zSeries System z10. All data was gathered using a 1.5 GB input file. All I/O is done to and from data sets on DASD. AES with 128-bit keys was the encryption algorithm used. Due to compression, the output file may not be the same size as the input file. The CPU utilization percentage given in many tables is the average utilization measured over all the enabled processors of the same type. That is, an average may be given for all the zAAP processors and a different average may be given for all the general CPs. As a result, when multiple processors are online, the calculated average may appear to be impacted. However, the aggregate of CPU time consumption is roughly equivalent. For example, there may not be a reduction of overall CPU time consumed if a CPU utilization value of 50% when only one general CP is available is reduced to 25% when two general CPs go online. The elapsed time is given in seconds. When giving statistics for zAAP processors, the internal throughput number given is the throughput for the general CPU and zAAP combined. When doing compression, the zip compression algorithm was used with level 1. The level value of 1 yielded the best performance. Tests have shown that a compression level of 9, which is the best possible compression ratio, results in a very significant performance reduction. Compression performance and compression percentages are greatly impacted by the type of data being compressed.
278
If these options are not specified and the security.provider.1 keyword in $(java_home)/lib/security/java.security file has not been updated to list the com.ibm.crypto.hdwrCCA.provider.IBMJCECCA provider, then the cryptographic functions will be performed exclusively by software (that is, the Java code within the JCE component of the JRE).
Table 12-2 lists the statistics measured with the hardware provider being enabled and only one general CPU and one CPACF online.
Table 12-2 Performance with one CP and the hardware provider enabled Input data size (bytes) 1,506,431,796 Output data size (bytes) 346,727,868 Elapsed time (sec) 86.67 MB/sec 16.58 CPU utilization % 56.31% MB/CPU sec 29.44
The hardware provider reduced the elapsed time by 11% and improved the MB/CPU seconds by 22%.
zAAP usage
Table 12-3 lists the statistics for the same test, but measured without the hardware provider being enabled and with one general CPU online and one zAAP process online.
Table 12-3 Performance with one CP and one zAAP, without the hardware provider Elapsed time (sec) 97.11 MB/sec 14.79 zAAP utilization % 62.28% General CPU utilization % 1.65% MB/General + zAAP CPU sec 23.14
Comparing the results in Table 12-1 and Table 12-3, the general CP utilization is reduced by more than 97%. Table 12-3 dissociates the internal throughput (MB/CPU sec) into two categories: MB/General CPU Seconds and MB/zAAP+General CPU Seconds. This distinction is given to allow those who use throughput as an informal indicator of cost to quickly see the financial impact of a zAAP processor. The System z10 shifted almost all of the work to the zAAP processor. Finally, the introduction of the zAAP processor resulted in a slight reduction in elapsed time of about 1%. Using a zAAP, the MB/zAAP+General CPU seconds throughputs about 4% lower than the total MB/CPU seconds without a zAAP. These comparisons are also valid for the case when the specialized cryptographic processor is being leveraged. Table 12-4 on page 280 lists the statistics measured with the hardware provider being enabled and one general CPU online and one zAAP process online.
Appendix H. Performance case study: IBM Encryption Facility for z/OS OpenPGP support
279
Table 12-4 Performance with one CP and one zAAP, with the hardware provider enabled Elapsed time (sec) 85.11 MB/sec 16.88 zAAP utilization % 58.51% General CPU utilization % 1.10% MB/General + zAAP CPU Sec 28.32
Comparing the results in Table 12-2 on page 279 and Table 12-4, the general CPU utilization is reduced by over 98%. Using a zAAP, the MB/zAAP+General CPU seconds was about 4% lower than the total MB/CPU seconds without a zAAP.
When any or all of these configuration options are enabled, the associated processing tasks are performed in a separate thread of execution. In effect, this relieves the CPU from waiting on the task to complete before continuing the main line processing. Further, multiple CPUs can be used to handle processing in a concurrent fashion. This results in a reduction of the total execution elapsed time. Table 12-2 on page 279 lists some performance statistics for encryption and compression without any of the options enabled and only one general CPU and one CPACF online. In contrast, Table 12-6 lists the measurements done when USE_ASYNC_IO, USE_ASYNC_COMPRESS, and USE_ASYNC_CIPHER are enabled and only one general CPU and one CPACF is online.
Table 12-6 Performance with all optimization options, one CP and the hardware provider enabled Input data size (bytes) 1,506,431,796 Output data size (bytes) 346,727,868 Elapsed time (sec) 65.25 MB/sec 22.02 CPU utilization % 89.02% MB/CPU sec 24.73
With one general CP and one CPACF available, full parallel processing shows a decrease of elapsed time of about 25%. However, due to significantly higher CPU utilization, the MB/CPU second drops by 16%.
280
Table 12-7 lists the statistics when USE_ASYNC_IO, USE_ASYNC_COMPRESS, and USE_ASYNC_CIPHER are enabled, and four general CPUs and four CPACFs are online.
Table 12-7 Performance with all optimization options, four CPs and the hardware provider enabled Input data size (bytes) 1,506,431,796 Output data size (bytes) 346,727,868 Elapsed time (sec) 55.82 MB/sec 25.74 CPU utilization % 37.79% MB/CPU Sec 17.03
A 36% improvement is seen when comparing the elapsed times of enabling all the parallel processing features and with four general CPs online to no parallel processing and only one general CP online. External throughput (MB/sec) is significantly improved. Internal throughput (MB/CPU sec) is lower because of as many as four CPs are used.
Table 12-9 is a repetition of Table 12-1 on page 279, shown here again for convenience, which lists the statistics when one general CP is online, no parallel processing options are enabled, and the hardware provider is not specified.
Table 12-9 Performance with one CP and no hardware provider enabled Input data size (bytes) 1,506,431,796 Output data size (bytes) 346,727,868 Elapsed time (sec) 97.72 MB/sec 14.70 CPU utilization % 60.87% MB/CPU sec 24.15
Table 12-8 shows significant improvement over Table 12-9: Elapsed time was reduced by over 43%. MB/second increased by approximately 77%. A full 97% of the CPU activity was able to run on a zAAP. For installations with multiple CPs and zAAPs configured, this probably is the lowest cost option.
Appendix H. Performance case study: IBM Encryption Facility for z/OS OpenPGP support
281
Conclusion
Two metrics that are key to the analysis of performance are the elapsed time needed to complete a task, and the CPU time used to complete that task. This appendix demonstrates some of the techniques that can used to achieve enhanced performance when using the IBM Encryption Facility for z/OS OpenPGP support, taken as a typical industry-class Java application. Clearly, all installations where CPACF are enabled should exploit this technology. Installations with multiple general CPs and zAAP processors online can benefit from enabling all of the parallel processing options for OpenPGP support.
282
Index
Symbols
/usr/include/java_classes/IRRRacf.jar 82 /usr/include/java_classes/IRRRacfDoc.jar 82 /usr/include/java_classes/RACFuserregistry.jar 63 /usr/include/java_classes/userregistry.jar 63 /usr/lib/libIRRRacf.so 82 /usr/lib/libIRRRacf64.so 82 /usr/lpp/eim/lib/eim.jar 103 /usr/lpp/eim/lib/eimzOS.jar 103 /usr/lpp/java/J5.0/lib/security/ 128 __check_resource_auth_np 58 _login() 21 _passwd() 21, 59, 81 _passwd_appl() 81 _pthread_security_np() 81 _pthread_security_np_appl() 81 _spawn() 21 Authorized Program Facility 18 AUTHPGM 211 AUTHTSF 211
B
BASE_PASSWORD 67 BASE_SPECIAL 70, 73 BASE_UAUDIT 67 BasicAttribute 75 BasicAttributes 66 BasicAttributesToTreeMap() 67 Batch Launcher 12 BIND 190191 Blowfish 132, 260 boolean attribute 65 BPX.DAEMON 20, 60 BPX.FILEATTR.APF 19 BPX.FILEATTR.PROGCTL 20 BPX.SERVER 35, 58 BPX1ENV 59 BPXBATCH 1112 BPXBATSL 1112 brute force attack 158 Byte Code Verifier 14
A
a extended attribute 19 abstract class 160 AC=1 19 access list 52 AccessControlContext 3435 AccessController 15, 34 AccessController.checkPermision 15 aclEntry 100 aclPropagate 100 aclSource 100 ADDGROUP 53, 62, 70 addMember() 64 addProvider 129 ADDRING 185 ADDTOKEN 190 ADDUSER 53, 62, 70 Administrative association 110 AES 133, 137, 143, 175, 260 AIX 5L V5R3 95 AlgorithmParameterGenerator 127 AlgorithmParameters 127 AlgorithmParameterSpec 161 AllPermission 16 ALTGROUP 53, 62 ALTUSER 53, 62, 70 APF 1819, 169 APPL 81 Assembler Callable Services 5 Associations 97 asymmetric algorithm 259 attributesHTML() 6566 attributesInfo() 6566 audit 27 AUDITOR attribute 50, 53 auth_check_resource_np 21 Copyright IBM Corp. 2008. All rights reserved.
C
CA 17 CallbackHandler 28 Candidate List 210 CBC 148, 154 CBS390 81 CCA 136 CCF 200 Central Processor Assist for Cryptographic Functions 200 certificate 259 Certificate Authority 17, 171, 265 Certificate class 160 certificate object 139 CertificateFactory 127 CEX2A 201 CEX2C 200 checksum 17, 147, 263 CICS 51 Cipher 127, 145, 148 cipher block-chaining 148, 154 cipher suites 134 CKDS 164, 179, 205 CKDS label 166 Class Loader 14 CLASSPATH 68 clear key 165, 182 clone_user() 67 codeBase 41
283
CodeSource 16 com.ibm.* 28 com.ibm.security.auth.module.OS390LoginModule 29 com.ibm.security.auth.PolicyFile 28 com.sun.* 28 compression 278 configuration file 191, 193 CONNECT 53, 62, 70, 185 ConnectInfo 105 connection credentials 67 connection mode 67 connection principal 67 connection suffix 67 Control Domain Index 210 CPACF 122, 200, 202203, 276 createGroup() 64, 66 createLoginContext 38 createUser() 6465 Crypto Express2 Coprocessor 122, 200 cryptographic accelerator 201 cryptographic algorithm 260 cryptographic domain 202 cryptographic engine class 126 CRYPTOZ class 139, 166, 190, 193, 204 CSFDAUTH 211 CSFDPKDS 211 CSFKEYS class 164, 204 CSFPRMxx 212 CSFSERV class 166, 169, 204
D
data object 138 DECRYPT_MODE 148 deleteGroup() 64 deleteUser() 64 DELGROUP 53 DELUSER 53 DES 132133, 137, 260 DiffieHellman 132, 134 Digest 122 digital certificate 17, 4849, 159 digital signature 122, 160, 259 Digital Signature Algorithm 126 dirty address space 20 displayAttributes() 67 distinguished name 27 doAs 35 Domain 97 DSA 126, 133134, 137 DSA/SHA1 132
EIM domain 95 EIM Domain Controller 9495 EIM example. 254 EIM Identifier 93, 96 EIM Identifier administrator 99 EIM lookup operation 97 EIM policies 96 EIM Registries administrator 99 EIM registry 96 eimadmin utility 95 EimJavaAuth.java 255 eimjavademo 113 EimJavaDemo.java 256 EimJavaSetup.java 254 EKM 267 ENCRYPT_MODE 148 Encryption Facility for z/OS 275 Encryption Key Manager 267 engine class 127, 146 Enterprise COBOL for z/OS V3R4 5 entropy 146 entryOwner 100 entryPropagate 100 entrySource 100 EXECUTE 20 execute bit 169 ExemptionMechanism 127 EXOP 53 extattr 1920 extended operation 53 External Security Manager 48, 50
F
FC 3863 206, 208 File Security Packet 49 FilePermission 16 findTarget 102 findTargetFromSource 102 FIPS 140-1 Level 4 201 FIPS 140-2 133 FIPS 140-2 Level 4 201 FIPSPRNG 134 FSP 49
G
GDBM 53 GENCERT 185, 190 getAssociatedEids 102 getAssociations 102 getAttributes 69 getAttributes() 64 getGroup() 64, 66 getGroups() 64 getInstance 127 getMembershipAttributes() 64 getName() 64 getUser method 69 getUser() 6465 GROUP profile 48, 51, 53
E
EIM 9798, 108 administrative association 96 source association 96 target Association 96 EIM Administrator 99 EIM associations 96 EIM client 95
284
H
hardware cryptography 131, 136, 199 Hash 122 Hmac 132, 134, 137 hwkeytool 164, 182 hybrid encryption 259, 262
I
IBM 4764 201 ibm-entryUUID 100 IBMJAAS 131, 135 IBMJCE 131, 268 IBMJCE4578 131132 IBMJCECCA 127, 131, 133, 136, 152, 154, 268 IBMJCECCA failover 136 IBMJCEFIPS 131, 133, 268 IBMJGSS 131, 135 IBMJSSE 131, 268 IBMJSSE2 131, 133 IBMJSSEFIPS 131, 133 IBMPKCS11Impl 131, 138, 191, 193 IBMPKCS11Impl configuration file 140 IBMSASL 131, 136 ICHRIX01 87 ICSF 137, 169, 203204 ICTX 53 IDCAMS 214 Identifiers 97 initialization vector 154, 262 insertProviderAt 129 instantiation 4 interface 160 intermediate 171 intermediate authority 171 IRR.DIGTCERT. 170 IRR.DIGTCERT.LIST 170 IRR.EIM.DEFAULTS 101 IRR.PROXY.DEFAULTS 101102 IRR.RADMIN 104 IRR.RAUDITX 104 IRR.RDCEKEY 104 IRR.RGETINFO.EIM 104 IRRPTAUTH 82, 85 IRRSGS64 85 IRRSPK00 85 isMember() 64
Java class 4 Java Cryptography Architecture 126 Java Native Interface 5 Java Virtual Machine 6 java.security 128 java.security.acl.Group 63 java.security.Principal 63 java.security.Provider 128 Java2 Security 15 javah 8 javax.naming.directory.BasicAttribute 63 javax.naming.directory.BasicAttributes 63 javax.naming.directory.ModificationItem 63 javax.security.auth.callback.CallbackHandler 28 javax.security.auth.login.LoginContext 28 javax.security.auth.Subject 27 JCA 126 JCE framework 126127 JCECCAKS 179, 205, 270 JCECCARACFKS 165, 179, 187, 205, 270 JCEKS 132, 163, 179180, 270 JCERACFKS 164, 179, 185, 270 JIT 15 JKS 132, 163 JNI jobject 7 mapping of primitive types 7 object types 7 primitive types 7 reference types 7 jobject 7 JRE 14 JRIO 910 JSec 256 JSec attributes 235 JSec sample code 225, 235 jstring 7 JVM 6 JZOS 910 JZOS Batch Launcher 11
K
KERB_KERBNAME 67 Kerberos 4849, 9394, 98, 135 Kerberos ticket 49 Key 161 key object 139 key pair 163, 261 key ring granular access control 170 KeyAgreement 127 KeyFactory 127, 145, 161 KeyGenerator 127, 145, 149, 162 KeyPair 162 KeyPairGenerator 127, 145, 149, 162 KeySpec 161 KeyStore 127, 145, 162 keystore 17, 157 KeyStore.getKey 142 KeyStore.load 142 KeyStore.setKeyEntry 142 Index
J
J2EE 6, 48 JAAS 26 JAR 5, 16 jarsigner 17 Java 2 Security 34, 56
285
L
LDAPBIND class 101 LINKLIST 169 LISTGROUP 53 LISTTOKEN 191 LISTUSER 53, 68 LNOTES_SNAME 67 local_policy.jar 130 LoginContext 28 LoginModule 26 LPA 19
M
Mac 127 Main-Class 5 manifest 5 Mars 132 Master Key 182, 187, 202, 216 MD2 132, 137, 151 MD5 132, 134, 137, 142, 151 members() 64 membershipAttributes() 66 membershipAttributesHTML() 66 MessageDigest 127, 145, 147 META-INF 5, 17 MLS 48 modifyGroup() 64 modifyMembershipAttributes() 64 modifyUser() 64 Multilevel Security 48
N
NDS_UNAME 67 NoSuchAlgorithmException 146 NoSuchProviderException 146 NOTRUST status 171
O
OMVS_UID 67 OMVSAPPL 81 one-way hash 263 Online List 210 OpenPGP 275 optional flag 29 Options Dataset 203, 212 OS390LoginModule 28, 30 OutputStream 15 owning group 169
padding 259, 261 PADS 20 Partitioned Data Set 10 Partitioned Data Set Extended 10 Passphrase Initialization 216 PassTicket 48, 78, 256 PassTicket generation 78 PASSWORD 53 Password Enveloping 54 Password Phrase enveloping 54 password-phrase 48 PBE 132, 137138 PCICA 201 PCICC 201 PCIXCC 201 PDS 10 PDSE 10 permission bits 169, 171 PKCS#1 133 PKCS#11 138 PKCS#11 token 189 PKCS#12 165, 167, 271 PKCS11IMPLKS 143, 179, 189, 205 PKCS12KS 132 PKCS5Key 138 PKCS5Padding 154 PKDS 164165, 174, 179, 205 PKIX 265 PlatformAccessControl 5658 PlatformAccessLevel 5657 PlatformReturned 5657 PlatformSecurityServer 56 PlatformThread 56, 59 PlatformUser 5657, 59 Pluggable Authentication Module 28 Policies 97 policy files 37 Policy Tool 40 Power on Reset 206 preference order 129 principal 16, 27 private credential 27 private key 149, 152, 159, 163, 261 PrivateKey 161 PROGRAM 20 Program Control 18, 20 PROGxx 18 ProtectionDomain 16 PROXY_BINDPW 67 pseudo random number generator 146 pthread_security_np 21 PTKTDATA class 80 public credential 27 public key 149, 152, 159, 163, 261 public methods 4 PublicKey 161 pure Java 6
P
p extended attributes 20 package 4
R
R_datalib 164, 170
286
R_gensec 80, 85 R_ticketserv 80, 85 RACDCERT 164, 170, 176, 185, 190191 RACF 20, 48, 139, 164, 166, 169, 190, 193, 204, 215 RACF Callable Services 50 RACF key ring 163164, 168 RACF_Group 66 RACF_remote 67 RACF_SecAdmin 66 RACFInputStream 162, 176, 186 RACFOutputStream 162, 176 RACLINK 53 RACROUTE macro instruction 50 random number 132 RC2 132 RC4 132 RDATALIB class 170171 Redbooks Web site 290 Contact us xiii Registries 97 registries 108 REMOVE 53, 62, 70 removeMember() 64 removeProvider 129130 replay protection 88 required flag 29 requisite flag 29 resource manager 5051 resource owner 49 retained key 164 RFC 2222 136 RFC 2440 275 root CA 171 RSA 132134, 137, 142143, 183, 261 RSA/SHA1 132 RTL (Run Time Library) 5 Run Time Library (RTL) 5 RuntimePermission 16
self-signed certificate 172 Service Provider Interface 127 session object 139 SET PROG 18 seteuid() 21 SETPROG 18 SETROPTS WHEN(PROGRAM) 20 setruid() 21 setuid() 21 SHA-1 17, 132, 134, 137, 142 SHA-256 134 SHA-384 134 SHA-512 134 signature 8, 127, 145 signedBy 38, 41 SocketPermission 16 Source association 110 SPECIAL 53 SPI 127 SSL 133 stack overflow 15 stack underflow 15 STARTED class 215 storage key 18 subclassing 16 sufficient flag 29 superior group 51 supervisor state 18 symmetric algorithm 259260 SYS1.LINKLIB 19 SYS1.LPALIB 19 SYS1.SVCLIB 19 SYSOUT 13 System Authorization Facility (SAF) 50, 163
T
Target Association 110 ThreadSubject.doAs 28 TKDS 139, 166, 168, 191, 205 TKE 200, 203, 216 TLS 133 Token Key Data Set 139 tokenLabel 140, 165 Triple-DES 132, 260 trojan 20 Trust 171 TRUST status 171 Trusted Key Entry 200 TS1040 267 TS1120 267 TSO 51
S
SAF 221 SAF Trace 88 SAFPermission 28 SASL 136 SCSFMOD0 169, 211 SDBM 5354, 6263 SDSF 13 Seal 132 SEARCH 53 SecretKeyFactory 127, 145 Secure Random 132 secured signon session key 79 SecureRandom 127, 145 Security Officer 138 security policy 15 security.zOS.domainName property 81 SecurityException 16 SecurityManager 15, 35, 37 securityManager.checkXX 15 seed 146
U
UACC 52 UDX 201 universal access 52 unrestricted policy files 130 UNWRAP_MODE 148 US_export_policy.jar 130
Index
287
Usage Domain Index 210 USE_ASYNC_CIPHER 280 USE_ASYNC_COMPRESS 280 USE_ASYNC_IO 280 USER profile 48, 51, 53
W
WebSphere Application Server 6 WRAP_MODE 148 writeable key ring 170 WTO 12
X
X.500 265 X.509 134, 138, 167168, 171 X.509 V3 48, 266
Z
z Application Assist Processor (zAAP) 6 z/OS PKCS#11 token 165 zAAP 169, 203, 277 zip file format 5
288
Related publications
The publications listed in this section are considered particularly suitable for a more detailed discussion of the topics covered in this book.
IBM Redbooks
For information about ordering these publications, see How to get Redbooks on page 290. Note that some of the documents referenced here may be available in softcopy only. Java Stand-alone Applications on z/OS Volume 1, SG24-7177 Java Stand-alone Applications on z/OS Volume 2, SG24-7291 System z Cryptographic Services and z/OS PKI Services, SG24-7470 IBM System Storage TS1120 Tape Encryption: Planning, Implementation, and Usage Guide, SG24-7320
Other publications
These publications are also relevant as further information sources: z/OS UNIX System Services Planning, GA22-7800 z/OS Security Server RACF General Users Guide, SA22-7685 z/OS Security Server RACF Security Administrators Guide, SA22-7683 z/OS Security Server RACF Callable Services, SA22-7691 z/OS Security Server RACF Diagnosis Guide, GA22-7689 z/OS Security Server RACF Command Language Reference, SA22-7687 z/OS Integrated Security Services Enterprise Identity Mapping (EIM) Guide and Reference, SA22-2875 z/OS Cryptographic Services Integrated Cryptographic Services Facility Administrator's Guide, SA22-7521 z/OS Cryptographic Services ICSF Application Programmer's Guide, SA22-7522 z/OS Cryptographic Services ICSF Trusted Key Entry PCIX Workstation Users Guide, SA23-2211 z/OS Cryptographic Services Integrated Cryptographic Service Facility Writing PKCS #11 Applications, SA23-2231 z/OS Cryptographic Services System Secure Sockets Layer Programming, SC24-5901 System z10 Enterprise Class Processor Resource/Systems Manager Planning Guide, SB10-7153 IBM Encryption Key Manager Component for the Java Platform Introduction, Planning, and User's Guide, GA76-0418
289
Online resources
These Web sites are also relevant as further information sources: A basic introduction to Java programming with JNI, available at IBM developerWorks http://www-128.ibm.com/developerworks/edu/j-dw-javajni-i.html Java Record I/O API download http://www-03.ibm.com/servers/eserver/zseries/software/java/jrio/overview.html/ zAAP specialty engine information http://www-03.ibm.com/systems/z/zaap/ Java JAAS information http://www-03.ibm.com/servers/eserver/zseries/software/java/jaas.html http://www.ibm.com/developerworks/java/jdk/security/60/secguides/JaasDocs/api.h tml Java SAF classes information http://www-03.ibm.com/servers/eserver/zseries/software/java/j5security.html Java Jsec API download http://www.ibm.com/servers/eserver/zseries/zos/racf/racfjsec/doc/index.html EIM APIs download http://www-1.ibm.com/servers/eserver/security/eim/availability.html IBMJSSE2 Guide http://www.ibm.com/developerworks/java/jdk/security/60/secguides/jsse2Docs/JSSE 2RefGuide.html#plug
290
Back cover
Comprehensively describes z/OS security services for Java applications Provides use cases illustrated with Java program examples Discusses industry-class Java applications
This IBM Redbooks publication describes and explains which z/OS security services can be exploited by Java stand-alone applications executing on z/OS. It is intended for experienced z/OS users with a moderate knowledge of Java, and experienced Java users with some knowledge of z/OS. For experimentation and customization it provides use cases that were composed and tested on a z/OS platform at z/OS V1R10 and SDK 6 SR1. The book describes the role of the major infrastructure components such as Security Manager, Access Controller, Class Loader and Byte Code Verifier. It addresses specific z/OS-provided facilities including the JZOS Toolkit and Java record I/O (JRIO), and explains how they fit within both security models. Java Authentication and Authorization Services (JAAS) is covered and practical examples illustrating its use in z/OS, including the LoginModules that interact with the SAF interface, are given. The relationship of these services to z/OS built-in security functions such as APF, Program Control, and so on is explained. The specific security-relevant services provided to Java applications executing on the z/OS platform are covered, along with practical examples of their setup and use. Java SAF classes, the JSec API, exploitation of RACF PassTickets, and the use of the z/OS Enterprise Identity Mapping (EIM) infrastructure are explained. Exploitation of z/OS integrated hardware cryptography by Java applications is detailed, along with numerous practical examples of the use of these services. z/OS cryptographic key management features are also discussed. Finally, the book addresses two industry-class IBM Java products that exploit z/OS hardware cryptography, IBM Encryption Key Manager and IBM Encryption Facility for z/OS OpenPGP Support, and highlights the exploited functionalities and performance optimization.
SG24-7610-00
ISBN 0738431869