Autenticación en GNU/Linux con PAM
Antiguamente, la autenticación en sistemas UNIX estaba ligada al que hoy conocemos como "sistema tradicional UNIX", el cual verifica usuario y contraseña contra los valores almacenados en el archivo /etc/passwd (en versiones modernas el password se movió al archivo /etc/shadow por cuestiones de seguridad).
Dado que con los años se fueron desarrollando distintos métodos de autenticación más seguros, seguir clavados utilizando el método tradicional era poco flexible y sin sentido.
A partir de la necesidad de poder cambiar fácilmente entre métodos de autenticación y utilizar distintos métodos, Sun diseñó PAM (Pluggable Authentication Modules). PAM es un conjunto de librerías que permiten una gran variedad de mecanismos de autenticación, entre los cuales contamos con Kerberos, LDAP, y RADIUS (además del tradicional /etc/passwd). Gracias a esto, actualmente es posible autenticar usuarios GNU/Linux contra bases centralizadas de usuarios como el citado kerberos.
PAM no sólo permite utilizar distintos métodos de autenticación, sino que permite utilizar varios al mismo tiempo. Además agrega la posibilidad de utilizar otros medios de autenticación (más allá del clásico usuario/password), como ser smartcards, tockens, etc.

En este artículo les explicaré cómo se configura la autenticación utiliando PAM, y sobre el final podremos entender la configuración de un debian default.


Configuración

PAM divide la tarea de autenticación en cuatro grupos de administración separados:
- account provee verificación de tipos de servicio para la cuenta: el password expiro? tiene permitido acceder el servicio requerido? root puede loguearse por consola?
- authentication autentica el usuario, y luego otorga los privilegios correspondientes (como membresía de grupo). Este módulo permite setear distintos requerimientos para autenticar al usuario, como passwords, smartcards, tockens, etc.
- password es responsable de actualizar los mecanismos de autenticación. Estos servicios están fuertemente acoplados con los del grupo authentication.
- session cubre las acciones que se deben hacer antes de que se otorgue un servicio y luego de que el servicio haya sido retirado. En el caso de login, las acciones pueden ser logging y montado de directorios.
La configuración de PAM se realiza a través de reglas y el archivo principal es /etc/pam.conf, aunque en general se prefiere dividir las reglas en diferentes archivos del directorio /etc/pam.d/.
Cada regla tiene cinco campos, separados por espacios:
servicio tipo control path-modulo argumentos-modulo
donde:
- servicio es el nombre familiar que corresponde a la aplicación (ej: login, su, sshd). Este campo no se incluye en los archivos de /etc/pam.d, dado que el servicio está indicado por el nombre del archivo en minúscula. El servicio correspondiente a login utiliza a los archivos common-account, common-auth, common-password y common-session para configurar cada uno de los grupos.

- tipo: es el grupo de administración al que se aplica la regla (account, auth, password o session).

- control indica el comportamiento que PAM debe seguir en caso de que el módulo asociado tenga éxito o falle. Este campo permite dos notaciones. En la notación simple, se utiliza una palabra clave, y en la compleja se encierran pares valor=acción entre corchetes [valor1=acción1, valor2=acción2, ....]
Una característica importante de PAM es que las reglas se pueden "apilar" para combinar los servicios de varios PAMs para una dada autenticación. Los valores de retorno de cada módulo se guardan en una pila. Gracias a esto, es posible, por ejemplo, intentar autenticar primero con kerberos, y si esto falla, intentar autenticar localmente con autenticación unix.

Las palabras claves más comúnmente utilizadas en la notación simple, son:
- required: indica que la ejecución del módulo debe ser exitosa para que la operación sea exitosa. Sin embargo, si el módulo falla, la operación fallará recién luego de que se invoque al resto de los módulos que vienen después.
- requisite: igual que required, pero si el módulo falla, se retorna el control directamente a la aplicación. Es decir, no se continua invocando módulos como sucede con required.
- sufficient: el éxito del módulo es requerimiento suficiente para la operación, esto es, no se continúa procesando los siguientes módulos. Si falla, el proceso continúa en la siguiente regla.
- optional: el resultado de este módulo es importante sólo si es el único en el stack.
En la notación compleja, los valores son códigos de retorno. Los más vistos comúnmente son:
- success: la función retornó ok
- ignore: ignorar el módulo en cuestión, sin importar si el flag de control es required, optional o sufficient.
- new_authtok_reqd: se requiere un nuevo token de autenticación. Utilizado generalmente cuando el password debe ser cambiado.
- default: implica todos los valores que no se mencionan explícitamente.
Las posibles acciones en esta notación pueden ser un entero n sin signo, que indica la cantidad de módulos a saltar en el stack, o tomar alguna de las siguientes formas:
- ignore: el estado de retorno del módulo no influenciará el resultado final, a menos que no haya otro módulo en el stack.
- bad: el estado de retorno debe indicar el fallo del módulo. Si esta es la primer falla, este estatus se usará para todo el stack.
- die: idem a bad, excepto que el stack termina y se retorna el control a la aplicación inmediatamente.
- ok: el código de retorno sobreescribirá un valor previo de éxito, pero no un estado previo de falla.
- done: idem a ok, excepto que el stack termina y el control se retorna inmediatamente a la aplicación.
- reset: se limpia el stack y se comienza de nuevo con el próximo modulo.
Como se puede observar, en la notación compleja se permite mucha más granularidad que utilizando palabras claves. Por ello, es posible representar los mismos valores que las palabras claves con notación compleja:
required = [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
requisite = [success=ok new_authtok_reqd=ok ignore=ignore default=die]
sufficient = [success=done new_authtok_reqd=done default=ignore]
optional = [success=ok new_authtok_reqd=ok default=ignore]
- path-modulo es el path al módulo, o la dirección relativa al directorio donde se ubican los módulos por default, el cual es /lib/security en debian.

- argumentos-modulo son los argumentos, separados por espacios, que se envían al módulo.

Ejemplo práctico

Para entender mejor cómo funciona PAM, veamos el contenido de los archivos en la configuración de un sistema debian default.
/etc/pam.d/common-account (verificación de tipos de servicio)
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
account requisite pam_deny.so
account required pam_permit.so
De la explicación anterior, podemos entender que el sistema utilizará el módulo pam_unix. Si esta autenticación tiene éxito (success=1), se saltea la siguiente regla y se ejecuta el módulo pam_permit, permitiendo el acceso.
En caso de fallar, se ejecuta el módulo pam_deny, el cual siempre retorna un valor de fallo; y como el parámetro de control es "requisite", la operación termina inmediatamente.

/etc/pam.d/common-auth (autenticación de usuario y seteo de credenciales)
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
Este caso es casi igual al anterior, sólo que se utiliza el parámetro nullok_secure al llamar al módulo. En la acción default del módulo no se permite el acceso a un servicio si su password oficial es nulo. Lo que hace este parámetro es sobreescribir este comportamiento y permitir usuarios con password en blanco.

/etc/pam.d/common-password (actualización de passwords)
password [success=1 default=ignore] pam_unix.so obscure sha512
password requisite pam_deny.so
password required pam_permit.so
password optional pam_gnome_keyring.so
En este archivo el cambio es que se agregan los parámetros obscure y sha512 al módulo pam_unix. obscure fuerza el checkeo de la fortaleza del password y sha512 hace que los passwords se almacenen hasheados con sha512.
El módulo pam_gnome_keyring permite el desbloqueo del archivo donde Gnome almacena credenciales del usuario (viene con Gnome). Como ven, el resultado de la ejecución de este módulo no afecta el resultado final de la operación.

/etc/pam.d/common-session (acciones a realizar antes de login y luego de logout)
session [default=1] pam_permit.so
session requisite pam_deny.so
session required pam_permit.so
session required pam_unix.so
En este último archivo no encontramos nada especial, sólo que se ejecuta el módulo pam_unix. El formato de este archivo no tiene mucho sentido, porque dado que pam_permit siempre termina bien, lo siguiente a ejecutar es nuevamente pam_permit, con lo cual se continúa hasta la ejecución de pam_unix. La razón de que esto esté así es por compatibilidad con los archivos anteriores, ya que si observan bien, la estructura es similar.


Referencias

- PAM configuration guide for Debian
- The Linux-PAM System Administrators' Guide - 4. The Linux-PAM configuration file
- Understanding PAM
Metiendo mano en el hardware

En este artículo voy a relatar una de las experiencias más satisfactorias que he tenido lidiando con hardware.

Este viernes encendí mi computadora de escritorio y al poco tiempo mi monitor lamentablemente se "murió". Era Es un monitor Samsung modelo SyncMaster740N LCD de 17" 4:3. Se trata de un modelo bastante común, ya que es usado generalmente en cibercafés, oficinas, etc.

Al poco tiempo de encender la computadora, la pantalla se volvió negra, como cuando se activa el ahorro de energía, pero la luz de power permaneció encendida (cuando está en ahorro de energía se mantiene parpadeando). Primero pensé en un problema de video por lo que reinicié la computadora sin éxito. Luego apagué y encendí el monitor repetidas veces y tampoco tuve éxito.

En ese momento me sentí frustrado al pensar en tener que afrontar un gasto de aproximadamente U$S 250, sobretodo teniendo en cuenta que el monitor tiene sólo 5 años de vida. Pero pensé que tal vez podría tener arreglo y, tocando botones de configuración y mirando detenidamente la pantalla, me dí cuenta que se veía una ventana muy pero muy tenuemente (con buena luz ambiente y prestando mucha atención). Parecía como si el monitor funcionara correctamente, aunque sin brillo o iluminación (la pantalla se veía opaca como la de una calculadora de bolsillo, aunque mucho más tenue).

Inmediatamente me puse a investigar en Internet y descubrí que a alguien ya le había sucedido exactamente lo mismo (http://www.fixya.com/support/t4636238-samsung_740n_blank_screen). Desde hace un tiempo el monitor emitía un zumbido extraño pero funcionaba correctamente, hasta que un día la pantalla se puso negra. Aparentemente los zumbidos se deben a capacitores en mal estado.

En otro sitio descubrí que cuando la pantalla se vuelve oscura pero se pueden ver las ventanas, significa que el problema son las backlights. Las backlights son una especie de pequeños tubos fluorescentes que se ubican detrás (o al costado) del panel LCD para darle iluminación y brillo a la pantalla y así producir una imagen visible. Esto se debe porque, a diferencia de las pantallas CRT, los paneles LCD no producen luz por sí mismos (http://en.wikipedia.org/wiki/Backlight). Entonces el problema podía estar en las backlights mismas o en el circuito que las alimenta. Aunque el zumbido que emitía el monitor hasta el momento de apagarse indicaba que el problema era algún capacitor en mal estado.

En un foro que me resultó extremadamente útil (http://www.yoreparo.com/foros/plasma_lcd/falla-lcd-samsung-740n-t259814.html) encontré la respuesta a mi problema:
Atención reparadores de monitores SAMSUNG 740 N, 17 pulgadas. Al cabo de tres años de funcionamiento, estos monitores fallan debido a la temperatura que alcanza la fuente de alimentación, por cierto muy mal ventilada.

Deja de funcionar la fuente de la lámpara del panel, sin embargo, el monitor sigue trabajando normalmente (se comprueba al abrir el menu de ajustes, porque se puede ver muy tenuemente)

Los primeros en fallar son tres capacitores de 820 uF/25v que filtran la etapa previa a los exitadores de la fuente de 650 v, 17 mA
(c112, c111, c301) extrañamente de un color distinto a los demas (marrones), se ve que son de inferior calidad. Con la temperatura se inchan y se desvalorizan. Tambien salta un pico fusible de 3A (ubicado entre medio de una pegamento blanco entre el disipador de D105 y los capacitores nombrados. Reemplazando estos se soluciona. [sic]

A eso se resume básicamente mi experiencia, podría cerrar el artículo en este punto pero voy a continuar explicando los detalles.

Esperanzado me puse a desensamblar el monitor y en un principio me resultó imposible ya que no tiene tornillos. Me puse a buscar en Google y encontré un manual (http://www.eserviceinfo.com/downloadsm/28685/Samsung_740N.html) del fabricante donde explica paso a paso como desarmar y armar el monitor con fotos (muy bueno, asombrosa la calidad de los manuales de Samsung). De forma increíble todo el monitor es sostenido por la carcasa de plástico, la cual se mantiene unida con unas pequeñas trabitas de plástico (afortunadamente no se rompió ninguna al desarmarlo, como me ha sucedido otras veces al tratar de desarmar otros dispositivos como radios, controles remotos, etc.).


En la foto se observa el monitor completamente destripado. Al examinar los componentes de la plaqueta rápidamente me dí cuenta que los tres capacitores indicados en el post del foro yoreparo.com estaban "inflados", incluso uno tenía un sedimento en la parte superior. Esto es algo que aprendí cuando cursaba taller de electrónica en la secundaria: si un capacitor está inflado significa que está roto. Por eso es uno de los componentes más fáciles de detectar.


En la foto se ve claramente la parte superior inflada (notar la diferencia con los otros capacitores).

El siguiente paso fue retirar del circuito los capacitores dañados. Esto se debe realizar cuidadosamente para no dañar el resto de los componentes. Con un soldador de estaño (si se dispone uno de baja potencia, por ejemplo 15W, mejor) se calientan las patas y se va tirando del capacitor suavemente y alternando entre patas hasta removerlo completamente.

Con uno de los capacitores me dirigí a la casa de electrónica más cercana (ninguna realmente cercana así que tuve que patear bastante) para buscar los recambios. Estos capacitores son de 820uF y son difíciles de conseguir, entonces tuve que comprar de 1000uF. Además no conseguí de 105º, los que compré son de 85º (espero que aguanten la temperatura elevada hasta que pueda conseguir de 105º).

Procedí entonces a instalar los nuevos capacitores. Primero se debe eliminar el estaño de la pista (sería ideal disponer de un removedor de soldadura) y luego colocar la pieza. Se debe prestar extrema atención al colocar los capacitores electrolíticos, ya que estos poseen polaridad. Si se conectan de forma inversa van a, literalmente, explotar (lo cual por cierto es muy divertido http://www.youtube.com/watch?v=ipiyP6Cph9M). En la plaqueta y en el capacitor se indica claramente el polo negativo. De todas formas hay que revisar la polaridad antes de soldar y antes de conectar.

La forma adecuada de soldar es calentar con la punta del soldador la pista y la pata al mismo tiempo y luego aplicar la cantidad suficiente de estaño. Si la pista o la pieza están frías la soldadura será defectuosa y seguramente no hará contacto, por lo que hay que tener cuidado al realizar la unión. Luego se corta el excedente de pata y se revisa cuidadosamente la pista para que no queden puentes de estaño entre pistas contiguas.


Bien, lo que quedaba era ensamblar precariamente el monitor para poder comprobar el correcto funcionamiento. En la primera prueba que hice el monitor no encendió, por ello tuve que volver al post encontrado en yoreparo.com para darme cuenta que también el picofusible podía estar quemado. De hecho lo estaba, para darme cuenta simplemente hice un puente en el fusible y el monitor encendió, para mi alegría.


Dado que no conseguí hasta el momento un picofusible de repuesto, lo reemplacé con un fusible común de 3A y probé continuidad con el tester para comprobar que estuviera todo OK.
Luego de terminada la reparación, ensamblé el monitor y lo probé con la notebook.


Perfetto!


El costo total de la reparación fue de aproximadamente U$S 2.

Conclusión: vale la pena intentar reparar las cosas :)

Espero que les haya gustado.
Administrar proyectos libres con Launchpad y Bazaar
En los últimos días estuve ocupado creando una herramienta que me permitiera realizar consultas sobre un servicio LDAP para obtener información de los usuarios de un dominio. La herramienta en cuestión la realicé en Python y me pareció que era lo suficientemente interesante como para compartirla con la comunidad libre para que cualquiera pueda utilizarla y/o modificarla.
Esto me llevó a la búsqueda de un servicio de versionado y hosting libre donde subir el proyecto. Algunos años atrás hubiera utilizado SourceForge sin pensarlo, pero gracias a su cambio de política hacia una censurista y asquerosamente repudiable (que raro que provenga de una ley yankee "defensores de la libertad"...) que deja afuera a los países Iran, Corea del Norte, Cuba, Siria, Libia y Sudan, decidí buscar una alternativa que sea realmente libre. La idea es compartir código entre comunidades sin importar estatus social, país de orígen, color de piel, etc, etc, y SourceForge no cumple con este importantísimo requisito. Lo mismo sucede con Google Code, lo cual elimina al segundo gran proveedor de software open source.
Por ello, utilizando la muy completa entrada de wikipedia Comparison of open source software hosting facilities, revisé cuál de los servicios se adaptaba mejor a lo que quería. Por orden de popularidad tenemos SourceForge (descartado), Launchpad, Google Code (descartado), GitHub y Assembla. De entre estos elegí Launchpad porque los términos de servicio de GitHub y Assembla no me terminaban de agradar. Increíblemente GitHub impone copyright sobre el código html/javascript/css de SU propia página... un site que promulga el hosting de aplicaciones open source y no es libre, no me agrada. Además, los mencionados servicios están hosteados en USA y aplican sus leyes, con lo cual corremos el riesgo que suceda lo mismo que con SourceForge.
Launchpad es de Canonical Ltd. (la gente detrás de Ubuntu) y esto también me genera dudas, dado que desconfío de las intenciones de dicha compañía... pero no encontré nada malo en sus términos de servicio (es más, no encontré términos de servicio para hosting de proyectos...), es una comunidad muy grande con proyectos importantes (MySQL, Ubuntu, Enlightenment, Bazaar, entre otros), no está hosteado en USA (por lo que vi, los servidores son de Gran Bretaña) y el administrador de proyectos me parece bueno.

A continuación describiré los pasos necesarios desde la creación hasta la publicación de una versión descargable de nuestro proyecto, utilizando Launchpad y Bazaar.


Creación del proyecto en Launchpad

Para crear un proyecto en Launchpad, primero debemos registrar una cuenta, si es que no poseemos una. La registración es simple y no requiere muchos datos.
Una vez que estamos registrados y logueados, nos dirigimos a https://launchpad.net/projects/+new para registrar nuestro proyecto.
Para tener una idea sobre cómo se administran los proyectos en Launchpad, les recomiendo leer la ayuda oficial.


Creación del proyecto en Bazaar

Launchpad utiliza Bazaar para el versionado de proyectos, por lo que necesitaremos conocer una lista de comandos básicos de este sistema. Es posible importar branchs de otros manejadores de versionado como Git, Mercurial, Subversion y CVS, pero si recién están comenzando, o si nunca utilizaron un manejador de versiones, por qué no probar con Bazaar?

Instalar Bazaar en debian y derivados es tan simple como ejecutar:
# apt-get install bzr
Una vez instalado, configuramos nuestro nombre de usuario:
$ bzr whoami "demasiadovivo <demasiadovivo@spameame.com>"
y verificamos que el nombre se registró correctamente:
$ bzr whoami
demasiadovivo <demasiadovivo@spameame.com>
Luego del simple setup inicial, nos metemos con la creación y administración de proyectos utilizando este sistema de versionado.
El primer paso es inicializar el proyecto:
- dirigirse al directorio donde se encuentra el código del proyecto:
$ cd /path/mi-proyecto
- inicializar:
$ bzr init
Al hacer esto, Bazaar crea el primer branch y almacena los datos en un directorio denominado ".bzr". Un branch es un registro de todos los commits que se han hecho. Pueden existir varios branches en paralelo, los cuales luego se pueden combinar (merge).
Para agregar los archivos que deseamos seguir, se utiliza el comando bzr add . Para agregar todos los archivos del directorio del proyecto, podemos simplemente ejecutar:
$ bzr add
adding README.txt
adding useraudit.cfg
adding useraudit.py
adding useraudit_cli.py
Ahora, cuando tenemos código sobre el cual deseamos crear un snapshot, realizamos un commit. En el commit es posible agregar un comentario, indicando la razón del mismo:
$ bzr commit -m "Primer commit"
Committing to: /ruta/mi-proyecto/
added README.txt
added useraudit.cfg
added useraudit.py
added useraudit_cli.py
Committed revision 1.
Podemos ver el historial de commits con:
$ bzr log
------------------------------------------------------------
revno: 1
committer: demasiadovivo

branch nick: mi-proyecto
timestamp: Sun 2011-06-05 16:20:03 -0300
message:
Primer commit

Subir el código a Launchpad

Para poder subir código a Launchpad, primero deberán generar un par de claves SSH, para lo cual pueden seguir el artículo Automatización de transferencias por SFTP, y a continuación publicar la clave pública en https://launchpad.net/~<usuario>/+editsshkeys
Recuerden que la clave pública se encuentra en /home/<usuario>/.ssh/id_rsa.pub, si es que no eligieron otro path al generar el par de claves.
Con esta clave podremos autenticarnos ante Launchpad y así subir código.

Una vez que registramos nuestra clave SSH, podemos subir el commit a Launchpad ejecutando:
$ bzr push sftp://<usuario>@bazaar.launchpad.net/~<usuario>/<mi-proyecto>/<branch>
donde:
bazaar.launchpad.net es la dirección de Bazaar en Launchpad
<usuario> es nuestro usuario en Launchpad
<mi-proyecto> es el proyecto que registramos en Launchpad
<branch> es el branch que deseamos crear
Si queremos hacer un commit a un branch que ya existe, deberemos ejecutar el mismo comando pero con un parámetro adicional:
$ bzr push --use-existing sftp://@bazaar.launchpad.net/~<usuario>/<mi-proyecto>/<branch>
Luego de crear el branch, es posible (al menos a mi me sucedió), que Launchpad nos diga que el proyecto todavía no tiene un branch. Esto es que Launchpad no sabe cuál es el branch principal, por lo cual nos dirigimos a https://launchpad.net//trunk/+setbranch y elegimos la opción "Link to a Bazaar branch already on Launchpad", y en el textbox donde indicamos el branch ponemos la dirección del branch recién creado:
~<usuario>/<mi-proyecto>/<branch>

Generar un release

Una vez que estamos lo suficientemente conformes con nuestro código y queremos que usuarios finales descarguen el programa, debemos generar un release y para generar un release, necesitamos un milestone.

Los milestones son puntos específicos en la vida de una serie (series en inglés), y una "serie" representa la serie de lanzamientos de una versión mayor. Los puntos representados por un milestone pueden ser beta tests, release candidates, o puntos menor y mayor de lanzamiento. Pueden leer más sobre series, milestones y releases en Projects/SeriesMilestonesReleases.
En fin, para crear un milestone, nos dirigimos a la sección "Milestones and releases" de la página principal del proyecto y le damos al link "Create milestone" (https://launchpad.net//trunk/+addrelease).
Entre la información que debemos proveer, el único campo obligatorio es el nombre, el cual se toma como la versión.

Una vez que tenemos el milestone creado, podemos proceder a realizar el release. Hacerlo es tan simple como darle al link "Create release" que se encuentra en el milestone bajo el título "Expected" y setear una fecha.

Cuando terminamos de crear el release, el site nos regresa al milestone, donde podemos ver que la fecha del release se actualizó. Ahora sí podemos agregar un archivo tarball descargable que contenga el programa completo.
Pueden generar el tarball de diferentes formas, pero si lo van a hacer desde la consola, deberán dirigirse al directorio padre del proyecto y ejecutar lo siguiente:
$ tar -czvf mi-proyecto_v0.1.tar.gz --exclude-vcs mi-proyecto/
donde la opción --exclude-vcs evita que tar incluya el directorio que utiliza Bazaar para sus datos (es decir, el ".bzr").
Ya tenemos todo lo necesario para subir el tarball con el programa completo y que se pueda descargar. Para ello, en el milestone seleccionamos "Add download file". En la interfaz de upload debemos proveer tanto el archivo como una descripción de lo que contiene el mismo (por ejemplo "mi-proyecto 0.1 tarball"). También es posible proveer una firma GPG, lo cual brinda mayor seguridad al cliente que descarga, ya que puede confiar que el archivo ha sido creado por nosotros. Para poder firmar el archivo debemos poseer una un par de claves GPG (o PGP), y la clave pública debe estar publicada en algún lugar de confianza.
El mismo site da la ayuda de cómo crear la firma digital del archivo:
gpg --armor --sign --detach-sig
lo cual crea el archivo filename.asc que después debemos subir utilizando el campo "GPG signature".


Trabajo Terminado

Si quieren ver el resultado final, pueden ingresar al site de mi proyecto. También están invitados a descargar, testear, recomendar, compartir, etc, etc, el programa. Ya escribiré algún post sobre la herramienta =)


Referencias

- Launchpad Projects
- Bazaar in five minutes
- Hosting your code on launchpad and bazaar