martes, 9 de febrero de 2010

Ojo con lo que compilás, nabo.

A veces uno hace tonterías y se le complican las cosas más simples... Esta es la historia de cómo se complicó algo que debió haber funcionado bien desde el principio, simplemente por equivocarse de versión de un software accesorio (y de cómo encontré el error finalmente).

En uno de nuestros productos (el servidor de correo electrónico), utilizo un sistema de control de contenidos basado en una versión modificada de simscan.

El viernes pasado estuve tratando de compilar la última versión (1.4.0), con algunas modificaciones para resolver detalles de ejecución cuando se hace referencia al antivirus ClamAV (básicamente, el problema surge del umask activo en el momento en que simscan crea el directorio de trabajo donde va a almacenar los adjuntos para procesarlos), así que apliqué los cambios e intenté compilar. El producto final pareció quedar perféctamente bien, así que se instaló y quedó "funcionando".

En las pruebas consecuentes, observé que el servicio SMTP fallaba miserablemente. Cuando intentaba enviar cualquier tipo de mensaje a través del nuevo servidor, aparecía un error en el programa de correo, aunque el error no aparecía como debía ser, sino que solo aparecía un error de transmisión (fucking cliente de correo apestoso...).

Puse una captura de tráfico en el servidor, y cuando intenté enviar un mensaje pude ver el mensaje de error que el servidor enviaba al cliente (y que el cliente no me mostraba...):

451 mail server temporarily rejected message (#4.3.0)

Traté de buscar el error en el código fuente del QMail (usando grep), para poder determinar qué era que lo causaba, y así llegué al archivo qmail.c, donde encontré que la línea se correspondía con el código de error número 71:

switch(exitcode) {
[...]
case 71: return "Zmail server temporarily rejected message (#4.3.0)";


En linux, los códigos de error están definidos en el archivo /usr/include/sysexits.h de los headers del kernel, así que como no me acordaba de a qué correspondía exactamente, me puse a buscar el código en los fuentes, llegando a la línea que contiene la explicación del error:

#define EX_OSERR 71 /* system error (e.g., can't fork) */


Aparentemente, el QMail no podía iniciar una instancia de "algo" que invocaba en el momento que el mensaje se iba a pasar a la cola para posterior procesamiento, así que evidentemente el problema tenía que estar en el programa de manejo de la cola. Solo hay dos opciones para este caso, o se usa el programa original de QMail para el manejo de la cola qmail-queue, o se invoca el programa que se encarga de los chequeos de contenidos, y ese es el simscan.

Como de todas maneras no sabía porqué fallaba, activé un recordio sobre el servicio (básicamente captura la salida y los mensajes de error de todos los programas implicados en la transacción y los almacena en el log para posterior análisis), y así podría ver qué pasaba exactamente en los registros del mismo. Y entonces el error se hizo visible:

@400000004b6c75a6291a77f4 simscan: ripmime error
@400000004b6c75a6291a7bdc simscan: exit error code: 71
@400000004b6c75a6291ca2a4 10303 > 451 mail server temporarily rejected message (#4.3.0)


Aparentemente, el que fallaba era el ripmime... cosa rara, ya que nunca me había dado problema. Simscan utiliza ripmime para extraer los adjuntos de los mensajes, para luego pasarle el antivirus y el antispam a cada uno por separado. Decidí revisar el ripmime y todo parecía correcto. El ripmime podía ser invocado sin problemas desde la línea de comandos. Hice pruebas para verificar que hacía su trabajo y todo funcionó correctamente, desorientándome más a cada momento. Revisé el código que instanciaba el ripmime en el fuente del simscan, y finalmente dí con esta línea:

/* fork ripmime */
switch(pid = vfork()) {
case -1:
return(-1);
case 0:
close(1);
close(2);
execl(RIPMIME, "ripmime", "--disable-qmail-bounce",
"-i", message_name, "-d", NULL );
_exit(-1);
}

Me llamó la atención el argumento pasado al ripmime durante el fork, --disable-qmail-bounce, ya que no recordaba haberlo visto en la ayuda del mismo, así que revisé bien el fuente del ripmime y me dí cuenta de que dicho argumento no existía en la versión que estaba usando(!)...

Comenté el argumento en la invocación del ripmime, recompilé el simscan, lo instalé y cuando intenté enviar el mensaje de correo, ¡funcionó todo a la perfección!

Ahí el problema se hizo obvio finalmente.

Revisé bien y me dí cuenta de que la versión de ripmime que estaba utilizando era la 1.3.0.9, así que busqué nuevamente con más tranquilidad y encontré la última versión disponible, la 1.4.0.9. Esta versión SI tiene el argumento anterior, y la invocación del ripmime con dicho parámetro funciona. Le había errado de versión al descargarlo, por un dígito.

Simplemente, el error fué bajar una versión de ripmime vieja, que no tenía el argumento que simscan le pasaba cuando lo invocaba.

Final feliz, pero luego de un buen rato de "entretenido" debugging...

¿Moraleja?: Revisá bien lo que bajás para compilar. Seguro ya te lo habían dicho, pero no viene mal que lo recuerdes de vez en cuando...

Happy hacking!

No hay comentarios:

 
Gustavo Castro

Crea tu insignia