JAAS Java Authentication and Authorization Services Bruce A Rich Java Security Lead IBM/Tivoli Systems Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
Trademarks Java, Java 2 are trademarks or registered trademarks of Sun Microsystems Inc. Windows 2000 is a registered trademark of Microsoft
Talk Outline JAAS fundamentals JAAS case study with Kerberos Backup materials Java2 security model JAAS and J2EE relationships
JAAS fundamentals Emphasis on "fun" or "mental"? Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
What is JAAS? Add the concept of "user identity" to the Java 2 security model Enable existing security services to plug in Compatibly extend the current model
Key elements Authentication framework Assertion of identity Enhanced authorization Low level of binding between authentication and authorization
Authentication framework Authentication framework Policy-based Generic and abstract Sufficient for today's mechanisms, extensible Pluggable, stackable Key abstractions Subject - any user of computing Collection of Principals, credentials Principal (java.security) Has a name
Assertion of identity Avoids incompatible behavior Lexically scopes identity Logically associates Subject with current Thread static Object Subject.doAs(Subject, action)
Enhanced Authorization Augmentation of current Permission specification Principal-based Any authentication with any Permission Example in Kerberos section
Java 2 Security Model Local or remote code (signed or unsigned) Domain A Security Policy Domain B Sandbox Ability to grant specific permissions to a particular piece of code about accessing specific resources on the client, depending on the signer of the code and/or the location from which the code was loaded. JVM Domain C Resources
Java 2 Permission Model SecureClassLoader Class A Class A's Protection Domain Certificate 1 Certificate 2... Code Base URL Permission 1 Permission 2... POLICY Certificate N Permission M Code Source Protection Domain Permission Collection
Java 2 Authorization Model Cert 1,I Cert 1,2... Cert 1,N 1 Code Base URL Perm 1,1 Perm 1,2... Perm 1,M 1 Class 1 Class 2... Cert 2,1 Cert 2,2... Cert 2,N Code Source Code Source Code Base URL Class K... 2 Permission Collection Perm 2,1 Perm 2,2... Perm 2,M 2 Permission Collection Permission to check Cert K,1 Cert K,2... Cert K,N K Code Base URL Perm K,1 Perm K,2... Perm K,M K Code Source Permission Collection
JAAS Authorization Model SecureClassLoader Class A Subject Y Class A's Protection Domain Subject Y's Protection Domain POLICY Certificate 1 Certificate 2... Code Base URL Permission 1 Permission 2... Permission 1 Permission 2... Certificate N Permission M Permission M Code Source Protection Domain Permission Collection Permission Collection POLICY
JAAS A Case Study with Kerberos Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
Building blocks LoginModule 5 methods New java.security.principal subclass Allows granting Permissions based on this new Principal class Possibly some "credentials" related to Principal Allows proof of identity at some later time
Kerberos Authentication Using JAAS KerberosUserPrincipal Allows permissions based on this authentication technique KerberosTGTCredential Allows further service acquisition without requiring password
KerberosUserPrincipal public class KerberosUserPrincipal extends Principal { private String name; // user name public KerberosUserPrincipal(String username) { name = username } } public String getname() { return name; }...
KerberosTGTCredential public class KerberosTGTCredential extends Object { private KrbCreds creds; public KerberosTGTCredential(KrbCreds creds) { this.creds = creds }; } public KrbCreds getcreds() { return creds; }...
KerberosLoginModule public KerberosLoginModule extends LoginModule { private KerberosUserPrincipal kup; } private KerberosTGTCredential ktc; private Subject subj; public void initialize (Subject s...) { subj=s;... } public boolean login() { if (callbackhandler == null) { // no way to get parameters??? } else { get username, pw, realm; authenticate, remember kup and tkc; } } public boolean commit() { subj.getprincipals.add(kup); subj.getpubliccredentials.add(ktc); }
Windows 2000 Interoperability If in a Windows 2000 domain, already have a Kerberos ticket, but how to use from Java? New wrinkle for KerberosLoginModule LSACallAuthenticationPackage KerbRetrieveEncodedTicketMessage + lots of JNI magic === KerberosTGTCredential for current Subject
Permissions using Kerberos grant signedby "mykey", codebase "file:e:/solutions/app/*" principal com.ibm.security.auth.kerberosuserprincipal "brich" { permission com.ebank.accountaccess "CloseAccount"; };
Configuring to use Kerberos testkerberosal { com.ibm.security.auth.kerberosloginmodule required debug=true; };...login configuration file... LoginContext lc = new LoginContext("testKerberosAL"); lc.login(); Subject whoami = lc.getsubject(); Subject.doAs(lc.getSubject(), someactioninstance);......code in exploiting application
Summary JAAS extends base security model to accomodate concept of "users" Pluggable, extensible Kerberos provides an excellent illustration of the power and ease of using JAAS to extend application security
Resources Java 2 Network Security Marco Pistoia, et al, Prentice Hall, 1999, ISBN 0-13-015592-6 Java and Internet Security Shrader, Rich, Nadalin, IUniverse, 2000, ISBN 0-595-13500-5 http://www.research.ibm.com/compsci/security/javasec/ http://java.sun.com/security http://java.sun.com/products/jaas http://www.ietf.org/rfc/rfc1510.txt, Kerberos V5 http://www.ietf.org/rfc/rfc2743.txt, GSS V2 http://www/ietf.org/rfc/rfc2853.txt, Java bindings for GSS
Backup Materials Java 2 Authorization Model Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
Java 2 Standard Edition Security: Review CodeSource Authorization Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
CodeSource Combination of a set of Signers (certificates) and a code base URL Certificate 1 Certificate 2... Certificate N Code Base URL CodeSource
Policy A Permission is an access right to a protected resource In Java 2, Permissions are stored in the Policy object The reference implementation is file based
Sample Java 2 Policy grant entries Describe Permissions granted to CodeSources An entry may contain one or more Permissions grant signedby "mykey", codebase "file:e:/mydir/app/*" { }; permission java.lang.runtimepermission "queueprintjob";
ProtectionDomain A ProtectionDomain contains: A CodeSource The Permissions granted to the CodeSource SecureClassLoader assigns a ProtectionDomain to each loaded class Classes with different CodeSources belong to different ProtectionDomains Certificate 1 Certificate 2... Certificate N Code Base URL Permission 1 Permission 2... Permission M CodeSource PermissionCollections ProtectionDomain
Classes, ProtectionDomains & Permissions Each class is assigned to only one ProtectionDomain As determined by its CodeSource Each ProtectionDomain may include zero or more Permissions Multiple classes from the same CodeSource are assigned the same ProtectionDomain
Example of Guard on Protected Resource... /* Check to see if the calling code is authorized. If not, a SecurityException (AccessControlException) will be thrown */ AccessController.checkPermission( new RuntimePermission("queuePrintJob")); // Trusted code starts here....
The GetProperty Example import java.security.*; class GetProperty { public static void main(string[] args) { try { if (args.length > 0) { String s = System.getProperty(args[0],"name " + args[0] + " not specified"); System.out.println(args[0] + " property value is: " + s); } else { System.out.println("Property name required"); } } catch(exception e){ System.err.println("Caught exception " + e.tostring()); } } }
Threads of Execution in Java Each thread in the JVM contains a number of stack frames Each stack frame contains the method instance variables for a method called in the current thread A thread of execution may: Occur completely within a single protection domain May involve application ProtectionDomain(s) and the system ProtectionDomain
Check of Current Thread 1. AccessController is in the system ProtectionDomain Permission is implicitly granted Proceed to the next frame on the thread stack 2. SecurityManager is in the system ProtectionDomain Permission is implicitly granted Proceed to the next frame on the thread stack 3. System is in the system ProtectionDomain Permission is implicitly granted Proceed to the next frame on the thread stack 4. GetProperty is in the application domain Is the permission granted? If yes, then proceed to the next frame on the thread stack If no, throw a SecurityException Calling hierarchy GetProperty.main() java.lang.system.getproperty() java.lang.securitymanager.checkpropertyaccess() java.security.accesscontroller.checkpermission() checkpermission() testing
Determining the Permission Set of a Thread The Permission set of a thread is the intersection of all ProtectionDomains traversed by the execution thread ProtectionDomain 2 I i = 1, 2, K, K j= 1, 2, K, Perm i M i, j ProtectionDomain 1 ProtectionDomain K
Authorization - Permissions Class1.methodA calls Class2.methodB ProtectionDomain for Class1 = { P1, P3 } P1 P3 P2 ProtectionDomain for Class2 = { P2, P3 } checkpermission(p1) fails checkpermission(p2) fails checkpermission(p3) succeeds
Authorization - Permissions Class1.methodA calls Class2.methodB Calls AccessController.doPrivileged() Class2.methodC ProtectionDomain for Class1 = { P1, P3 } P1 P3 P2 checkpermission(p1) fails checkpermission(p2) succeeds checkpermission(p3) succeeds ProtectionDomain for Class2 = { P2, P3 }
Authorization - Permissions Class1.methodA calls doprivileged(accesscontrolcontext({p3,p4})) calls Class2.methodB ProtectionDomain for Class1 = { P1, P3 } AccessControlContext = {P3, P4} P1 P3 P4 P2 checkpermission(p3) succeeds All others fail. ProtectionDomain for Class2 = { P2, P3 }
Lexical Scoping of Privilege Modification How privileged code works Why it is necessary Algorithm for run-time access control verification
Why Privileged Code? An application is not allowed to access font files The system utility to display a document must obtain those fonts on behalf of the user The application is temporarily enabled to access the font files Application System utility File System
The Privileged Code Mechanism doprivileged() annotates the stack frame AccessController.checkPermission() stops Permission testing at this stack frame ProtectionDomain for the class and all the classes that it calls are checked ProtectionDomain of its callers are not checked Call hierarchy Caller class Permission testing not performed Caller class Permission testing not performed Class called Permission testing performed Class called Permission testing performed Class called Permission testing performed Class called Permission testing performed checkpermission() testing
Example Privileged Code Must use java.security.privilegedaction interface The run() method contains code needing privilege AccessController.doPrivileged() Takes PrivilegedAction object argument Invokes its run() method Returns the run() method's return value
Example - Anonymous Inner Class somemethod() { // some normal code here... AccessController.doPrivileged(new PrivilegedAction() { public Object run() { // privileged code goes here, for example: System.loadLibrary("awt"); return null; // nothing to return } } ); } // some normal code here...
AccessController Algorithm - Stage 1 Build AccessControlContext for use in stage 2 For each class on the thread stack: Get the class's ProtectionDomain If the stack frame is annotated by a doprivileged(), Exit the loop If the last stack frame checked is not annotated with by a doprivileged(), Add the ProtectionDomains inherited by the current thread when the current thread was instantiated
AccessController Algorithm - Stage 2 Check each ProtectionDomain to see whether it contains the Permission being checked If no ProtectionDomains from step1, Return (only fully trusted code is running) For each unique ProtectionDomain P obtained in stage 1, Call P's implies() method with the Permission Does P imply the Permission being checked? If no, Throw an exception Else, Continue
JAAS / J2SE Authorization Relationship Policy based Uses a "principal" extension Lexically scoped Subject.doAs() & doasprivileged take a PrivilegedAction / PrivilegedExceptionAction as an argument But, no doprivileged() mark Authorization algorithm unmodified
Sample JAAS Policy Consists of grant entries Describe Permissions granted to CodeSources and Principals Each entry may contain one or more Permissions grant signedby "mykey", codebase "file:e:/solutions/app/*" principal com.esite.webprincipal "George" { permission java.lang.runtimepermission "queueprintjob"; };
Sample JAAS Policy - Roles "Roles" can be assigned to Subjects Authorization performed based on "Role" assigned to subject grant signedby "mykey", codebase "file:e:/solutions/app/*" principal com.edmv.methodrole "DMVSupervisor" { permission com.ebank.accountaccess "CloseAccount"; };
Example doas() Lexically scoped Subject... // Authenticate user & build a Subject wuser... // Switch to the authenticated user Subject.doAs(wUser, new PrivilegedAction() { public Object Run(){ // Work to be done as wuser requiring // the addition of the user's privileges return processuserrequest(); } } // end of PrivilegedAction );
Subject.doAs() Effect Extends the effective ProtectionDomains of methods called after the Subject.doAs() call
Example scenario Thread / Class Permissions Effective Thread Permission Class 1 Class 2 { P1, P2 } { P1, P3 } { P1, P2 } { P1 } Class 3 Class 4 { P2 } { P1, P5 } { } { } checkpermission(p1) fails P c1 3 P c2 3 P c3 3 P c4 = { }
Augmented with doas() Thread / Class Permissions Effective Thread Permission Class 1 Class 2 { P1, P2 } { P1, P3 } { P1, P2 } { P1 } doas(x) { P1, P4 } Class 3 Class 4 { P2, P1, P4 } { P1, P5, P4 } { P1 } { P1 } checkpermission(p1) succeeds! P c1 3 P c2 3 (P c3 U P X ) 3 (P c4 U P X ) = { P1 }
Another doas() scenario Thread / Class Permissions Effective Thread Permission Class 1 { P1, P2 } { P1, P2 } doas(x) { P2, P3 } Class 2 { P1, P2, P3 } { P1, P2 } checkpermission(p2) succeeds! P c1 3 (P c2 U P X ) = { P1, P2 }
Another doas() scenario (con't) Thread / Class Permissions Effective Thread Permission Class 1 { P1, P2 } { P1, P2 } doas(x) { P2, P3 } Class 2 { P1, P2, P3 } { P1, P2 } doas(y) { P1, P3 } Class 2 { P1, P3 } { P1 } checkpermission(p2) fails! P c1 3(P c2 UP X )3(P c2 UP Y )={P1}
Summary Subject.doAs() extends the ProtectionDomains of all classes / methods which the PrivilegedAction object calls The basic CodeSource authorization algorithm is unmodified Subsequent Subject.doAs() calls replace the Subject in the authorization algorithm
JAAS and EJBs Java is a trademark and Java 2 is a registered trademark of Sun Microsystems Inc.
EJB Roles Enterprise Bean Provider Application Assembler Deployer System Administrator EJB Server Provider EJB Container Provider
Development/Deployment Process Enterprise Bean Providers Application Assembler Deployer System Administrator
JAAS->EJB security Containers implement security JAAS is a reasonable building block EJB security built around "roles" JAAS built around "Principal"s Mapping required/possible
JAAS->EJB security (cont) Identity (Principal) Mapping Front-end authenticated principal can be mapped to principal required by back-end systems Credential Mapping Used when application server s and backend support different authentication domains i.e. PKI to Kerberos Principal to EJB security role mapping
Exploiting J2SE Security (1/4) How can J2SE mechanisms perform container-based authentication / authorization? JAAS login modules perform principal authentication JAAS principal created Maps authenticated principal to EJB role(s) EJB method authorization is based on permission for an EJB role
Exploiting J2SE Security (2/4) Example: Role as principals : Mapping of principal to "role principals" happens in the JAAS login module iscallerinrole() looks for the appropriate EJB role principal in the in the current thread Typically, does the current caller have permission for this method? Method dispatch authorization tests check, via checkpermission(), the corresponding MethodPermission JAAS-like Syntax: grant MethodPermission(ejb.account.withdraw) to RolePrincipal(customer) grant MethodPermission(ejb.loan.borrow) to RolePrincipal(customer)
Exploiting J2SE Security (3/4) Example: Role as Permissions: Given principal-to-roles map, assign permissions for all roles to this principal Mapping takes place "statically" in the authorization policy definition Potential problems: Treats a role both as a principal and a permission Is dependent on a mapping from method permission from a role permission JAAS-like Syntax grant RolePermission(customer) to sam grant MethodPermission(ejb.account.withdraw) to RolePrincipal(customer) grant MethodPermission(ejb.loan.borrow) to RolePrincipal(customer)
Exploiting J2SE Security (4/4) Example: Role as collection of permissions and credential Role is granted a collection of permissions iscallerinrole() done by checking if caller has access to appropriate RolePermission collection Individual method permission test performed by searching the Role permission collections, granted to the subject, for a method permissions that matches desired operation JAAS-like Syntax define RolePermission (customer) as { MethodPermission(ejb.account.withdraw) MethodPermission(ejb.loan.borrow)... } grant RolePermission(customer) to sam