Tips: recibir mensajes SMS online
Desde hace tiempo, la mayoría de los sites requieren una dirección de email válida para poder registrar un usuario, a la cual envían un código de confirmación para terminar la validación. Si bien esto sigue siendo igual en la mayoría de los casos, cada vez más sitios empiezan a requerir algo más... un número de celular. Estos sites envían al número ingresado un código de confirmación, el cual hay que ingresar para validar al usuario.
En diferentes sites el número de celular es opcional y permite autenticación de dos vías, lo cual refuerza el sistema de autenticación, pero en otros es mandatorio colocar el número.

Los paranoicos como yo (o los usuarios que todavía desean poseer un mínimo de privacidad), no deseamos colocar el condenado número para que después la página pueda, como mínimo, enviarnos SPAM. Por ello me puse a buscar alguna alternativa que me permita recibir mensajes en un número online. Así fue como llegué al excelente artículo How to receive SMS online to bypass SMS verification? 
El artículo resume cuáles páginas permiten la recepción de SMSs online. Las mismas proveen una serie de números, controlados por ellos, los cuales están aptos para recibir SMSs internacionales. Cuando se recibe un mensaje, el mismo es agregado en la web para que pueda ser leído.
Las alternativas más simples de utilizar (digo simples porque no necesitan creación de usuario) son Receive-SMS-Online y ReceiveSMSOnline. De estas, la que a mi me funcionó es la primera, utilizando los números de Noruega. En el resto de los números no pude recibir mensajes. La ventaja adicional de la primera es que separa los SMS recibidos en cada número en páginas diferentes.
La tercer página citada en el artículo es Pinger, la cual pintaba bien en su descripción, pero tampoco pude recibir mensajes. La cuarta requiere justamente lo que no quería originalmente, un número de celular. No se por qué el autor colocó ésta en la lista, siendo que no es la idea del artículo. La última citada es para recibir faxes y mensajes de voz, ya alejandose de los SMS, así que no la probé.

Adicionalmente a las del articulo, encontré Receive-SMS, similar a ReceiveSMSOnline en la cual se muestran los mensajes de todos los números en una misma págna.

Estas páginas son de mucha utilidad, pero no siempre servirán, dado que los sites no son tontos (bueno, no todos) y muchos controlan los números de cel que ya validaron códigos y no permiten que sean utilizados nuevamente.

Me pareció interesante listar estas páginas porque, si bien existen cientos de páginas para el envío de mensajes online, no existen muchas para recibirlos.
Encriptar directorios con eCryptfs
Cuando uno transporta información sensible en medios removibles, o bien necesita resguardar los datos contenidos en su máquina, debe recurrir a algún sistema de encripción. Hasta hace un tiempo utilizaba TrueCrypt para realizar esta tarea, el cual es excelente, pero me interesé por probar algo más estándar y libre. Así fue como llegué a eCryptfs, un sistema que permite encriptar fácilmente directorios, que es lo que estaba necesitando. Además eCryptfs es POSIX-compliant, libre y se encuentra integrado en el kernel de Linux desde hace tiempo.

En este post les mostraré los pasos necesarios para instalar y utilizar eCryptfs. Mi configuración inicial se basó en el artículo How To Encrypt Directories/Partitions With eCryptfs On Debian Squeeze.

En debian y derivados existe un paquete de utilidades para utilizar ecryptfs, el cual se instala ejecutando:
  # apt-get install ecryptfs-utils
Otras distribuciones tienen paquetes similares, sólo hay que buscar el equivalente.

Encryptar un directorio es tan simple como montarlo utilizando el tipo ecryptfs:
  # mount -t ecryptfs /data/crypt /data/crypt

Cada vez que se monte el directorio, ecrypfs consultará cuáles parámetros utilizar:
1- Tipo de clave:
  1) passphrase
  2) tspi
  eCryptfs permite utilizar tanto passphrase como TSPI (TCG Service Provider Interface).
2- Algoritmo para cifrar:
  1) aes: blocksize = 16; min keysize = 16; max keysize = 32
  2) blowfish: blocksize = 8; min keysize = 16; max keysize = 56
  3) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24
  4) twofish: blocksize = 16; min keysize = 16; max keysize = 32
  5) cast6: blocksize = 16; min keysize = 16; max keysize = 32
  6) cast5: blocksize = 8; min keysize = 5; max keysize = 16
3- Tamaño en bytes de la clave a utilizar:
  1) 16
  2) 32
  3) 24
4- Decidir si se permitirá utilizar archivos sin encriptar dentro del directorio (plaintext passthrough). En la gran mayoría de los casos se elige que no, a menos que exista alguna razón muy específica para no hacerlo.
5- Decidir si encriptar los nombre de archivos (filename encryption). Si no se desea que se pueda saber ni siquiera el nombre de los archivos contenidos en el directorio, debe seleccionarse sí en esta opción.
6- En el último paso se genera un "Filename Encryption Key (FNEK) Signature", el cual para un uso default (y avanzado también?) no es necesario cambiar.

Cuando se monta el directorio por primera vez, el sistema indicará que no encuentra el signature en la máquina y preguntará si desean almacenarlo. Si no se desea que cada vez que se monte el directorio el sistema pregunte esto, elegir que se almacene el signature.

Una vez montado el directorio, los archivos se acceden de la misma manera que cualquier otro archivo del filesystem. Si se desmonta, los archivos se ven con nombres codificados y no se pueden acceder.


eCryptfs también provee la posibilidad de automontar directorios o particiones editando fstab. Para hacerlo debe colocarse la passphrase en un archivo, el cual se utiliza como parámetro en las opciones de montaje. Algo interesante es que de esta forma se puede copiar el archivo con la clave en un pen drive, con lo cual se podrá acceder a los archivos utilizando el pen-drive. La forma de hacerlo está muy bien explicada en el HowTo de referencia.

Algo a destacar es que este tipo de encripción no protege completamente los datos. Como se observa en la imagen de arriba, si bien los nombres de los archivos no se ven, si se distingue entre directorios y archivos, y los atributos no cambian (fecha de creación, owner, etc). El simple hecho de contar con esta información puede ser suficiente en algunos casos.
Mi resumen de la ekoparty 2012
Después de 2 años deseando ir, por fin se me dio y pude asistir a mi primer ekoparty, la recientemente finalizada ekoparty 2012, y la verdad que volví muy satisfecho. Si bien ya fui sabiendo que las charlas que se realizan en este evento son de muy buen nivel, la verdad es que superaron ampliamente mis expectativas. Los disertantes fueron de lujo y las charlas de muy buen contenido, mostrando vulnerabilidades nuevas, no publicadas en ningún lugar, así que fue un honor poder estar allí para presenciarlo.
No he ido a ninguna otra conferencia de este estilo, así que no tengo punto de comparación, pero por lo que he visto siguiendo otras como Black Hat y Defcon, creo que tenemos localmente un congreso de muy buen nivel.
Fui a todas las presentaciones, y por supuesto que tengo mis favoritas, así como algunas que no me llegaron tanto, ya sea porque yo no tenía el background suficiente para seguirlas, o porque al disertante le costaba transmitir las ideas, pero en general todas fueron muy buenas.
Algo que me sorprendió gratamente es la cantidad de investigación del tema que se realiza en Argentina, mostrando que si se nos da la posibilidad (económica y/o laboral) somos capaces de lograr muy buenos resultados. Los disertantes argentinos estuvieron en un gran nivel.

En fin, para los que no pudieron asistir, les dejo un pequeño resumen de las charlas que más me gustaron, lo cual no quiere decir que el resto fueran malas, sino que yo no pude sacarles tanto el jugo. Igualmente como verán, me gustaron casi todas =P

Cyberwar para todos: Cesar Cerrudo hizo un buen resumen y análisis (con muy buen humor) de lo que conocemos como Cyberwars. La presentación pretendía demistificar un poco las acusaciones continuas sobre quién ataca a quién, tratando de que tomemos conciencia que si bien los países se acusan entre sí sobre los ataques cybernéticos, es casi imposible determinar el origen real de los mismos. Además habló sobre el (nulo?) nivel de seguridad informática que tenemos en Argentina, esperanzado de que en algún momento quienes nos gobiernan tomen conciencia de la necesidad de contar con mecanismos para defendernos ante un eventual cyberataque.

Inception of the SAP Platform's Brain: Attacks to SAP Solution Manager: si bien no manejo mucho SAP, conozco la infraestructura y funcionamiento básico de este sistema, por lo cual esta charla me resultó muy útil. Juan Perez Etchegoyen nos habló de cómo tomar el control de SAP partiendo del componente que nuclea todas las conexiones: SolMan. A través de la presentación demostró cómo partiendo de un mandante sin privilegios y utilizando cuentas default o alguna vulnerabilidad específica, podía conectarse a SolMan mediante conexiones confiables (trusted) y tomar el control del mismo, para luego acceder al ambiente productivo. La joyita de la presentación (a mi gusto) fue utilizar Bizploit (herramienta de Onapsis) para tomar el control de un server *nix donde se encontraba instalado SAP =)

One firmware to monitor 'em all: Andrés Blanco y Matias Eissler hicieron un excelente trabajo de ingeniería inversa para poder inyectar código malicioso en firmware de placas wireless Broadcom, utilizadas por diferentes marcas en sus dispositivos (Apple, Samsung, Nokia, etc). Los muchachos partieron de un pedazo del driver instalado en el sistema de archivos del dispositivo para luego tomar control e instalar su propio código en el firmware de diferentes dispositivos. Debido a que el driver de estas placas es similar en todos los dispositivos, con lograr diseccionar el de uno, les es posible infectar a todos.

HTExploit - Bypassing your htaccess and beyond!: Esta turbo talk fue una de las que más me sorprendió debido a las implicaciones de lo que encontraron tomando como base algo muy simple. Maximiliano Soler y Matias Katz nos trajeron una herramienta (HTExploit) que mostraron en el último BlackHat de Las Vegas, la cual les permite acceder a páginas PHP cuyo acceso está restringido mediante archivos .htaccess. La falla que explota esta herramienta es que muchos archivos htaccess limitan el acceso utilizando la sentencia "Limit GET, POST", lo cual si bien limita el acceso mediante estos métodos, no restringe otros. Dado que PHP asume el método GET siempre que se utilice un método que desconozca, si un atacante utiliza, por ejemplo, el método PEPE, el mismo podrá bypassear el control de Apache y obtener las páginas... un lujo.

Bitcoin, MavePay and the future of cryptocurrencies: esta charla presentada por Sergio Lerner (creo que nada que ver con Alejandro Lerner...) me gustó porque desconocía este sistema de pagos P2P. Como fanático de sistemas P2P, conocer este Bitcoin me interesó mucho como un posible área de investigación. Sergio habló sobre distintos ataques que se pueden realizar para robar "dinero virtual" (Bitcoins) en esta red, además mostró distintas modificaciones sobre las que está trabajando (MavePay) para hacer al sistema más resistente a ataques, desmotivando el robo, favoreciendo el buen uso del sistema para obtener dinero de forma legal.

Fuzzing DTMF Input Processing Algorithms: si hay algo que me encanta son los ataques "locos", y este es uno de ellos. Rahul Sasi demostró cómo realizar ataques contra sistemas de reconocimiento de voz o pulsaciones de teclado, utilizados en telefonía (DTMF). Si bien no demostró como hacerlo, eventualmente podría realizar inyecciones SQL haciendo un simple llamado telefónico, o bien voltear todo un sistema bancario o de atención al cliente... realmente muy loco.

Cryptographic flaws in Oracle Database authentication protocol: en esta presentación, Esteban Fayo demostró vulnerabilidades en los protocolos nativos de autenticación en bases de datos Oracle 10 y 11. Cuando se elige utilizar la autenticación nativa de Oracle, es posible obtener, en dichas versiones de base de datos, el hash de las contraseñas almacenado en el session key enviado por el servidor en el handshake. Para hacerlo, debe contarse con el nombre de una base de datos y un nombre de usuario, que deberá obtenerse mediante otra técnica. Una vez que se obtiene dicho hash, es posible obtener la contraseña mediante un ataque offline, ya sea por diccionario o fuerza bruta. Con esto se reduce el trabajo de obtener una contraseña a romper un hash. La forma de obtener dichos hashes varía dependiendo de si se utiliza la versión 10 o la 11, según demostró Esteban en su presentación.

Satellite baseband mods: Taking control of the InmarSat GMR-2 phone terminal: probablemente la presentación con más humor de toda el congreso, donde Alfredo Ortega y Sebastián Muñiz mostraron los resultados obtenidos al jugar con un teléfono satelital, realizando ingenería inversa sobre el mismo de modo de modificar el firmware y así para poder sniffear e inyectar tráfico enviado entre el teléfono y el satélite. Realmente un trabajo excelente el realizado por este par que lograron el interés de todos a través de una presentación con mucho humor de por medio, algo que siempre ayuda a distender y llegar mejor a la audiencia.

Welcome to your secure /home, $user: un gusto personal el haber podido conocer a uno de los editores del blog Security By Default, Lorenzo Martinez Rodriguez, blog que sigo desde hace tiempo. Lorenzo presentó, también con muchísimo humor de por medio, las modificaciones que realizó sobre los sistemas instalados en su propio hogar para obtener en 2012 la casa del futuro. Mostró cómo es posible tener un hogar más seguro mediante grabación de videos en los momentos adecuados, detección de movimiento, detección facial para reconocer a las personas que ingresan en el hogar (OpenCV haar classifier cascade), detección de presencia mediante bluetooth, interacción con la alarma mediante internet, así como automatizar ciertas tareas llevadas a cabo diariamente. Sin dudas, una de las presentaciones más entretenidas de la jornada.

SinFP3: More Than A Complete Framework for Operating System Fingerprinting: si bien el fingerprinting es algo bastante conocido, me resultó interesante conocer, de la mano de alguien que lleva varios años en el tema, cómo se trabaja para distinguir y lograr la mejor precisión posible detectando sistemas operativos, tanto pasiva como activamente. Patrice Auffret es alguien que trabaja desde hace tiempo con SinFP3, una herramienta que vi en Backtrack en algún momento pero que reconozco nunca utilicé. Esta fue una de esas charlas que te dejan con ganas de contribuir y trabajar un poco en este tipo de detecciones.

4140 ways your alarm system can fail: presentación realizada por Babak Javadi y Keith Howell que nos introdujo al mundo de los sistemas de alarma, esos que utilizamos en nuestros hogaras y en los que deberíamos (?) confiar.  Al introducirme en un mundo que desconocía, realmente me dejaron con un sentimiento de mucha inseguridad (y eso que trabajo en seguridad...) al mostrarnos lo fácil (y cuando digo fácil, es FACIL) que es deshabilitar un sistema de alarmas una vez que se conoce su funcionamiento. Estos muchachos mostraron en vivo como podían desactivar alarmas mediante diferentes técnicas, como realizar fuerza bruta sobre los códigos del centro de mandos, puenteo de terminales, e inyección de tráfico wireless, entre otras cosas. Otra de las tantas buenas presentaciones de este congreso, que dejan mucho información interesante al asistente.

VGA Persistent Rootkit: Nicolás Economou y Diego Juarez nos mostraron el resultado de su trabajo con placas de video que tiene implicancias muy perturbadoras, dado que es poco y nada lo que podremos hacer si un atacante nos infecta. El trabajo realizado fue inyectar código malicioso en el firmware de las placas de video (mediante un upgrade utilizando programas provistos por los fabricantes), de forma que el malware tomará el control de nustra máquina antes de que se cargue cualquier otro sistema... creepy! Nicolás y Diego realizaron ingeniería inversa para agregar código en el bloque de memoria libre de las placas y llamarlo desde el código "legal" del controlador. Además trabajaron para hokearse en la interrupción 10h y lograr que el BIOS no elimine lo inyectado al cargar el sistema operativo. Todo esto fue mostrado en vivo, con algunos mínimos contratiempos ;) y nos dejaron muy sorprendidos. Un aplauso para estos muchachos.

Dirty use of USSD Codes in Cellular Network: otra charla de las que categorizo como "locas" con implicancias TERRIBLES para la telefonía móvil. Ravi Borgaonkar nos introdujo al mundo de los códigos USSD, muy utilizado en Europa y en su India natal, aunque no tannnn conocido en Argentina. Describiría los USSD Codes como similares a los web services, donde mediante un mensaje de texto una persona puede obtener servicios de distintos proveedores. Ravi demostró un exploit que le permite bloquear tarjetas SIM de smartphones Android (todas las versiones), tan solo visitando un link! Como si esto no fuera poco, también demostró como formatear a su estado de fábrica un celular con Android mediante un link, y cómo hacerlo mediante la lectura de un tag NFC! Un lujaso contar con este investigador que nos dejó a todos asombrados con su trabajo. Una de las charlas más aplaudidas de la jornada, algo muy merecido.

The CRIME Attack: la frutilla del postre fue la charla de Juliano Rizzo y Thai Duong quienes una vez más pudieron contra SSL/TLS, logrando obtener cookies en de una conexión encriptada, con un ataque similar al que presentaron el año pasado (BEAST). En esta ocasión, Juliano y Thai explotaron una vulnerabilidad introducida al utilizar compresión en TLS, la cual también está presente al utilizar el protocolo SPDY (reemplazo de HTTP introducido por Google) que también comprime el contenido de las conexiones. El exploit se basa en realizar un session hijack de la víctima para generar tráfico desde la misma contra una página web que utilice TLS (como por ejemplo twitter) y observar el tamaño de los paquetes comprimidos enviados por el servidor. Dado que los paquetes enviados están especialmente armados por el atacante, mediante la observación del tamaño de diferentes request comprimidos, es posible inferir de a un byte el contenido de la cookie encriptada. Los muchachos demostraron en vivo cómo obtener una de las cookies de twitter en pocos minutos, aunque debido a una modificación introducida a último momento por Thai antes de la presentación, no les permitió obtener la otra cookie necesaria para lograr una autenticación exitosa. Igualmente el exploit quedó demostrado al poder obtener una de las cookies y seguramente liberarán el código actualizado para poder llevar a cabo un ataque completo. Un gustaso poder ver a estos dos en acción luego de seguir su trabajo en las últimas dos ekoparty.

Resumiendo, me vine muy MUY contento con lo visto en el congreso y espero poder volver el año que viene. Quién sabe, tal vez alguna día tendré el honor de asistir como speaker =)
Apache kerberizado - Single Sign On (AD y MIT Kerberos)

Una funcionalidad que se está utilizando mucho en las empresas es el Single Sign On (SSO), esto es, permitir que los usuarios se logueen una vez y accedan a todos los sistemas que necesiten, sin tener que ingresar nuevamente sus credenciales. Más allá de las graves implicaciones de seguridad que esto acarrea, es algo que se está utilizando mucho y que los administradores deben conocer.
El SSO no es otra cosa que kerberizar servicios, es decir, autenticar el usuario, obtener un ticket, y luego solicitar servicios con el ticket de sessión. En el caso de los servicios Web, MS integra fácilmente IIS con la autenticación de Active Directory. Apache, por su parte, también brinda esta posibilidad.
En este artículo mostraré los pasos necesarios para kerberizar Apache, es decir, permitir que un usuario acceda a un sitio web sólo si antes se autentica utilizando kerberos. La configuración mostrada es sobre un servidor GNU/Linux, y describe los pasos para kerberizar Apache tanto en una red con AD, como en una de MIT Keberos.
Se asume que el lector tiene ciertos conocimientos básicos de kerberos. Sino pueden leer los artículos que escribí anteriormente sobre el tema:
- Instalación de MIT Kerberos
- Configurar PAM para utilizar kerberos
- Autenticar con kerberos y almacenar información de usuarios con LDAP en GNU/Linux
- OpenLDAP kerberizado

Yendo al grano, los pasos de configuración son los siguientes:

1. Crear un usuario en el dominio que servirá como principal para el servicio HTTP (solicitud de tickets de servicio). El uso es como el de una cuenta de máquina.
  En AD:
    - Abrir Active Directory Users and Computers (ADUC)
    - Ir al dominio donde se creará el usuario.
    - Click derecho en Users
    - Elegir New -> User
    - Completar los datos y finalizar.

  En MIT Kerberos:
      # kadmin.local
      Authenticating as principal root/admin@DVPEM.ORG with password.
      kadmin.local: addprinc -randkey HTTP/apache.dvpem.org@DVPEM.ORG
      WARNING: no policy specified for HTTP/apache.dvpem.org@DVPEM.ORG; defaulting to no policy
      Principal "HTTP/apache.dvpem.org@DVPEM.ORG" created.
      donde -randkey permite generar un password random.

2. Mapear el servicio HTTP con el usuario recién creado y exportar el keytab para ser utilizado en el servidor:
    En AD:
      ktpass -princ HTTP/apache.dvpem.org@DVPEM.ORG -mapuser DVPEM\pruebaapache -ptype KRB5_NT_PRINCIPAL -pass prueba -out C:\apache.keytab
    donde:
      -princ indica el nombre que tendrá el principal (servicio HTTP)
      -mapuser indica el usuario con el que se mapea el servicio
      -ptype especifica el tipo del principal
      -pass asigna un password para el principal. Si utilizan un asterisco (*) el sistema pregunta el password.
      -out especifica el nombre del archivo keytab a generar
    Dependiendo del tipo de encripción soportado por el servidor y el cliente, puede ser necesario especificar el uso de encripción débil. Esto se realiza con:
      -mapop set +desonly
      -crypto all o bien -crypto DES-CBC-MD5

    En MIT Kerberos:
      kadmin.local: ktadd -k /root/apache.keytab HTTP/apache.dvpem.org
      Entry for principal HTTP/apache.dvpem.org with kvno 5, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/root/apache.keytab.
      Entry for principal HTTP/apache.dvpem.org with kvno 5, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/apache.keytab.
      Entry for principal HTTP/apache.dvpem.org with kvno 5, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/apache.keytab.
      Entry for principal HTTP/apache.dvpem.org with kvno 5, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/root/apache.keytab.

3. Copiar el keytab al servidor donde se encuentra Apache instalado. Cambiar el dueño del archivo y restringir los permisos. Si por ejemplo se copia el archivo a /etc/apache2/apache.keytab, ejecutar lo siguiente:
    chown www-data:www-data /etc/apache2/apache.keytab
    cmod 400 /etc/apache2/apache.keytab

4. Instalar en el servidor web las utilidades de kerberos y el módulo de Apache, y habilitar el módulo:
    # apt-get install krb5-{config,user} libapache2-mod-auth-kerb
    # a2enmod mod_auth_kerb

5. Configurar los valores de realm, KDCs, y dominios para kerberos. Esto es, editar las siguientes líneas del archivo /etc/krb5.conf
  - En la sección libdefaults setear el nombre del realm:
      default_realm = DVPEM.ORG
  - En la sección realms, indicar cuáles son los servidores KDC para nuestro realm:
      DVPEM.ORG = {
 kdc = kdc01.dvpem.org:88
 admin_server = kdc01.dvpem.org
 }
  - En la sección domain_realm, agregar los mapeos de dominio con realms:
      .dvpem.org = DVPEM.ORG
      dvpem.org = DVPEM.ORG

6. Testear si kerberos funciona correctamente. Para ello, solicitar un ticket de usuario, para un usuario válido del dominio:
    $ kinit demasiadovivo@DVPEM.ORG
    $ klist

7. Agregar la siguiente configuración a apache para el directorio que se desea autenticar con kerberos. En este ejemplo, la intención es autenticar el directorio /var/www/mipagina
    <Directory /var/www/mipagina>
      AuthType Kerberos
      AuthName "Kerberos Login"
      KrbMethodK5Passwd Off
      KrbMethodNegotiate On
      KrbAuthRealms DVPEM.ORG
      KrbServiceName HTTP
      Krb5KeyTab /etc/apache2/apache.keytab
      require valid-user
    </Directory>
donde:
  AuthType Kerberos: especifica el tipo de autenticación
  KrbMethodNegotiate On: habilita el uso de SPNEGO (GSSAPI-SASL)
  KrbMethodK5Passwd Off: deshabilita el uso de password para la autenticación. Esto puede causar problemas con browsers que no soportan SPNEGO, o máquinas que no se encuentran unidas al dominio. En estos casos puede setearse este valor en On, pero esto permite el uso de autenticación BASIC (muy insegura).
  KrbAuthRealms DVPEM.ORG: especifica el realm (o dominio)
  KrbServiceName HTTP: nombre del servicio
  Krb5KeyTab /etc/apache2/apache.keytab: donde se encuentra el keytab
  require valid-user: fuerza a que el usuario sea validado antes de acceder.

8. Chequear que el ticket provisto por el servidor contiene un tipo de encripción que es consistente con los valores configurado en el keytab:
  Obtener un ticket de servicio y listar los tipos de encripción:
    kvno HTTP/apache.dvpem.org@DVPEM.ORG
    klist -e
  Mostrar los tipos de encripción configurados en el keytab:
    klist -e -k -t /etc/apache2/apache.keytab
Si los valores no coinciden, el servicio no podrá ser utilizado.
NOTA: Hay que tener en cuenta que Windows 7 y 2008 dejaron de aceptar por defecto la encripción con DES, algo que puede causar errores en la autenticación.

9. Reiniciar Apache y probar la configuración accediendo a la página Web protegida con Kerberos.
Algo muy importante es que debe utilizarse el nombre DNS especificado en el keytab como nombre del servicio, dado que si se utiliza la IP o un alias, la autenticación no funcionará.

10. Errores, posibles causas y soluciones. A continuación se listan los errores con los que me topé al configurar el servicio y una explicación sobre cómo lo solucioné. Además incluí soluciones alternativas.
  krb5_get_init_creds_password() failed: Cannot resolve network address for KDC in requested realm
    - Verificar que tanto el registro A como el registro PTR del servidor se encuentren registrados. Si por ejemplo el nombre del servidor apache es apache.dvpem.org, debe ingresarse el registro PTR correspondiende a la IP de dicho servidor.
    - El parámetro KrbAuthRealms de Apache debe estar seteado correctamente. Recordar que en este parámetro se especifica el realm (dominio) en mayúsculas:
KrbAuthRealms DVPEM.ORG
    - Los kdc del dominio se encuentran seteados correctamente en el archivo /etc/krb5.conf. Un ejemplo de esta configuración es:
DVPEM.ORG = {
 kdc = kdc01.dvpem.org:88
 admin_server = kdc01.dvpem.org
 }

  failed to verify krb5 credentials: Server not found in Kerberos database
    - El principal utilizado esta mal configurado en el keytab creado o en el atributo KrbServiceName de la configuración de Apache.
    - Al acceder a la página debe utilizarse el nombre del servidor registrado en el keytab. Es decir, si el principal está designado para apache.dvpem.org, en el navegador debe utilziarse la dirección apache.dvpem.org.
   
  failed to verify krb5 credentials: KDC has no support for encryption type
    - El tipo de encripción aceptada por el servidor no es compatible con la encripción aceptada por el cliente, o bien los tipos de encripción configurados en el keytab no son compatibles con el servidor. Verificar obteniendo un ticket de servicio y la encripción soportada en el keytab:
      kvno HTTP/apache.dvpem.org@DVPEM.ORG
      klist -e
      klist -e -k -t /etc/apache2/apache.keytab
      Hay que tener en cuenta que Windows 7 y 2008 dejaron de aceptar por defecto la encripción con DES, algo que puede causar el error mencionado si se utilizan estos sistemas.
   
  gss_acquire_cred() failed: Unspecified GSS failure.  Minor code may provide more information (, )
    - Revisar si no se encuentra seteado el valor "Use Kerberos DES encryption for this account" en la cuenta del usuario utilizada para el pricipal.

 
Referencias

- Kerberos Module for Apache - Configuration
- Configure Apache to use Kerberos authentication
- Kerberos authentication with Apache in a multi-domain Active Directory
- Single Sign On with Kerberos using Debian and Windows Server 2008 R2
- Kerberos-Based SSO with Apache
- Using mod_auth_kerb and Windows 2000/2003/2008R2 as KDC
- Apache on Linux and Single-Sign-On with Active Directory
- Active Directory and Apache Kerberos authentication
- JBoss Doc - Chapter 5. Configuring Microsoft Active Directory
- Ktpass
Auditar grupos críticos y alertar por mail en Active Directory
Es muy importante para todo administrador de seguridad conocer en todo momento quienes tienen cuentas de usuario con privilegios elevados y "vigilarlos". A partir de esto se desprende que es todavía más importante saber cuando se otorgan privilegios a usuarios.
En todo dominio existen grupos de usuario utilizados por administradores o helpdesk que cuentan con mayores privilegios que los usuarios comunes, por obvias razones. El problema es cuando se asignan estos privilegios y no todos (o ninguno) los administradores están informados. El caso más riesgoso es cuando un atacante logra escalar privilegios gracias a algún exploit o vulnerabilidad conocida (se acuerdan de pass-the-hash?).
Active Directory posee grupos bien definidos con privilegios elevados, siendo "Domain Admins" el Dios supremo. Cada organización puede definir sus propios grupos, pero "Domain Admins" estará siempre presente como la autoridad máxima, así que debe estar auditado. Otros grupos de importancia son "Enterprise Admins", "Schema Admins" y "Backup Operators".
Este artículo brinda los pasos necesarios para auditar grupos en Active Directory y enviar mensajes de alerta por mail cuando un grupo crítico esté siendo modificado. De esta forma los responsables de Seguridad de la Información estarán notificados al instante cuando ocurra una brecha de seguridad donde un usuario escale privilegios en el dominio. Lo que se auditará serán inserciones y eliminaciones de usuarios en los grupos que corresponda.


Habilitar auditoría de grupos en AD

La auditoría de usuarios/grupos/workstations en AD se realiza de la misma manera que la auditoría de directorios. Para hacerlo hay que utilizar la herramienta "Active Directory Users and Computers" (ADUC). En esta debe dirigirse a View y tildar "Advanced Features" para poder ver las propiedades avanzadas de los objetos.
Con la opción habilitada, resta dirigirse a la unidad organizativa (OU) donde se encuentran los grupos a auditar. Tal vez deseen habilitar la auditoría para todos los usuarios, o para usuarios/grupos particulares. Para esta explicación habilitaremos la auditoría a todos los objetos de la OU Users. Entonces, dirigirse a la OU Users y abrir las propiedades, allí dirigirse a la pestaña Security y en esta dar al botón Advanced. En esta ventana dirigirse a la pestaña Auditing, dar al botón "Add...", escribir Everyone y dar Ok. En la lista de propiedades a auditar, tildar todo menos "Full control", "List contents", "Read all properties" y "Read Permissions" (las lecturas generan demasiados logs y no son de demasiada utilidad)

Lo que se hace con esta configuración es que cada vez que cualquier usuario (por eso se elige Everyone) modifique un objeto de la OU Users se genere una entrada en el log de Windows.

Probablemente se encuentren con que esta auditoría ya se encuentra habilitada y heredada de la configuración del dominio, pero si no es así, con los pasos anteriores podrán configurarla.


Hook al evento y envío de mail

Cuando el evento que deseamos auditar se dispare deberemos realizar alguna acción. Como comenté al principio, nuestra acción será enviar un mail a los encargados de la seguridad, y en el mismo colocaremos el contenido de la entrada de log que generó el evento.
Si bien es muy simple generar una tarea que envíe un mail avisando del evento, la información que puede contener el mismo es muy escueta y no sirve de mucho más que estar informado. Lo mejor es contar con un script que lea la entrada del log y envíe el mail con el contenido de la misma.


Script en PowerShell

En la mayoría de los blogs explican cómo utilizar la herramienta wevtutil para enviar la información de los logs en el mail cuando se ejecuta el evento. Wevtutil permite parsear los logs y obtener información, para lo cual es muy útil, pero para este caso, no lo es tanto. El problema es que estas soluciones se basan en crear un script que lee la última entrada del log que cumple con las condiciones del evento buscado, y de esta forma puede ocurrir que si dos o más eventos con las mismas características se generan en corto intervalo de tiempo, perdamos información.

La mejor solución que encontré es la explicada en el artículo Trigger a PowerShell Script from a Windows Event, a partir de la cual generé el siguiente script (luego de pelear un buen rato con PS), denominado eventreporter.ps1:

  # Script by demasiadovivo
  param($eventRecordID,$eventChannel)

  $event = Get-WinEvent -Logname $eventChannel -FilterXPath "<QueryList><Query Id='0' Path='$eventChannel'><Select Path='$eventChannel'>*[System[(EventRecordID=$eventRecordID)]]</Select></Query></QueryList>"

  $smtp_server = "mailserver.ejemplo.com"
  $msg = New-Object Net.Mail.MailMessage
  $msg.From = "security_alert@ejemplo.com"
  $msg.To.Add("demasiadovivo@ejemplo.com")
  $msg.subject = "ALERTA! se hicieron cambios en grupo crítico"

  $data =$event.Message
  $data = [String]::join([environment]::NewLine, $data)
  $msg.body = $data

  $smtp = new-object Net.Mail.SmtpClient($smtp_server)
  $smtp.Send($msg)

Vayamos por partes para comprender su funcionamiento. El script primero obtiene los parámetros eventRecordID y eventChannel, donde eventRecordID es el valor que identifica la línea del log donde se encuentra el evento que disparó la acción, y eventChannel es el log donde se encuentra (System, Security, Application, etc). No confundir eventRecordID con eventID. El primero es el identificador de la entrada del evento, algo así como el número de línea dentro del log, mientras que eventID es el identificador que utiliza Windows para distinguir el tipo de evento (por ejemplo Logon). Estos valores los envía la tarea programada que se dispara con el evento, como veremos después.
El siguiente paso es obtener la entrada del log correspondiente al evento. Para ello se utiliza el comando Get-WinEvent y los valores de eventRecordID y eventChannel. El evento se obtiene con la consulta "<QueryList><Query Id='0' Path='$eventChannel'><Select Path='$eventChannel'>*[System[(EventRecordID=$eventRecordID)]]</Select></Query></QueryList>" que se encuentra en formato XML y utiliza el lenguaje XPath (http://en.wikipedia.org/wiki/XPath). Se utiliza XPath en las consultas porque internamente los logs se guardan en formato XML. Para entender un poco mejor cómo se arman consultas en este lenguaje, leer MSDN XPath Syntax.
Finalmente el script arma un mail con el contenido obtenido del log ($event.Message) y lo envía a las direcciones designadas. Una línea que puede llamar la atención es "[String]::join([environment]::NewLine, $data)". Me llevó más de 3 horas encontrar cómo hacer que el mensaje del log original conserve los enters, lo cual se logra a través de esa línea... en bash todo esto sería mucho más fácil...

Recuerden que para poder ejecutar scripts de PowerShell, primero deben cambiar la política de ejecución de la máquina. Esto se realiza ejecutando lo siguiente:
  Set-ExecutionPolicy RemoteSigned


Asignar una tarea al evento

Bien, ya activamos la auditoría de los grupos y tenemos el script a ejecutar cuando el evento ocurra. El siguiente paso es asignar la ejecución del script con el evento. Esto se hace a través de la herramienta "Computer Management". Hay que tener en cuenta en este punto que la tarea deberá agregarse en todos los controladores de dominio (DC), dado que las modificaciones de grupos podrían realizarse en cualquiera de ellos.

Como todo en el mundo MS, nada es tan directo y uno termina teniendo que utilizar algunas artimañas para lograr lo que desea. Para poder entregar al script los argumentos eventRecordID y eventChannel hay que hacer algunas modificaciones manuales a una tarea, como veremos a continuación.

Primero hay que crear la tarea que se ejecutará al producirse el evento. Para ello, dirigirse a "Task Scheduler -> Task Scheduler Library" dentro de "Computer Management". Allí dando click derecho se elige "Create Task..." y se obtiene la ventana de configuración de la tarea. A la misma habrá que asignar un nombre y opcionalmente una descripción. Como queremos que se ejecute en modo batch, hay que cambiar el usuario con el que se ejecutará la tarea, así que clickear el botón "Change User or Group..." y escribir "SYSTEM" (o bien crear un usuario con los privilegios suficientes para leer logs).
En la pestaña "Triggers" se agrega la condición que debe darse para que se ejecute el script. En ella debe crearse un nuevo Trigger con "New..." y elegir la opción "On an event" como disparador de la tarea. Luego elegir "Custom" en las settings y dar a "Edit Event Filter...". En esta ventana ir a la pestaña "XML", seleccionar "Edit query manually" y utilizar el siguiente código:
  <QueryList>
    <Query Id="0" Path="Security">
      <Select Path="Security">*[(System/EventID=4732) or (System/EventID=4733)] and *[EventData/Data [@Name='TargetUserName']='Backup Operators'] or *[(System/EventID=4728) or (System/EventID=4729)] and *[(EventData/Data[@Name='TargetUserName']='Domain Admins') or (EventData/Data[@Name='TargetUserName']='Schema Admins') or (EventData/Data[@Name='TargetUserName']='Enterprise Admins')]</Select>
    </Query>
  </QueryList>
Como se puede observar, la consulta es similar a la utilizada en el script, en formato XML y utilizando el lenguaje XPath para seleccionar los siguientes eventos:
- 4732/4733 se agregó/eliminó un usuario a un grupo local. Se utilizan en conjunto con el grupo "Backup Operators" que es local.
- 4728, 4729 se agregó/eliminó un usuario a un grupo global. Se utilizan en conjunto con los grupos "Domain Admins", "Schema Admins" y "Enterprise Admins" que son globales.
  NOTA 1: si en un futuro desean auditar algún grupo universal, los identificadores de eventos son 4756 para cuando se agrega, y 4757 para cuando se elimina un usuario del grupo.
  NOTA 2: para entender mejor la consulta, pueden observar la estructura XML de los eventos en MSDN Event Schema Elements.
Continuando en la pestaña "Actions", elegir "New" para agregar la ejecución del script. Dentro de la ventana emergente elegir la acción "Start a program", en el nombre del programa/script escribir "PowerShell.exe", y en la sección de argumentos escribir ".\eventreporter.ps1 -eventRecordID $(eventRecordID) -eventChannel $(eventChannel)", reemplazando el path del script por el que corresponda. Con esto ya termina la definición de la tarea y pueden dar OK para terminar.
Como se ve, se utilizan los parámetros eventRecordID y eventChannel en la llamada del script, los cuales se utilizan luego para obtener el identificador de la entrada. Acá es donde entra en juego la "magia" del administrador. Para variar, nada es coherente con las herramientas de MS y no es posible indicar, de forma directa, cómo asignar los valores a los parámetros... gracias MS!!! Por ello es necesario aplicar el siguiente artilugio.
Primero deben dar click derecho sobre la tarea recién creada, elegir la opción "Export" y guardar el XML en alguna ubicación. Supongamos que llamamos a este XML como el nombre de la tarea, "Eventos_criticos.xml". Una vez hecho esto, eliminen la tarea. Sí eliminen, ya la volveremos a crear a partir del XML.
Ahora abrir el XML recién generado con algún editor de texto y buscar la sección "<Triggers>". Dentro de la misma encontrarán la sección "<EventTrigger>". En ella colocar el siguiente código:
      <ValueQueries>
        <Value name="eventChannel">Event/System/Channel</Value>
        <Value name="eventRecordID">Event/System/EventRecordID</Value>
        <Value name="eventSeverity">Event/System/Level</Value>
      </ValueQueries>
es decir, la sección completa debe quedar:
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription><QueryList><Query Id="0" Path="Security"><Select Path="Security">*[(System/EventID=4732) or (System/EventID=4733)] and *[EventData/Data [@Name='TargetUserName']='Backup Operators'] or *[(System/EventID=4728) or (System/EventID=4729)] and *[(EventData/Data[@Name='TargetUserName']='Domain Admins') or (EventData/Data[@Name='TargetUserName']='Schema Admins') or (EventData/Data[@Name='TargetUserName']='Enterprise Admins')]</Select></Query></QueryList></Subscription>
      <ValueQueries>
        <Value name="eventChannel">Event/System/Channel</Value>
        <Value name="eventRecordID">Event/System/EventRecordID</Value>
        <Value name="eventSeverity">Event/System/Level</Value>
      </ValueQueries>
    </EventTrigger>
  </Triggers>
Salvar los cambios en el XML.
Finalmente volvemos a crear la tarea a partir del XML modificado. Para ello ir a Task Scheduler, dar click derecho y elegir la opción "Import Task", la cual les permitirá buscar el archivo recién creado. Otra forma de hacer esto último es ejecutando desde consola el siguiente comando:
  C:\>schtasks /create /TN "Event Viewer Tasks\Eventos_Criticos" /XML Eventos_criticos.xml

Lo que se hizo aquí es indicarle a la tarea cuáles son los valores que debe utilizar para los parámetros eventChannel (Event/System/Channel), eventRecordID (Event/System/EventRecordID) y eventSeverity (Event/System/Level), que luego entregará al script creado en la sección anterior. No hay forma de hacer esto modificando la tarea desde el GUI, esta es la única manera... lindo verdad?...

En los otros controladores de dominio solamente deberán importar el XML recién creado y copiar el script a una ubicación donde el DC pueda ejecutar.


Acerca de...

Como comentario final solo me resta renegar una vez más contra MS. Algo tan simple como auditar un log, que en algún *nix sería cosa de dos minutos, se convierte en un dolor de cabeza. Siguiendo los pasos que describo en este artículo podrán hacerlo en dos minutos, pero encontrar la información necesaria para poder armar esto me llevó casi dos tardes. Windows es fácil de usar para el usuario final, pero cuando se quiere hacer algo semi-avanzado de administración te hace la vida imposible.
Dirán, me quejo pero lo uso. Y si, no me queda otra, desgraciadamente la gran mayoría de las organizaciones con una infraestructura IT mediana utilizan Active Directory, y para ser administrador de seguridad, necesitas conocer esta tecnología y hacer cosas como la que describí en este artículo. Lo único que espero es que en algún momento se tome conciencia y se deje de utilizar esta bosta para pasar a algo mejor.


Referencias

- Trigger a PowerShell Script from a Windows Event
- AD DS Auditing Step-by-Step Guide
- Getting event log contents by email on an event log trigger
- Email with event log attachment on an event log trigger
- MSDN XPath Syntax
- Event Schema Elements
- Attaching Tasks to Event Viewer Logs and Events
- PowerShell Cookbook - Chapter 23. Event Logs
- PowerShell Cookbook - Appendix C. XPath Quick Reference
Instalación y configuración básica de ModSecurity
Desde hace tiempo tengo ganas de instalar un Web Application Firewall (WAF) y siempre tuve ModSecurity en la mira. Hoy con un poco de tiempo, decidí darle una chance y jugar un rato.
ModSecurity es un módulo para Apache que permite analizar los pedidos en distintas fases del protocolo HTTP. De esta forma, es posible procesar los pedidos antes de ser entregados a la aplicación subyacente (por ejemplo, escrita en PHP), o luego de que se completó la ejecución. Con este sistema es posible prevenir ataques de SQL Injection, XSS, LDAP Injection, File Injection, Session Fixation, etc.
Como es un módulo para Apache, es muy fácil de instalar, aunque requiere algunos pasos para su configuración. En este artículo explicaré cómo instalar, configurar y poner en funcionamiento ModSecurity. La explicación culmina con una configuración básica de ModSecurity trabajando en modo monitoreo, es decir, sólo loggea los eventos, no actúa de forma activa. Por supuesto que la verdadera utilidad de un WAF es la prevención de los ataques, pero para evitar falsos positivos que afecten la funcionalidad de los sites que se encuentren activos, es preferible comenzar en un modo pasivo e ir habilitando reglas a medida que se va conociendo el tráfico.

Instalar ModSecurity en debian, una vez que ya está instalado Apache, es tan simple como ejecutar:
  apt-get install libapache2-modsecurity modsecurity-crs

El paquete modsecurity-crs contiene el conjunto de reglas core creado por OWASP. ModSecurity es simplemente el motor del firewall y todo firewall necesita reglas para funcionar. Las reglas creadas por OWASP abarcan todos los ataques más comunes de la web y por supuesto que son gratuitas de utilizar.

Una vez instalado el módulo, debe activarse ejecutando:
  a2enmod mod-security

En el paquete de debian encontré un error al intentar cargar el módulo, dado que las librerías estaban mal referenciadas en el archivo .load. Para arreglar el problema, debe modificarse la línea Load del archivo /etc/apache2/mods-enabled/modsecurity.load para que quede
  LoadFile /usr/lib/libxml2.so.2
en lugar de "LoadFile libxml2.so.2".

Para probar que el módulo está instalado correctamente, renombrar el archivo de configuración default:
  mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
reiniciar Apache:
  /etc/init.d/apache2 restart
y ejecutar nikto:
  nikto -host http://localhost
Puede utilizarse cualquier otra herramienta que genere tráfico malicioso, nikto es solamente un ejemplo.

Con esto ya debería existir el archivo de auditoría /var/log/apache2/modsec_audit.log, donde deberían estar las entradas generadas por nikto.

Como explicaba al principio, por si solo ModSecurity no hace nada, necesita ser alimentado con reglas, para ello el paquete modsecurity-crs. Si ya está instalado, las reglas se encontrarán en /usr/share/modsecurity-crs/. Este directorio está dividido en 5 subdirectorios:
  activated_rules
  base_rules
  experimental_rules
  optional_rules
  slr_rules
Los nombres explican por si mismos el contenido. La idea es colocar en activated_rules links simbólicos a las reglas que deseemos activar, como por ejemplo "/usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf". Todo dependerá de qué deseen hacer, es una cuestión organizativa.
Para una configuración básica, simplemente incluiremos todo el directorio base_rules, en lugar de incluir activated_rules y agregar de a una las reglas. También debe incluirse el archivo de configuración modsecurity_crs_10_config.conf, que cuenta con seteos básicos. Esto se realiza editando el archivo "/etc/apache2/mods-enabled/mod-security.conf" y agregando las siguientes líneas:
  Include "/usr/share/modsecurity-crs/modsecurity_crs_10_config.conf"
  Include "/usr/share/modsecurity-crs/base_rules/*.conf"
es decir, el archivo debería quedar como a continuación:
<ifmodule security2_module="">
        SecDataDir /var/cache/modsecurity
        Include "/etc/modsecurity/*.conf"
        Include "/usr/share/modsecurity-crs/modsecurity_crs_10_config.conf"
        Include "/usr/share/modsecurity-crs/base_rules/*.conf"
</ifmodule>

Cada vez que realicen un cambio en la configuración deberán cargar nuevamente Apache. Claro que no es necesario reiniciarlo, también es posible hacer un reload más sutil y no matar las conexiones existentes:
  /etc/init.d/apache2 graceful

Un error bastante común al ejecutar las reglas de OWASP es el exceso en el límite de la librería PCRE que viene por defecto en el archivo modsecurity.conf. El error contiene el siguiente mensaje:
  Execution error - PCRE limits exceeded
Estos límites se configuran mediante las directivas SecPcreMatchLimit y SecPcreMatchLimitRecursion (modsecurity - Configuration Directives) y previenen que expresiones regulares mal formadas se salgan de control. Aumenten con cuidado este valor, tratando de que las reglas se ejecuten, pero sin asignar un número exorbitante. Por ejemplo, un valor que a mi me funcionó bien es 5000:
  SecPcreMatchLimit 5000
  SecPcreMatchLimitRecursion 5000

Con esto ya cuentan con ModSecurity habilitado y funcionando en modo "sniffer", dado que sólo revisa el contenido y loggea los ataques. A partir de aquí deberán analizarse dichos logs y decidir qué tipo de prevención aplicar. Hay que tener cuidado con los falsos positivos, dado que pueden influir en el correcto funcionamiento de los sites que intentamos proteger.

Una idea interesante es utilizar ModSecurity en conjunto con el módulo mod_proxy, es decir, utilizar Apache como un reverse Proxy y proteger con una sola instancia de ModSecurity varios web servers que se encuentren detrás.


Referencias

- ModSecurity Reference Manual
- Category: OWASP ModSecurity Core Rule Set Project
- mod_security on Apache
Gnome 3: volver a lo clásico
Hace algunos meses, debian testing, como muchas distribuciones, decidió actualizar sus paquetes para dar comienzo a la era Gnome 3. Yo siempre tuve más feeling con KDE que con Gnome, pero debido a lo "pesado" que se volvió KDE 4 en mi máquina, decidí darle una chance más a Gnome 2, y realmente me resultaba cómodo. El problema fue cuando actualicé a Gnome 3... resumiendo, mi sensación fue "oh, come on!!!".
Gnome 3, que utiliza la interfaz Gnome Shell, no sólo me resultó incómodo, sino que además extremadamente pesado. Intenté tunearlo de varias maneras, hasta incluso llegué a adaptarme un poco, pero después de un tiempo seguía teniendo esa sensación de "me molesta usar esto". Luego de darle una oportunidad a Enlightenment (esa historia la dejo para otro día), hoy volví a intentarlo con Gnome 3, pero con su versión classic.

Para los que no lo sepan, Gnome 3 viene con la premisa "la nueva versión te parece una patada en los huevos? no nos abandones, tenemos una versión más liviana y similar a Gnome 2", la cual denominan Classic (o Fall-Back Mode). Gnome Classic posee un entorno muy similar a Gnome 2, con barra de tareas, menú de inicio, botones para maximizar, y, tal vez lo más importante, una interfaz más liviana.

Para iniciar Gnome en su versión Classic, deberán elegir "Gnome Classic" en el apartado session del display manager que estén utilizando (GDM, KDM, XDM, etc). Esta opción aparece como si eligieran entre usar Gnome o KDE.
Una vez dentro de Gnome encontrarán el panel con el menu inicio clásico de Gnome 2 (Aplicaciones y Lugares), fecha y hora, y la tray. Abajo cuentan con una barra de tareas, algo muy extrañable en Gnome Shell. A partir de aquí hay que hacer un par de cambios para acercarse un poco más la versión 2.
Como paso inicial, recomiendo instalar la herramienta gnome-tweak-tool. Esta es una suerte de herramienta de configuración avanzada, la cual les permitirá configurar varios aspectos de Gnome 3, no configurables desde la herramienta de configuración básica. Con esta herramienta podrán permitir que el administrador de archivos administre el escritorio, lo cual se traduce a que vuelvan a aparecer los archivos e íconos que tuviesen en el escritorio, algo que en Gnome 3 no existe por defecto. Para lograrlo deberán dirigirse al apartado File Manager y poner en 1 la opción "Have file manager handle the desktop"


Con esta herramienta también podrán configurar varias opciones de visualización, como el estilo de las ventanas, el theme a utilizar, los íconos, las fuentes, etc.
Otras herramientas que ayudan mucho en la configuración son dconf-editor y gconf-editor. Gnome desde hace tiempo trae una especie de "registry" a lo Windows, la cual se puede acceder con estas herramientas. La versión 2 utilizaba gconf-editor, mientras que Gnome 3 usa dconf... el problema es que no acceden a los mismos valores, sino que poseen configuraciones separadas. Los programas nuevos ya vienen preparados para utilizar dconf, pero algunas configuraciones antiguas guardan sus datos con gconf. Utilizando estas herramientas es conveniente configurar la forma en que se hace foco en una ventana, y desactivar las alertas de poco espacio en disco.
A algunos puede molestarles tener que hacer click en la ventana para que obtenga el foco. Esto se puede cambiar en la opción apps -> metacity -> general -> focus_mode, utilizando gconf-editor. Las opciones son click (clickear para obtener foco), sloppy (la ventana obtiene el foco cuando pasamos el mouse encima) y mouse (la ventana obtiene foco cuando el mouse pasa encima y lo pierde cuando el mouse se va).
Aparentemente existe un bug en las alertas de disco lleno. Me sucedió que aún indicando al sistema que no vuelva a alertarme acerca de los discos llenos, lo seguía haciendo! Es posible desactivar completamente esta funcionalidad modificando el valor de org -> gnome -> settings-daemon -> plugins -> housekeeping -> active, utilizando dconf-editor.

Otra cosa muy útil es saber cómo agregar íconos de acceso rápido al panel. En todo panel un click derecho significa poder ver un listado con acceso a las propiedades, agregar, mover y quitar íconos... pero no en Gnome 3. No se quién habrá tenido la brillante idea de tener que pulstar el botón Alt antes de hacer click derecho para poder ver estas opciones. Con "Alt + Click derecho" podrán acceder todo lo mencionado y agregar paneles. Si quieren añadir un shortcut al panel, ejecutan Alt + Click derecho y luego eligen "Añadir al panel"... el resto es igual que antes.


Un tip adicional es cómo apagar/cerrar sesión ya que no existe un botón para tal fin en el menú ni en el panel. Todas estas acciones se encuentran al pulsar (botón izquierdo del mouse) el nombre del usuario, que se encuentra a la derecha del panel.


Otro faltante que encontré en las opciones de configuración es la edición de qué aplicaciones ejecutar al inicio. A pesar de que recorrí varias opciones en los paneles de configuración, no pude dar en la tecla, por lo que recurrí al comando gnome-session-properties.

Con esto, básicamente cubrí lo que necesitaba para asemejar el entorno a lo que venía utilizando en Gnome 2. Encontrar todo esto me llevó un buen rato de pruebas y búsquedas, así que espero les resulte útil =)


Algunos links que me ayudaron

- Add/Remove shortcut icon to the GNOME panel in Ubuntu Linux [video]
- How to customize the gnome classic panel
- Gnome 3 - This is the end, it seems
- Startup Applications in Gnome 3 [Fedora Forum]
- Gnome gconf docs: chapter 3 - Metacity
- Gnome 3 focus follows mouse
OpenLDAP kerberizado
Hasta ahora se mostró como utilizar OpenLDAP con autenticación anónima, es decir, sin autenticación (ver Instalar y configurar el directorio OpenLDAP  y Autenticar con kerberos y almacenar información de usuarios con LDAP en GNU/Linux). Si bien este modelo puede servir en algunos casos donde el servicio de directorio es público, en general se desea que la información sea accesible sólo para ciertos usuarios. De las autenticaciones soportadas en LDAP, la más segura es SASL-GSSAPI con kerberos y sobre conexión encriptada.
En este artículo veremos cómo utilizar GSSAPI, y cómo definir los accesos al directorio en base a los usuarios autenticados con kerberos para obtener una estructura de usuarios centralizada con autenticación segura, similar a Active Directory.
Con esto cierro la serie de artículos Autenticación y administración centralizada de usuarios en GNU/Linux, la cual comencé a publicar en julio del año pasado y contempla todos los pasos necesarios para armar dicha estructura. En el artículo principal pueden encontrar los links a todos los artículos de la serie.


Autenticar con SASL-GSSAPI kerberos

Para poder utilizar SASL-GSSAPI en LDAP, es necesario instalar el API Cyrus SASL compilado para el kerberos de MIT, tanto en el servidor como en clientes:
# apt-get install libsasl2-modules-gssapi-mit

Como vimos en la descripción de kerberos, cada servicio que desee kerberizarse deberá tener un principal en la base de datos. Entonces, para poder utilizar GSSAPI con kerberos necesitamos crear el principal correspondiente. Esto se logra utilizando kadmin o kadmin.local de la siguiente manera:
# kadmin.local
Authenticating as principal root/admin@DEMASIADOVIVO.ORG with password.
kadmin.local: addprinc -randkey ldap/ldap01.demasiadovivo.org@DEMASIADOVIVO.ORG
WARNING: no policy specified for ldap/ldap01.demasiadovivo.org@DEMASIADOVIVO.ORG; defaulting to no policy
Principal "ldap/ldap01.demasiadovivo.org@DEMASIADOVIVO.ORG" created.
donde ldap01.demasiadovivo.org es la dirección del servidor ldap y -randkey permite generar un password random.
El siguiente paso es guardar la clave del principal recién creado en un archivo (keytab), el cual luego se utilizará desde OpeLDAP para la autenticación:
kadmin.local: ktadd -k /root/ldap.keytab ldap/ldap01.demasiadovivo.org
Entry for principal ldap/ldap01.demasiadovivo.org with kvno 5, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/root/ldap.keytab.
Entry for principal ldap/ldap01.demasiadovivo.org with kvno 5, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/ldap.keytab.
Entry for principal ldap/ldap01.demasiadovivo.org with kvno 5, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/ldap.keytab.
Entry for principal ldap/ldap01.demasiadovivo.org with kvno 5, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/root/ldap.keytab.
Si no especifican el nombre del archivo (-k), la clave se escribe en /etc/krb5.keytab. Esto no es aconsejable porque este archivo será utilizado por OpenLDAP, para lo cual debemos darle permiso de lectura/escritura, y al hacerlo, le damos acceso a todas las claves que se encuentren en el. Por ello, es mejor separar la clave de OpenLDAP en un archivo propio.

Una vez creado el principal y exportado a un archivo, hay que copiar el mismo al servidor donde se encuentre OpenLDAP y darle permiso de lectura/escritura al usuario openldap, que es el usuario con el que se ejecuta el servicio. Un buen lugar para ubicar el archivo es dentro del mismo directorio de ldap.
/etc/ldap# chown openldap:openldap ldap.keytab
/etc/ldap# chmod 750 ldap.keytab
A continuación hay que editar el archivo /etc/default/slapd para indicar donde se encuentra el keytab para utilizar con SASL, ya que por default intentará usar /etc/krb5.keytab. Esto se hace editando o agregando la siguiente línea:
export KRB5_KTNAME=/etc/ldap/ldap.keytab

OpenLDAP mapea los principals de kerberos a DNs especiales, que tienen el siguiente formato:
uid=<nombre de="" usuario="">,cn=<realm>,cn=<mecanismo>,cn=auth
<nombre de="" usuario=""><realm><mecanismo>
<nombre de="" usuario=""><realm><mecanismo>
o
<nombre de="" usuario=""><realm><mecanismo> uid=<nombre de="" usuario="">,cn=<mecanismo>,cn=auth
<nombre de="" usuario=""><realm><mecanismo><nombre de="" usuario=""><mecanismo>
Por ejemplo, si el principal es demasiadovivo@DEMASIADOVIVO.ORG, éste se mapeará con el DN:
uid=demasiadovivo,cn=DEMASIADOVIVO.ORG,cn=gssapi,cn=auth
es decir, para poder utilizar autenticación kerberos en LDAP, debe existir una entrada en el directorio con el formato mostrado.

Si están utilizando LDAP como directorio de usuarios, el formato de los DN para estos usuarios (uid=demasiadovivo,ou=People,dc=demasiadovivo,dc=org) es muy diferente al recién mostrado (uid=demasiadovivo,cn=DEMASIADOVIVO.ORG,cn=gssapi,cn=auth). Esta diferencia se debe a que una entrada es para usuarios de LDAP y el otro es para usuarios almacenados en LDAP. Una entrada es para autenticar quién es el usuario y qué puede hacer en el directorio, y la otra es para almacenar datos de un usuario.
En el caso de utilizar autenticación kerberos y tomar los datos del usuario de LDAP con NSS, ambos usuarios son el mismo usuario, entonces se necesita una forma de mapearlos.
Para esto, OpenLDAP provee reemplazo de nombres de autenticación utilizando expresiones regulares. Esto es, en lugar de tener que definir dos entradas para el mismo usuario, es posible definir la entrada con los datos del usuario y mapear el DN de autenticación al DN real. La forma de hacerlo es ingresando una regla authz-regexp en el archivo slapd.conf (/usr/share/slapd/slapd.conf en debian). La directiva utiliza dos parámetros:
authz-regexp <patron buscado=""> <patron de="" reemplazo="">
Entonces, ingresando la siguiente regla, se tiene el reemplazo buscado:
authz-regexp
    uid=([^,]*),cn=DEMASIADOVIVO.ORG,cn=gssapi,cn=auth
    uid=$1,cn=People,dc=demasiadovivo,dc=org
Finalmente hay que reiniciar el servicio slapd para que tome los cambios:
# /etc/init/slapd restart
Para probar que la autenticación funciona, adquirimos un token y ejecutamos un ldapwhoami:
$ kinit demasiadovivo
Password for demasiadovivo@DEMASIADOVIVO.ORG:
$ ldapwhoami
SASL/GSSAPI authentication started
SASL username: demasiadovivo@DEMASIADOVIVO.ORG:
SASL SSF: 56
SASL data security layer installed.
dn:uid=demasiadovivo,cn=gssapi,cn=auth
CUIDADO: Asegúrense de que el servidor LDAP tiene resolución DNS inversa (registro PTR), caso contrario pueden encontrarse con un error como el siguiente:
Cannot determine realm for numeric host address
Para ver los mecanismos de autenticación habilitados, se puede ejecutar:
$ ldapsearch -s base -b "" supportedSASLMechanisms

Configurar permisos para acceder LDAP

Hasta ahora la configuración cuenta con autenticación GSSAPI-kerberos que es mucho mejor a tener autenticación simple, o no tener autenticación, pero todavía no se definió ningún rol de usuario que determine qué usuario puede hacer qué.
Por default OpenLDAP cuenta con el usuario admin que posee control total sobre el directorio, y se autentica utilizando autenticación simple con password. Además cuenta con un perfil público a través del cual cualquier persona, utilizando autenticación simple, puede leer los datos del directorio. Como se mostró en el artículo de instalación y configuración de LDAP, estos permisos se pueden observar ejecutando:

# slapcat -b cn=config -a olcDatabase={1}hdb
Como la autenticación la realizaremos a través de kerberos, una configuración interesante es permitir acceso de lectura de atributos no confidenciales a todo usuario autenticado mediante kerberos (en lugar de acceso anónimo), y acceso total a un grupo administrador, cuyos miembros sean usuarios autorizados y autenticados con kerberos.
Para lograr esta configuración, los pasos a realizar son los siguientes:

1. Eliminar al usuario admin y accesos default.
2. Crear un grupo administrador de dominio.
3. Otorgar control total al grupo del paso anterior (como suele ser el grupo Domain Admins en Active Directory).
4. Asignar acceso de lectura a usuarios autenticados.


1. Eliminar usuario admin y accesos default

Por defecto, OpenLDAP provee acceso de escritura para el usuario admin y de lectura sin autenticación. En la configuración de un servicio centralizado de usuarios con kerberos, estos accesos son poco flexibles e inseguros, por lo tanto hay que eliminarlos, y luego plantear nuevos accesos que utilicen usuarios autenticados con kerberos.
Al utilizar la estructura kerberos, los atributos userPassword y shadowLastChange no son necesarios, por lo que se puede eliminar dicho acceso.

Para lograr este objetivo, crear el siguiente LDIF llamado delete-default.ldif:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
#
# Eliminar acceso al usuario admin
delete: olcAccess
olcAccess: {2}to *
by self write
by dn="cn=admin,dc=dvpem,dc=org" write
by * read
-
# Eliminar acceso de lectura sin autenticacion
delete: olcAccess
olcAccess: {1}to dn.base=""
by * read
-
# Eliminar accesos a los atributos password de los usuarios
delete: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
by self write
by anonymous auth
by dn="cn=admin,dc=dvpem,dc=org" write
by * none
-
# Prohibir acceso al atributo password
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
by * none
-
# Eliminar el usuario admin
delete: olcRootPW
-
y ejecutar el comando:
$ ldapmodify -f delete-default.ldif -x -D cn=admin,cn=config -W
Se puede verificar que todo salió como se deseaba con el comando:
# slapcat -b cn=config -a olcDatabase={1}hdb

2. Crear grupo administrador del dominio

Como muchos sabrán, en Active Directory existe un grupo denominado Domain Admins, el cual tiene permiso de administración sobre todo el directorio y las máquinas unidas al dominio.
En el caso del dominio que se está configurando, es muy útil tener un grupo con las mismas características, que permita administrar el directorio. El siguiente LDIF denominado domain-root.ldif crea dicho grupo, cuyo único miembro (por ahora) es el usuario demasiadovivo:

dn: cn=domain_root,ou=Group,dc=demasiadovivo,dc=org
cn: domain_root
gidNumber: 1000
objectClass: top
objectClass: posixGroup
memberUid: demasiadovivo
Como todavía el único usuario con permiso de administración es admin, se debe utilizar el mismo con la herramienta ldapadd:
$ ldapadd -x -D cn=admin,cn=config -W -f domain-root.ldif
Enter LDAP Password:
adding new entry "cn=domain_root,ou=Group,dc=demasiadovivo,dc=org"

3. Otorgar control total al grupo domain_root sobre el directorio

Este punto es uno de los más complejos. Como vimos, OpenLDAP es muy flexible en cuanto a otorgar permisos y posee una facilidad para otorgar permisos por grupo (by group). El problema es que este se aplica a la clase groupOfNames y no sirve para posixGroup.
Se me ocurrieron varias alternativas para solucionar este problema:

1- Utilizar groupOfNames y mapear los request NSS_LDAP con una expresión regular que sustituya los pedidos, como se mostró en la sección anterior.
2- Editar el esquema de posixGroup para agregar el atributo member.
3- Utilizar la definición de posixGroup del RFC 2307bis, la cual expiró y nunca se aprobó. Esta RFC incluye el campo member en la definición.
4- Otorgar permisos basados en sets.
5- Cambiar el formato de las consultas LDAP de la librería NSS_LDAP para que utilice groupOfNames.
Como se puede observar, opciones hay, pero ninguna satisfactoria del todo. Yo opté por la 4ta, dado que encontré una buena definición del permiso por parte de Pierangelo Masarati. De todas, creo que es la que menos complicaciones trae, al menos para este setup inicial. Si bien el acceso que defino a continuación tiene la misma base que el de Pierangelo, tuve que cambiar el DN del conjunto, porque el original no me funcionó.

Para el permiso definimos el siguiente LDIF denominado domain_root-access.ldif:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to dn.subtree="dc=demasiadovivo,dc=org"
by set="([uid=] + ([cn=domain_root,ou=Group,dc=demasiadovivo,dc=org])/memberUid + [,cn=gssapi,cn=auth])/entryDN & user" write
Al principio puede resultar confuso, pero analicemos un poco qué es lo que se está haciendo.
En la primer línea se indica que se está otorgando permiso a todo el dominio demasiadovivo.org. dn.subtree es el scope, e indica que se aplique a todo lo que contiene el dominio.
En la segunda línea se indica a quién se otorga el permiso y qué tipo de permiso (write). Esta es la parte más confusa.
Primero hay que entender qué es lo que se desea otorgar. Lo que debemos hacer es otorgar permiso de escritura a todos los miembros del grupo domain_root. Los miembros se obtienen del atributo memberUid, pero este atributo no es un DN, sino sólo el nombre del usuario. Como el permiso debe otorgarse a un DN, primero hay que armarlo.
El DN de un usuario consta de uid=,cn=gssapi,cn=auth. Lo único que tenemos es el nombre de usuario, por lo tanto, hay que armar el resto del string (los strings se concatenan con el signo +). Para hacerlo se utilizan los siguientes valores:

  • [uid=], para agregar el string uid=
  • ([cn=domain_root,ou=Groups,dc=demasiadovivo,dc=org])/memberUid para agregar el nombre de usuario de los miembros del grupo. Se utilizan los parentesis porque los mismos indican precedencia, de esta forma se evalúa primero el grupo y luego se obtienen los miembros.
  • [,cn=gssapi,cn=auth] para agregar la parte restante del DN
Para obtener el DN definitivo, se encierra todo entre paréntesis y se obtiene el atributo entryDN. El resultado es la lista de todos los usuarios que integran el grupo domain_root. Este conjunto se intersecta (operador &) con la base "user" que referencia al usuario autenticado actualmente. La intersección retornará el DN del usuario, si el usuario está en el grupo, o vacío si no lo está, otorgando o negando el permiso.

Para agregar este nuevo acceso, utilizar ldapmodify con el usuario administrador de la base de datos de configuración (cn=admin,cn=config):

$ ldapmodify -f domain_root-access.ldif -x -D cn=admin,cn=config -W

4. Asignar acceso de lectura a usuarios autenticados

Llegado este punto, ya tenemos el grupo de administración del dominio, pero no los accesos de lectura para que los usuarios lean las entradas. Esto se logra definiendo el siguiente LDIF denominado read-access.ldif:

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {1}to *
by users read
by * none
que se agrega con:
$ ldapmodify -f read-access.ldif -x -D cn=admin,cn=config -W

Configurar las máquinas cliente para usar GSSAPI

De la configuración anterior tenemos que ahora sólo se puede consultar al servidor LDAP si el cliente se autenticó previamente ante kerberos. Debido a esto, hay que configurar NSS-LDAP de forma especial, para que el servicio pueda consultar el directorio y obtener los datos del usuario que se está autenticando.
Hasta ahora, cuando un usuario se autentica ante el sistema, primero PAM valida las credenciales con kerberos, y luego NSS se conecta de forma anónima al servidor LDAP para traer los datos del usuario. Como ahora no es posible obtener datos de forma anónima, es necesario que NSS utilice GSSAPI con un ticket kerberos. El problema es qué ticket utilizar? dado que no podemos utilizar el ticket que se obtiene al validar al usuario.

Para solucionar este problema, es necesario realizar los siguientes pasos:

1. crear un principal por cada host,
2. exportar la clave de cada principal a keytabs,
3. mover cada keytab al host correspondiente,
4. configurar NSS de cada host para utilizar kerberos y realizar la autenticación con el keytab correspondiente.

Crear principal para host y exportar clave en keytab

Para crear el principal del host maquina01 y exportarlo en el keytab maquina01.keytab, nuevamente hacemos uso de la herramienta kadmin.local (o kadmin si se conectan remoto), y ejecutamos lo siguiente:

kadmin.local: addprinc -randkey host/maquina01.dvpem.org@DVPEM.ORG
WARNING: no policy specified for host/maquina01.dvpem.org@DVPEM.ORG; defaulting to no policy
Principal "host/maquina01.dvpem.org@DVPEM.ORG" created.
kadmin.local: ktadd -k /root/maquina01.keytab host/maquina01.dvpem.org
Entry for principal host/maquina01.dvpem.org with kvno 2, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/root/maquina01.keytab.
Entry for principal host/maquina01.dvpem.org with kvno 2, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/maquina01.keytab.
Entry for principal host/maquina01.dvpem.org with kvno 2, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/maquina01.keytab.
Entry for principal host/maquina01.dvpem.org with kvno 2, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/root/maquina01.keytab.
Se utiliza -randkey para generar una clave aleatoria, dado que se utilizará directamente desde el archivo maquina01.keytab.

El paso anterior podría haberse realizado directamente desde el host maquina01, utilizando el comando kadmin y descargando la clave a un keytab local (/etc/krb5.keytab). En resultado es el mismo.


Configurar NSS-LDAP para utilizar kerberos en los clientes

Una vez generado el principal del host maquina01, hay que mover el keytab recién creado al host correspondiente. Un buen lugar para colocar el keytab es en /etc/krb5.keytab, que es el archivo default de kerberos. Por seguridad, el archivo debe poseer permisos 640:

# chmod 640 /etc/krb5.keytab
Con la clave en su lugar, procedemos a configurar NSS-LDAP. En debian el archivo de configuración se encuentra en /etc/nslcd.conf. En dicho archivo se deben agregar las siguientes líneas:
sasl_mech gssapi
krb5_ccname FILE:/tmp/krb5cc_0

donde:

- sasl_mech indica el mecanismo SASL a utilizar (GSSAPI)
- krb5_ccname informa donde se encuentra el ticket kerberos
Una vez especificados los parámetros anteriores, nslcd comenzará a utilizar k5start para obtener el ticket del host antes de acceder a LDAP. Este demonio permite configurar algunos aspectos de cómo utilizar k5start a través del archivo /etc/default/nslcd. En el mismo se puede forzar la ejecución de k5start, como configurar la ubicación de la clave, el nombre del principal, y cada cuánto refrescar el ticket. La configuración por default es buena para la mayoría de los casos, aunque recomiendo agregar las siguientes líneas:
K5START_START="yes"
K5START_PRINCIPAL="host/maquina01.dvpem.org"
donde K5START_START="yes" fuerza el uso de k5start, y K5START_PRINCIPAL="host/maquina01.dvpem.org" indica cuál es el nombre del principal.
Si todavía no tienen instalado kstart, pueden hacerlo con:

# apt-get install kstart
Al finalizar la configuración, reiniciar el demonio nslcd para que tome los cambios:
# /etc/init.d/nslcd restart
Para probar, simplemente realizar un login con una cuenta que esté definida en LDAP. También pueden ver que se consulta LDAP al utilizar el comando:
$ getent passwd
En caso de que no esté funcionando y debamos revisar la configuración, primero detener el demonio nscd, dado que este cachea los resultados de las consultas, y por lo tanto, el resultado que se obtiene puede no ser el real:
# /etc/init.d/nscd stop
Luego revisar los siguientes logs:
- en el cliente:
/var/log/auth.log
- en el servidor:
/var/log/debug
Otra ayuda es observar en el cliente si el proceso login se conecta al servidor LDAP al momento de autenticar, con el siguiente comando:
# lsof -r 2 -i
donde:
-r 2 pone lsof en modo repetición. De esta forma lsof lista lo seleccionado por otros argumentos, espera 2 segundos y vuelve a listar.
-i lista los procesos que estan escuchando en sockets tcp o udp.

Referencias

- OpenLDAP - 15. Using SASL 

- LDAP, Kerberos 5, SASL and Passwords 
- Debian OpenLDAP with Kerberos Authentication
- Red Hat Documentation - 10.2.6. Setting Up Kerberos Authentication
- OpenLDAP - 5. Configuring slapd
- LDAP Administration Guide
- OpenLDAP FAQ - Sets in Access Controls
- Integrated Kerberos-OpenLDAP client on Debian lenny
- Configuring LDAP Authentication

- FreeBSD Forum - nss_ldap sasl gssapi authentication?
- RedHat mailing list - nss_ldap using sasl with gssapi. Kerberos credentials cache problem[Scanned]