10.3.1 Receiver Security SandBoxThe advantages of executable content, such as ECMA Script or Java classes, come from the increase in power and flexibility provided by software programs. The essence of the problem is that running programs on an iTV receiver typically gives that program access to certain resources on that receiver. If an iTV receiver that downloads and executes code is not careful to restrict access, untrusted applications may contain malicious programs with the same ability to do mischief as a hacker who had gained access to the receiver. Unfortunately, the solution is not as simple as completely restricting a downloaded program's access to resources: To be useful, a program needs to access certain resources. Thus, if one desires useful and secure executable content, access to resources needs to be carefully controlled. In the context of iTV, the following operations are typically considered sensitive:
The Java security framework was designed to address this problem. The original security model provided by the Java platform, known as the sandbox model , existed to provide a very restricted environment in which to run untrusted code obtained from the open network. In the sandbox model local code is trusted to have full access to vital system resources, such as the file system, but downloaded remote code (an applet) is not trusted and can access only the limited resources provided inside the sandbox. A security manager is responsible in this and subsequent platforms for determining which resource accesses are allowed. Receivers typically comply with the following security rules:
10.3.2 Java Cryptography Architecture (JCA)While powerful, the JCA is not required to be implemented by most approved iTV standards. However, in many cases manufacturers may choose to include its implementation as an option, and its presence may influence the purchase decision of many consumers who are sensitive about their privacy. The JCA, introduced in JDK 1.1, is a framework API for access to services implemented by pluggable security "providers." It provides support for Digital Signature Algorithms (DSA), MD5, SHA1, key-generation algorithms, conversions between different key representations, simple certificate management (JDK 1.1 did not provide format-specific APIs). Certificate management capabilities include certificate factory support to generate certificates and CRLs from their encodings (Sun implements X.509's). JCA also provides simple key management database or keystore. It also ads a random-number generation algorithm that could be used to support the JCA. The Java 2 platform introduced the Java Cryptography Extension (JCE) as well as some changes to the JCA; it was separated from JCA due to export control issues. It adds encryption, key exchange, key generation, Message Authentication Code (MAC) and multiple providers (to be distinguished from MAC). It supports fine-grained configurable policies and provides runtime state protection using the ProtectionDomain or CodeSource or Policy classes. It provides a runtime security check algorithm utilizing permission classes and subclasses. A SecurityManager and AccessController are used to define the security sandbox. The notion of Guard and GuardedObjects was introduced as well.
Additional areas of recent development, beyond JCA and JCE include Java Secure Socket Extension (JSSE) and Java Authentication and Authorization Service (JAAS). JSSE Implements SSL. JAAS is based on PAM, which is pluggable authenticators for passwords, smart cards, biometric devices, and so on. The JAAS enables code authors to specify whether authenticators are required, requisite (i.e., stop on failure), sufficient (i.e., not required), or optional. It extends the SecurityManager by introducing user -centric (vs. code-centric) control through granting permissions to a Principal in addition to a CodeSource . 10.3.2.1 Evolution of SecurityManagersThe SecurityManager class contains check methods that perform permission testing, such as checkRead() and checkConnect() . Various methods in the Java libraries call a check method before performing each potentially security-sensitive operation. This coding convention provides the security manager an opportunity to prevent completion of the operation by throwing an exception. A security manager routine simply returns if the operation is permitted, but throws a SecurityException if the operation is not permitted. The only exception to this convention is checkTopLevelWindow() , which returns a boolean value. The other key methods contained in the SecurityManager class are those related to class loader existence and depth: currentClassLoader() , currentLoadedClass() , inClassLoader() , and classLoaderDepth() In JDK 1.1, the class java.lang.SecurityManager was an abstract class. The default implementations of the security manager check methods threw exceptions. The class loader and depth-related classes were often implemented in native code. A Java application that needed a security manager had to provide their own implementation with the appropriate concrete implementations of the methods (e.g., check methods) that threw exceptions by default. Security managers based on the JDK 1.1 applet (and iTV Xlet) security manager model typically based their access control decisions on two factors: Whether or not a class with a class loader was on the stack, and how far down the stack the most recent occurrence of a method from a class defined using a class loader was. For example, a typical 1.1-style security manager might have a checkExit() method like the following: public void checkExit(int status) { switch (status) case ...: if (classLoaderDepth() > 2) { throw new SecurityException(..); } break; case ...: if (inClassLoader()) { throw new SecurityException(..); } } } Such a checkExit() method would not allow Runtime.exit() to be called in certain situations by throwing an exception. In this specific example, certain execution states do not allow the presence of a class loader at all, whereas other states allow a shallow class loader of up to two stack levels. JDK 1.2 introduced a number of changes into the class java.lang.SecurityManager to allow it usage of a default security manager. It is no longer an abstract class, and can thus be installed as-is. Most check methods called a new checkPermission() method, which by default calls the method of the same name (checkPermission) in the new AccessController class. Those methods that do not call checkPermission() have reasonable defaults. Methods used in JDK 1.1 to determine if a class loader is on the stack and/or to calculate class loader depth have been modified in JDK 1.2 to ignore system class loaders and security contexts that have been granted java.security.AllPermission . Since java.lang.SecurityManager is no longer abstract, it can be installed and used as the default security manager, in many ways. For example, some VM implementation allow setting a system property when launching some VM implementations, e.g., java -Djava .security.manager <Application> . Alternatively, an application can install a SecurityManager directly using the call System.setSecurityManager(new SecurityManager()). The behavior of a SecurityManager can be customized by modifying policy files. See the security guide on policy files for more information. In JDK 1.2, the SecurityManager methods related to class loaders and class loader depth are not called by any of the check methods, and they are deprecated. They should not be used by any new security managers, and it is recommended that their use be eliminated from existing security managers as well. However, they are left in for backward compatibility and they have been modified in an attempt to enable old 1.1-style security managers to still work under JDK 1.2, without modification. For example, the constructor for java.security.SecureClassLoader() has an explicit call to SecurityManager.checkCreateClassLoader() even though the constructor for its superclass ( ClassLoader ) also does. If the check was not placed in the constructor for SecureClassLoader , then a 1.1-style security manager would allow untrusted code to extend SecureClassLoader and construct class loaders, as the class loader depth would always be greater than 2. 10.3.3 Java 2 Runtime Security CheckMost iTV standards do not support Java 2 and therefore do not support the security checking framework described next . However, this does not preclude a specific iTV implementation from supporting this feature. Runtime security checks are one of the capabilities enabled by the use of a JVM to execute Java bytecode. The design goal of this framework was to support actions on behalf of another, for example, one thread posts an event to another, as well as delayed actions or background operations (e.g., cron job). The runtime security check is based on the notion of execution context. The latter could be accessed using the getContext() method, which takes a snapshot of current execution context (i.e., stack trace). The result includes snapshoting ancestor threads stored in the AccessControlContext object. The runtime security check is performed as follows. If method M requires permission P, then M's implementation must call current SecurityManager.checkPermission(P) , which by default, calls the AccessController . For each call stack entry, the runtime security check performs the following:
For example, consider the use of multiple ProtectionDomains . Let Instance1 of Class1 be associated with ProtectionDomain M1 , and assume that Class1 calls Instance2 of Class2, which is associated with ProtectionDomain M2 . Class2 , in turn , calls a system method of Class3 in a system ProtectionDomain M3 . With the last call, M3 asks for a permission check. Permissions are checked against the ProtectionDomains for the system object Class3 , then, going up the call stack, asks for a check on Class2 , and Class1 . The implications of this algorithm are as follows: default privileges are the intersection (i.e., minimum) of all class' permissions in call tree. A call to doPrivileged() enables all class' privileges; the node calling doPrivileged() is a root of a call-tree under which the default permissions are unrelated to that of its parent. When doPrivileged() is called without a context, all privileges are enabled. When called with a context, enables only those privileges that are given to the context; this is safe because the resulting privileges are always subsumed or equal to those of that context. 10.3.4 Guarded ObjectsGuardedObject s are used to protect methods and references against unauthorized access. iTV standards do not support Java 2 and therefore do not support guarded objects. However, this does not preclude a specific iTV implementation from supporting this feature. A GuardedObject encapsulates a target object and a Guard object, such that access to the target object is possible only if the Guard object allows it. Once an object is encapsulated by a GuardedObject , access to that object is controlled by the getObject() method, which invokes the checkGuard() method on the Guard object that is guarding access. |