6. control de acceso

82
Seguridad en aplicaciones JavaEE

Transcript of 6. control de acceso

Page 1: 6. control de acceso

Seguridad en aplicaciones JavaEE

Page 2: 6. control de acceso

CONTENIDOS

Introducción. Criptografía con Java. Infraestructura con PKI con Java. Control de acceso. Aplicaciones con Java SSL. Seguridad en aplicaciones WEB. Introducción a la seguridad en los web services.

Page 3: 6. control de acceso

Control de acceso

Evolución del modelo de seguridad. El “Security Manager”.

Evolución del “Security Manager”.Cómo portar gestores de seguridad de la 1.1.

Ficheros de políticas de seguridad (Policy Files).Cambios en las políticas en Java 2 SDK SE 1.4.Implementación por defecto de políticas de seguridad.Localizaciones por defecto de los ficheros de políticas.Especificar un fichero de políticas adicional en tiempo de ejecución.Cambiar la implementación de Policy.

Page 4: 6. control de acceso

Control de acceso

Sintaxis del fichero de políticas.Ejemplos de ficheros de políticas de seguridad.Expansión de propiedades en los ficheros de políticas.

Java Authentication and Authorization Service (JAAS).

Introducción.Descripción del servicio JAAS.Autenticación JAAS.Autorización JAAS.Conclusión.

Page 5: 6. control de acceso

Control de acceso

Java proporciona en sus API un conjunto de clases, interfaces y herramientas que proporcionan la seguridad para las aplicaciones.

El desarrollador J2EE tiene que tener una comprensión profunda de los fundamentos de la seguridad Java.

Sin embargo, no tiene que saber cómo se implementan las medidas de seguridad.

Page 6: 6. control de acceso

Evolución del modelo de seguridad

JDK 1.1: las aplicaciones locales y applets firmados digitalmente de forma correcta tenían acceso total a recursos vitales del sistema, como el sistema de archivos, mientras que los applets sin firma podían acceder sólo a recursos limitados. Un “security manager” era responsable de determinar qué accesos a recursos se permitían.

Java 2 SDK: basada en políticas de seguridad (policies). La política de seguridad especifica qué permisos están disponibles para el código.

Page 7: 6. control de acceso

Métodos del Security Manager

La clase SecurityManager contiene varios métodos con nombres que comienzan por la palabra check:

checkReadcheckConnect…

Muchos métodos de las bibliotecas de Java llaman a un método check antes de realizar una operación sensible a la seguridad. De este modo se le da una oportunidad al security manager de prevenir la ejecución de la operación lanzando una excepción.

Page 8: 6. control de acceso

Métodos del Security Manager

Una rutina del gestor de seguridad simplemente retorna si la operación está permitida, pero lanza una excepción si la operación no lo está.

Existe otro tipo de métodos contenidos en la clase SecurityManager, relacionados con la existencia y profundidad del class loader:

currentClassLoader

currentLoadedClassinClassLoaderclassLoaderDepth

Page 9: 6. control de acceso

Security Manager en JDK 1.1

Cualquier aplicación que quería instalar un gestor de seguridad tenía que escribirlo ella misma, proporcionando implementaciones concretas apropiadas de los métodos que lanzaban excepciones por defecto, sobre todo los métodos check.

La clase java.lang.SecurityManager era abstracta.

Page 10: 6. control de acceso

Security Manager en JDK 1.1

Las decisiones sobre control de acceso se basaban en:

si una clase con un class loader (por ejemplo, un applet en JDK 1.1) estaba en la pila o no.la profundidad del class loader (cómo de profunda en la pila estaba la ocurrencia más reciente de un método de una clase definida usando un class loader).

Page 11: 6. control de acceso

Security Manager en JDK 1.1

Ejemplo de método check de un SecurityManager. No permite la llamada a Runtime.exit cuando haya en la pila una clase definida con un class loader:

public void checkExit(int status) {

if (inClassLoader()) {

throw new SecurityException(…);

}

}

Page 12: 6. control de acceso

Security Manager en JDK 1.1

Ejemplo de método check de un SecurityManager. No permite la creación de un class loader cuando la profundidad del propio sea 2:

public void checkCreateClassLoader() {

if (ClassLoaderDepth()==2) {

throw new SecurityException(…);

}

}

Page 13: 6. control de acceso

Security Manager en Java 2 SDK

Cambios en java.lang.SecurityManager:Ya no es una clase abstracta.La mayoría de los métodos check llaman a un nuevo método checkPermission, que por defecto llama al método del mismo nombre (checkPermission) en la nueva clase AccessController.

Los métodos usados en JDK 1.1 para determinar si una clase está en la pila o para calcular la profundidad del cargador de clases han sido modificados en el Java 2 SDK para ignorar los cargadores de clases del sistema y contextos de seguridad que ha sido garantizados por java.security.AllPermission.

Page 14: 6. control de acceso

Security Manager en Java 2 SDK

Como SecurityManager ya no es una clase abstracta, ahora se puede instanciar y usar directamente como gestor de seguridad por defecto. Esto se puede hacer:

Estableciendo la propiedad del sistema adecuada conforme se lanza la VM:java –Djava.security.manager TuAplicacion

Vía código:System.setSecurityManager(new SecurityManager());

Su comportamiento se podrá modificar mediante ficheros de políticas de seguridad (policy files).

Page 15: 6. control de acceso

Security Manager en Java 2 SDK

Ejemplo:

Analizar la salida.

public class PropiedadesSistema { public static void main(String[] args) { System.out.println(System.getProperty("java.version")); System.out.println(System.getProperty("java.home")); System.out.println(System.getProperty("java.vendor")); }}

Page 16: 6. control de acceso

Políticas de seguridad

La política de seguridad para un entorno de aplicación en lenguaje Java está asociado a un objeto Policy.

Se representa mediante una subclase de Policy, que proporciona una implementación de los métodos abstractos de la clase Policy (en el paquete java.security).

Esta implementación viene indicada en el fichero java.security .

Page 17: 6. control de acceso

Políticas de seguridad

Page 18: 6. control de acceso

Políticas de seguridad

Con la integración del servicio JAAS en el J2SDK 1.4, la API java.security.Policy maneja consultas basadas en Principal.

La implementación por defecto de las políticas de seguridad soportan entradas grant (garantías de permiso) basadas también en principales.

El control de acceso puede ahora basarse no sólo en qué código se está ejecutando, sino también en quién lo está ejecutando.

Page 19: 6. control de acceso

Implementación por defecto de las políticas de seguridad

Las políticas se establecen en uno o más ficheros de políticas de seguridad (Policy File), que detallan qué permisos se conceden al código en función de qué código es, de que fuente viene y quién lo está ejecutando.

Un fichero de políticas está codificado UTF-8 y se puede crear con un simple editor de texto o la herramienta gráfica Policy Tool.

Por defecto hay un único fichero global al sistema y otro opcional para el usuario.

Page 20: 6. control de acceso

Localización por defecto de los ficheros de políticas

El fichero de políticas de seguridad del sistema se localiza por defecto en:

java.home/lib/security/java.policy (Solaris)java.home\lib\security\java.policy (Win32)

La propiedad del sistema “java.home” especifica el directorio de instalación del SDK.

El fichero de políticas del usuario se localiza por defecto en:

user.home/.java.policy (Solaris)user.home\.java.policy (Win32)

Page 21: 6. control de acceso

Localización por defecto de los ficheros de políticas

Page 22: 6. control de acceso

Localización por defecto de los ficheros de políticas

El fichero de políticas instalado por defecto con el SDK permite a cualquier:

Escuchar en un puerto no privilegiadoPermite a cualquier código leer propiedades “estándar” que no sean sensibles a la seguridad.

Page 23: 6. control de acceso

Policy files

El funcionamiento del sistema de políticas de seguridad es: primero se carga el fichero de políticas del sistema y, posteriormente, se añade el/los de usuario.

Las localizaciones de los ficheros de políticas de seguridad están detalladas en el fichero de propiedades de seguridad, que se encuentra en:

java.home/lib/security/java.security (Solaris)java.home\lib\security\java.security (Win32)

Page 24: 6. control de acceso

Policy files

Las localizaciones de los ficheros de políticas están especificadas como valores de las propiedades que tienen la siguiente forma:

policy.url.n =URL (n es un número, que actúa como contador del número de ficheros de políticas).

Ejemplo:policy.url.1=file:${java.home}/lib/security/java.policypolicy.url.2=file:${user.home}/.java.policy

Se cargarán sólo los ficheros indicados con índices consecutivos. Si hay un hueco en los números no se cargarán los ficheros a partir del hueco.

Page 25: 6. control de acceso

Policy files

Page 26: 6. control de acceso

Policy files

Page 27: 6. control de acceso

Policy files

Se puede especificar un fichero de políticas adicional en tiempo de ejecución:

java –Djava.security.manager –Djava.security.policy=unaURL MiApp

Ese ejemplo cargaría el fichero especificado por unaURL además de los especificados en las propiedades de seguridad. Si se usase un ‘==‘ en lugar de un ‘=‘ entonces sólo se cargaría el fichero de políticas especificado.

Page 28: 6. control de acceso

Cambio de implementación

Se puede proporcionar una clase de políticas alternativa para reemplazar la implementación de referencia de la clase Policy.

Una subclase de Policy.Implementación de todos los métodos necesarios.

La implementación de referencia puede ser cambiada editando el fichero java.security cambiando la propiedad:

policy.provider = NombreClase

Page 29: 6. control de acceso

Sintaxis del fichero de políticas

Los ficheros de configuración de políticas de seguridad especifican qué permisos (qué tipos de accesos a recursos del sistema) se garantizan al código de una fuente concreta de código y ejecutado por un determinado principal.

Un policy file contiene:Una entrada keystore (opcional).Cero o más entradas grant.

Page 30: 6. control de acceso

Sintaxis del fichero de políticas

La entrada keystore: sirve para definir el keystore usado para buscar las claves públicas de los firmantes especificados en las entradas grant del fichero.

Si alguna entrada grant especifica alias de firmantes o principales entonces debe aparecer una entrada keystore.

Sólo puede haber una entrada keystore en el fichero de políticas de seguridad. Si se ponen más de una, sólo se considerará la primera.

Puede aparecer en cualquier lugar del fichero.

Page 31: 6. control de acceso

Sintaxis del fichero de políticas

Sintaxis de la entrada keystore:keystore "ks_url", "ks_tipo", "ks_proveedor";keystorePasswordURL "password_url";

Las URLs indicadas son relativas con respecto al directorio donde se encuentra el fichero de políticas en cuestión.

Tipo de keystore: define el formato de los datos y su almacenamiento y los algoritmos usados para protegerlo. El tipo por defecto soportado por Sun es un tipo propietario llamado “JKS”.

Page 32: 6. control de acceso

Sintaxis del fichero de políticas

Entradas grant: especifica qué permisos se conceden a qué código. El formato básico es:

grant signedBy "signer_names", codeBase "URL", principal principal_class_name "principal_name", principal principal_class_name "principal_name", ... {

permission permission_class_name "target_name", "action", signedBy "signer_names"; permission permission_class_name "target_name", "action", signedBy "signer_names"; ...

};

Page 33: 6. control de acceso

Sintaxis del fichero de políticas

Un código en ejecución siempre viene de una fuente (code source) concreta, representada por un objeto CodeSource y que se está ejecutando como un principal concreto, representado por un objeto Principal.

El code source incluye la URL donde se originó el código y, además, una referencia a los certificados que contienen las claves públicas correspondientes a las claves privadas usadas para firmar dicho código:

codeBasesignedBy

Page 34: 6. control de acceso

Sintaxis del fichero de políticas

Los campos signedBy, principal y codeBase son opcionales y no importa el orden entre ellos.

signedBy: referencia un alias de un certificado que está almacenado en el keystore. Una entrada con signedBy está concediendo permisos al código firmado con la clave privada correspondiente a la clave pública almacenada en la entrada del keystore indicada por el alias. Su valor puede ser una lista de múltiples alias, indicando que el código está firmado por todos ellos (operación AND).

Page 35: 6. control de acceso

Sintaxis del fichero de políticas

principal: especifica un par nombre de clase/nombre de principal.

Nota: si se especifica el valor del principal como una cadena de texto entre comillas (sólo se está dando el nombre de principal, en lugar del par), se trata como una alias del keystore. Si no se encuentra en el keystore el certificado correspondiente a ese alias, se ignora la entrada grant entera. Si se encuentra, se considera que el nombre de la clase es “javax.security.auth.x500.X500Principal” y la cadena el nombre distinguido del principal.

Page 36: 6. control de acceso

Sintaxis del fichero de políticas

Ejemplo:

Se está garantizando permisos de lectura y escritura a ficheros del directorio home del usuario “duke” y de creación de sockets a “duke.com” a cualquier código ejecutándose como “duke” o “0”.

grant

Principal com.sun.security.auth.SolarisPrincipal "duke",

Principal com.sun.security.auth.SolarisNumericUserPrincipal "0" {

permission java.io.FilePermission "/home/duke", "read, write";

permission java.net.SocketPermission "duke.com", "connect";

};

Page 37: 6. control de acceso

Sintaxis del fichero de políticas

Las entradas de permisos: deben empezar por la palabra permission. Los permisos corresponden a clases específicas de Java.

Para muchos permisos se requiere una acción, por ejemplo, para FilePermission, que indique que tipo de acceso a ficheros es el que se está permitiendo.

Page 38: 6. control de acceso

Sintaxis del fichero de políticas

Las entradas permission tienen una claúsula signedBy opcional, que indica que la clase correspondiente al permiso debe estar firmada por el alias indicado.

Ejemplo: se concede un permiso de tipo Foo si la clase Foo.class se encuentra en un JAR que has sido firmado por “FooSoft”.

grant {

permission Foo “foobar”, signedBy “FooSoft”;

};

Page 39: 6. control de acceso

Sintaxis del fichero de políticas

Las clases de sistema no están sujetas a las restricciones de las políticas de seguridad, por lo que si, en el ejemplo anterior, Foo.class fuera una clase de sistema, entonces ese permiso estaría implícito.

Las entradas permission termina con ‘;’. En las palabras reservadas de los ficheros de

políticas no se distinguen mayúsculas y minúsculas.

Page 40: 6. control de acceso

Sintaxis del fichero de políticas

Tipos de permisos incorporados por JDK (consultar las API):

java.security.AllPermission

java.security.SecurityPermission

java.security.UnresolvedPermission

java.awt.AWTPermission

java.io.FilePermission

java.io.SerializablePermission

java.lang.reflect.ReflectPermission

java.lang.RuntimePermission

java.net.NetPermission

Page 41: 6. control de acceso

Sintaxis del fichero de políticas

java.net.SocketPermission

java.sql.SQLPermission

java.util.PropertyPermission

java.util.logging.LoggingPermission

javax.net.ssl.SSLPermission

javax.security.auth.AuthPermission

javax.security.auth.PrivateCredentialPermission

javax.security.auth.kerberos.DelegationPermission

javax.security.auth.kerberos.ServicePermission

javax.sound.sampled.AudioPermission

Page 42: 6. control de acceso

Ejemplos de Policy Files

grant signedBy "Duke" { permission java.io.FilePermission "/tmp/*", "read,write";};

grant { permission java.util.PropertyPermission "java.vendor", "read";};

grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; permission java.security.SecurityPermission "Security.setProperty.*";};

grant principal javax.security.auth.x500.X500Principal "cn=Alice" { permission java.io.FilePermission "/home/Alice", "read, write";};

grant codebase "http://www.games.com", signedBy "Duke", principal javax.security.auth.x500.X500Principal "cn=Alice" { permission java.io.FilePermission "/tmp/games", "read, write";};

Page 43: 6. control de acceso

Especificación de rutas de archivos en Win32

Cuando se está concediendo un FilePermission, el “target_name” es una ruta de archivo. En sistemas Win32, si se especifica directamente una ruta en una cadena, es necesario incluir dos barras (\\) por cada una que aparezca en la ruta, así:

grant {

permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";

};

Page 44: 6. control de acceso

Expansión de propiedades

La expansión de propiedades es posible tanto en los ficheros de políticas de seguridad como en los ficheros de propiedades de seguridad.

La expansión de propiedades es similar a la expansión de variables en una shell. Así, cuando una cadena como “${propiedad}” aparece en un fichero de políticas o en uno de propiedades de seguridad, será expandido al valor de la propiedad correspondiente del sistema.

Page 45: 6. control de acceso

Expansión de propiedades

Ejemplo:permission java.io.FilePermission "${user.home}", "read";

Si la propiedad “user.home” del sistema vale “/home/cathy” se expandirá a:

permission java.io.FilePermission "/home/cathy", "read";

Para ayudar a la creación de ficheros de políticas independientes de la plataforma, también se puede usar la notación especial “${/}”, que es una referencia corta a “${file.separator}” (propiedad del sistema que indica cuál es el separador usado en las rutas, ‘\’ en Win32, ‘/’ en Unix, por ejemplo).

Page 46: 6. control de acceso

Expansión de propiedades

Ejemplo:permission java.io.FilePermission "${user.home}${/}*", "read”;

Si la propiedad “user.home” del sistema vale “/home/cathy” se expandirá a:

permission java.io.FilePermission "/home/cathy/*", "read";

No se pueden anidar las propiedades para su expansión. Estaría MAL:

“${user.${foo}}”

Si una propiedad dentro de una entrada grant, permission o keystore no se puede expandir, se ignora la entrada entera.

Page 47: 6. control de acceso

Servicio de autenticación y autorización

Introducción. Autenticación JAAS. Ejemplo JAAS. Autorización JAAS.

47

Page 48: 6. control de acceso

Introducción

JAAS aumenta los controles de acceso basados en código existentes anteriormente con controles de acceso basado en el usuario y capacidades de autenticación.

Esto permite garantizar permisos basados no sólo en qué código se está ejecutando, sino también en quién lo está ejecutando.

Page 49: 6. control de acceso

Introducción

JAAS consiste en dos partes: la autenticación y la autorización. Esto quiere decir que se puede usar tanto para la autenticación como para la autorización:

Para la autenticación de usuarios y así determinar de forma segura quién está ejecutando código Java, sin tener en cuenta si el código es una aplicación Java independiente, un applet, un EJB o un servlet.Para la autorización de usuarios y garantizar que tienen los permisos requeridos para realizar las acciones.

Page 50: 6. control de acceso

Introducción

La autenticación está basada en los Pluggable Authentication Modules (PAMs) con un framework que se usará tanto para clientes como para servidores.

La realización de la autenticación usando PAMs permite a las aplicaciones Java ser independientes del mecanismo de autenticación subyacente.

Esto tiene la ventaja de que nuevos o revisados mecanismos de autenticación podrán ser incorporados sin modificar la aplicación en sí misma.

Page 51: 6. control de acceso

Introducción

La autorización es una extensión del mecanismo existente basado en ficheros de políticas que se usa para especificar qué se le permite a una aplicación hacer o no hacer.

Está basada en dominios de protección. Anteriormente, este mecanismo garantiza permisos en función de dónde viene el código y no en quién lo está ejecutando.

Con JAAS, los permisos y el control de acceso se pueden basar no sólo en qué código se está ejecutando sino también en quién lo está haciendo, como ya se ha visto.

Page 52: 6. control de acceso

Introducción

Los paquetes siguientes componen la arquitectura JAAS:

javax.security.auth: contiene clases básicas para la autenticación y autorización.javax.security.auth.callback: contiene una estructura de clases e interfaces para envío de información de autenticación a la aplicación.java.security.auth.login: contiene clases que emplean para conectarse a un dominio de seguridad.javax.security.auth.spi.

Page 53: 6. control de acceso

Autenticación JAAS

Sujeto: identidad en un sistema que se quiere autenticar y a la que se le quieren asignar derechos de acceso.

Un sujeto puede ser un usuario humano, un proceso o una máquina y está representado por la clase javax.security.auth.Subject.

Analizar la clase en las APIs de Java.

Page 54: 6. control de acceso

Autenticación JAAS

Un sujeto puede interactuar con múltiples autoridades (una clave para una web bancaria, otra para una cuenta de correo, otra para una intranet…)

Por esa razón, se usa java.security.Principal para representar la identidad en esas interacciones.

Ver APIs de Java.

Page 55: 6. control de acceso

Autenticación JAAS

La interfaz Principal es una noción abstracta que puede ser usada para representar una entidad, una empresa o una ID de usuario. Un Subject puede contener múltiples principales.

Contexto de conexión (LoginContext): objeto a través del que los clientes interactúan con JAAS.

Módulo de conexión (LoginModule): responsable de implementar y realizar la autenticación. Será implementado por diversos proveedores de tecnología de autenticación.

Page 56: 6. control de acceso

Autenticación JAAS

Los elementos que integran el sistema son:Contexto de login (LoginContext).Configuración específica.Módulos de login (LoginModule).CallBackHandler.

Page 57: 6. control de acceso

Autenticación JAAS

Contexto de login:Funcionamiento general: el objeto LoginContext lee la configuración e instancia el LoginModule especificado.Normalmente se usarán módulos de conexión ya desarrollados y no deberemos codificar ninguno.Sun Microsystems pone a nuestra disposición varios: JndiLoginModule KeyStoreLoginModule Krb5LoginModule NTLoginModule UNIXLoginModule

Page 58: 6. control de acceso

Autenticación JAAS

Contexto de login:La cadena de módulos que va a ser aplicada se indica a la hora de crear el objeto contexto mediante su constructor.public LoginContext()Ver la API de Java.

La configuración se indica mediante un fichero de configuración.

Page 59: 6. control de acceso

Autenticación JAAS

Configuración: Especifica la tecnología de autenticación, o LoginModule usado. Así se puede cambiar el LoginModule usado sin que sea necesario ningún cambio en el código de la aplicación.Se apoya en la clase abstracta Configuration del paquete javax.security.auth.login.

Mirar APIs de Java.

Application { ModuleClass Flag ModuleOptions; ModuleClass Flag ModuleOptions; ModuleClass Flag ModuleOptions;};

Page 60: 6. control de acceso

Autenticación JAAS

Configuración (cont.): ModuleClass: nombre de la clase. Flag: Required. Requisite. Sufficient. Optional.

Login { com.sun.security.auth.module.UnixLoginModule required; com.sun.security.auth.module.Krb5LoginModule optional; };

Page 61: 6. control de acceso

Autenticación JAAS

Configuración (cont.): Required: El módulo de conexión asociado debe ser capaz de

autenticar el sujeto en todo el proceso de autenticación para poder éxito. Independientemente de que falle o no, se continua en la cadena de módulos hasta el final.

Requisite: El módulo de conexión asociado debe tener éxito para

que se considere que todo el proceso de autenticación ha tenido éxito. Si el módulo falla, el proceso de autenticación no continua. Devuelve el control a la aplicación.

Page 62: 6. control de acceso

Autenticación JAAS

Configuración (cont.): Sufficient: No es requisito indispensable para la autenticación. Ahora

bien, si el módulo se supera con éxito la autenticación es automática.

Optional: no es necesaria la capacidad que tiene el módulo de conexión asociado para autenticar al sujeto. El proceso de autenticación sigue por la lista buscando otros módulos de conexión.

Page 63: 6. control de acceso

EJEMPLO JAAS: MyClient.java

import javax.security.auth.Subject;import javax.security.auth.login.LoginContext;import javax.security.auth.login.LoginException;

public class MyClient { public static void main(String argv[]) { LoginContext ctx = null; try { ctx = new LoginContext("WeatherLogin", new MyCallbackHandler()); } catch(LoginException le) { System.err.println("LoginContext cannot be created. "+ le.getMessage()); System.exit(-1); } catch(SecurityException se) { System.err.println("LoginContext cannot be created. "+ se.getMessage()); } try { ctx.login(); } catch(LoginException le) { System.out.println("Authentication failed. " + le.getMessage()); System.exit(-1); } System.out.println("Authentication succeeded."); System.exit(-1); }

}

Page 64: 6. control de acceso

Autenticación JAAS

Módulo de login:Si se implementa un LoginModule se debe dar cuerpo a los siguientes métodos (LoginContext los usará en ese orden): initialize: el propósito de este método es inicializar

este LoginModule con la información relevante. El Subject pasado a este método se usa para almacenar los principales (Principal) y credenciales (Credential) si la conexión tiene éxito. Nótese que este método recibe un CallbackHandler que puede ser usado para introducir información de la autenticación.

Page 65: 6. control de acceso

Autenticación JAAS

Módulo de login:login: le pide al LoginModule que autentique al Subject. Nótese que el Principal todavía no ha sido asignado.commit: se llama a este médodo si tiene éxito la autenticación total del LoginContext.abort: informa al LoginModule de que algún proveedor o módulo ha fallado al autenticar al Subject. En ese caso la conexión entera (el logado) debe fracasar.logout: desconecta al Subject borrando los principales (Principal) y credenciales (Credential) del Subject.

Page 66: 6. control de acceso

Ejemplo JAAS: WeatherLoginModule.javaimport java.io.*;import java.util.*;import java.security.Principal;import javax.security.auth.Subject;import javax.security.auth.callback.*;import javax.security.auth.spi.LoginModule;import javax.security.auth.login.LoginException;

public class WeatherLoginModule implements LoginModule { private Subject subject; private ExamplePrincipal entity; private CallbackHandler callbackhandler; private static final int NOT = 0; private static final int OK = 1; private static final int COMMIT = 2; private int status;

public void initialize(Subject subject, CallbackHandler// callbackhandler, Map state, Map options) { status = NOT; entity = null; this.subject = subject; this.callbackhandler = callbackhandler; }

Page 67: 6. control de acceso

Ejemplo JAAS: WeatherLoginModule.java

public boolean login() throws LoginException {

if(callbackhandler == null) { throw new LoginException("No callback handler is available"); } Callback callbacks[] = new Callback[1]; callbacks[0] = new NameCallback("What is the weather like today?"); String name = null; try { callbackhandler.handle(callbacks); name = ((NameCallback)callbacks[0]).getName(); } catch(java.io.IOException ioe) { throw new LoginException(ioe.toString()); } catch(UnsupportedCallbackException ce) { throw new LoginException("Error: "+ce.getCallback().toString()); } if(name.equals("Sunny")) { entity = new ExamplePrincipal("SunnyDay"); status = OK; return true; } else { return false; } }

Page 68: 6. control de acceso

EJEMPLO JAAS: WeatherLoginModule.java

public boolean commit() throws LoginException { if(status == NOT) { return false; } if(subject == null) { return false; } Set entities = subject.getPrincipals(); if(!entities.contains(entity)) { entities.add(entity); } status = COMMIT; return true; } public boolean abort() throws LoginException { if((subject != null) && (entity != null)) { Set entities = subject.getPrincipals(); if(entities.contains(entity)) { entities.remove(entity); } } subject = null; entity = null; status = NOT; return true; }

Page 69: 6. control de acceso

Ejemplo JAAS: WeatherLoginModule.java

public boolean logout() throws LoginException { subject.getPrincipals().remove(entity); status = NOT; subject = null; return true; }

}

Page 70: 6. control de acceso

Autenticación JAAS

CallbackHandler:Una aplicación basada en JAAS implementa la interfaz CallbackHandler de forma que pueda interactuar con los usuarios para introducir los datos específicos de autenticación, tales como usuario y clave, o mostrar mensajes de error y advertencia. Implementar la interfaz significa darle cuerpo al método handle para recuperar o mostrar la información requerida en las llamadas.

Page 71: 6. control de acceso

Autenticación JAAS

CallbackHandler:Diferentes tipos de respuesta: NameCallback: pasa al método handle de

CallbackHandler una respuesta al nombre de autenticación.

PasswordCallback. ChoiceCallback: muestra una lista de opciones y

captura la elegida por el usuario. ConfirmationCallback: pregunta por YES/NO, OK/

CANCEL, YES/NO/CANCEL u otras confirmaciones similares.

Page 72: 6. control de acceso

Autenticación JAAS

TextInputCallback: recupera información genérica de texto.TextOutputCallback: muestra información o mensajes de error o advertencia.Otras clases que implementan la interfaz Callback…

Page 73: 6. control de acceso

Ejemplo JAAS: MyCallbackHandler.java

import javax.security.auth.Subject;import javax.security.auth.login.LoginContext;import javax.security.auth.login.LoginException;

public class MyCallbackHandler implements CallbackHandler {

public void handle(Callback callbacks[]) throws IOException, UnsupportedCallbackException { for(int i=0;i<callbacks.length;i++) { if(callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback) callbacks[0]; System.err.print(nc.getPrompt()); System.err.flush(); String name = (new BufferedReader( new InputStreamReader(System.in))).readLine(); nc.setName(name); } else { throw(new UnsupportedCallbackException(callbacks[i], "Callback handler not support")); } } }

}

Page 74: 6. control de acceso

Ejemplo JAAS: ExamplePrincipal.java

Esta clase es una implementación de Principal, a la que se ha hecho referencia en nuestro LoginModule:

import java.security.Principal;

public class ExamplePrincipal implements Principal { private final String name;

public ExamplePrincipal(String name) { if(name == null) { throw new IllegalArgumentException("Null name"); } this.name = name; }……

Page 75: 6. control de acceso

Ejemplo JAAS: ExamplePrincipal.java

…… public String getName() { return name; } public String toString() { return "ExamplePrincipal: "+name; } public boolean equals(Object obj) { if(obj == null) return false; if(obj == this) return true; if(!(obj instanceof ExamplePrincipal)) return false; ExamplePrincipal another = (ExamplePrincipal) obj; return name.equals(another.getName()); } public int hasCode() { return name.hashCode(); }}

Page 76: 6. control de acceso

Ejemplo JAAS: example.conf

Fichero de configuración. La entrada del fichero debe ser la misma que se usa en el cliente. Especifica el módulo que se va a usar para la autenticación.

WeatherLogin { WeatherLoginModule required;

};

Page 77: 6. control de acceso

Ejecución del ejemplo JAAS

Crear un directorio. Copiar MyClient.java, WeatherLoginModule.java, ExamplePrincipal.java y example.conf a ese directorio.

Compilar todos los fichero .java: javac *.java

Ejecutar el cliente usando el siguiente comando, que especifica el fichero de configuración de conexión:

java –Djava.security.auth.login.config=example.conf MyClient

Page 78: 6. control de acceso

Autorización JAAS

La autorización JAAS extiende la arquitectura de seguridad de Java centrada en el código que usa políticas de seguridad para especificar qué derechos de acceso están garantizados para un código en ejecución.

Los permisos se pueden garantizar no sólo en función de qué código se está ejecutando, sino además, quién lo está ejecutando.

Los permisos se pueden garantizar en el fichero de políticas para especificar principales.

Page 79: 6. control de acceso

Autorización JAAS

Importante:Para la autorización primero se debe haber procedido a la autenticación del usuario.Hay que llamar al método doAs (o doAsPrivileged) de la clase Subject, que invocará el método run que contiene el código a ser ejecutado como el sujeto especificado.

Page 80: 6. control de acceso

Ejemplo de Autorización JAAS

Vamos a ampliar el ejemplo usado en autenticación JAAS para que trabaje también con autorización.

Los ficheros ExamplePrincipal.java, WeatherLoginModule.java y example.conf no sufren ninguna modificación.

El objetivo del ejemplo es que el código habilite autorice a un usuario que se ha autenticado a realizar una acción.

Page 81: 6. control de acceso

Ejemplo de Autorización JAAS

MyClient.java: ahora, una vez que la autenticación tenga éxito, deberá realizar lo siguiente:

Se hace que el sujeto realice una acción (definida en la clase MyAction) como el sujeto autenticado.

Subject subject = ctx.getSubject(); PrivilegedAction action = new MyAction(); Subject.doAsPrivileged(subject, action, null); try { ctx.logout(); } catch(LoginException le) { System.out.println("Logout: " + le.getMessage()); }

Page 82: 6. control de acceso

Ejemplo de Autorización JAAS

MyAction.java:

import java.io.File;import java.security.PrivilegedAction;

public class MyAction implements PrivilegedAction { public Object run() { File file = new File("max.txt"); if(file.exists()) { System.out.println("The file exists in the current working directory"); } else { System.out.println("The file does not exist in the current working directory"); } return null; }