{"id":280,"date":"2015-11-23T14:43:12","date_gmt":"2015-11-23T13:43:12","guid":{"rendered":"http:\/\/www.alvaromarin.com\/?p=280"},"modified":"2015-11-23T14:43:12","modified_gmt":"2015-11-23T13:43:12","slug":"bug-de-scan-messages-en-mailscanner","status":"publish","type":"post","link":"http:\/\/www.alvaromarin.com\/2015\/11\/23\/bug-de-scan-messages-en-mailscanner\/","title":{"rendered":"Bug de Scan Messages en MailScanner"},"content":{"rendered":"
Unas de las cosas que m\u00e1s gustan de MailScanner es la feature<\/em> de que cada una de las directivas de configuraci\u00f3n, en su gran mayor\u00eda, pueden ser un archivo de reglas o una llamada a una funci\u00f3n. Esto permite que para cada configuraci\u00f3n t\u00edpica de un sistema antispam pueda diferenciarse en base a cuenta origen\/destino, IP origen, dominio origen\/destino…etc, lo cu\u00e1l, permite la personalizaci\u00f3n absoluta del sistema.<\/p>\n Por ejemplo, a la hora de decidir si un mensaje va a ser escaneado o no, en vez de tener un valor de \u00abyes\u00bb o \u00abno\u00bb para la directiva de configuraci\u00f3n que lo controla, que se aplicar\u00eda a todos los mensajes, puede hacerse mediante un archivo de reglas externo:<\/p>\n donde se establecer\u00e1n las reglas que se deseen, por ejemplo:<\/p>\n evitando que se escaneen los mensajes de un determinado FROM, de una determinada IP o de un conjunto de IPs que cumplan la expresi\u00f3n regular. Con el resto de mensajes, se har\u00e1 lo que el \u00abdefault\u00bb diga, en este caso, \u00abyes\u00bb (escanearse).<\/p>\n <\/p>\n La otra opci\u00f3n es tener una llamada a una funci\u00f3n, por ejemplo:<\/p>\n lo que provoca que la configuraci\u00f3n de dicha directiva se consulte ejecutando dicha funci\u00f3n. Estas funciones suelen contener un c\u00f3digo base de inicio, un c\u00f3digo principal y la finalizaci\u00f3n de la funci\u00f3n, como el que sigue:<\/p>\n Reiniciando el servicio de MailScanner, cuando llega un mensaje, se muestra esto en los logs:<\/p>\n Como se puede ver, hay 2 llamadas a nuestra funci\u00f3n ScanMsgs para un mismo mensaje, algo que no deber\u00eda ser as\u00ed.<\/p>\n Debugeando<\/em> c\u00f3digo, se ve c\u00f3mo MessageBatch.pm (el escaneo de mensajes en MailScanner se realiza por procesos batch<\/em> que agrupan un n\u00famero determinado de ellos y los procesan) llama a la funci\u00f3n CreateBatch() de Postfix.pm (en el caso de usar Postfix como MTA); hecho esto, se llama al constructor de Message.pm (cada batch<\/em> contiene mensajes que necesitan de su constructor) que contiene, entre otras cosas, lo siguiente:<\/p>\n En la primera l\u00ednea se ve la llamada a la funci\u00f3n Value de MailScanner::Config que es una funci\u00f3n que coge el valor de una directiva y calculca el valor que le corresponde, en nuestro caso \u00abscanmail\u00bb; esta funci\u00f3n realiza las operaciones necesarias para calcularla, ya sea leer un archivo de reglas, llamar a funciones creadas…etc. Por tanto, en este punto, ya tendr\u00edamos en $this->{scanmail}<\/em> el valor correspondiente a si un mensaje debe escanearse o no. <\/p>\n El problema viene despu\u00e9s de todo esto, en esa misma funci\u00f3n que coment\u00e1bamos antes, CreateBatch() de Postfix.pm, hay el siguiente c\u00f3digo:<\/p>\n es decir, se vuelve a llamar a la funci\u00f3n Value de MailScanner::Config que ya fue llamada anteriormente, de ah\u00ed la segunda ejecuci\u00f3n que ve\u00edamos en los logs.<\/p>\n La forma de corregir esto es sencilla; ve\u00edamos en el c\u00f3digo anterior que el valor de \u00abscanmail\u00bb ya era calculado y guardado en la variable $this->{scanmail}<\/em>. Este c\u00f3digo del constructor de Message.pm es llamado desde Postfix.pm en l\u00edneas anteriores:<\/p>\n por lo que la variable $newmessage<\/em> tiene ya ese valor. Por tanto, sustituyendo el c\u00f3digo anterior por:<\/p>\n hacemos que la llamada a la funci\u00f3n que consume m\u00e1s recursos (b\u00fasqueda en archivos de reglas, llamada a funciones externas…etc), sea solo una vez, como debe ser.<\/p>\n Ya coment\u00e9 el bug<\/em> en la lista de distribuci\u00f3n, esperemos que para pr\u00f3ximas releases<\/em> est\u00e9 ya corregido, aunque el cambio de c\u00f3digo que indico, es suficiente para subsanarlo.<\/p>\n","protected":false},"excerpt":{"rendered":" Unas de las cosas que m\u00e1s gustan de MailScanner es la feature de que cada una de las directivas de configuraci\u00f3n, en su gran mayor\u00eda, pueden ser un archivo de reglas o una llamada a una funci\u00f3n. Esto permite que … Sigue leyendo Scan Messages = %rules-dir%\/scanmessages.rules<\/code><\/p>\n
From: origen@confiable.com no
\nFrom: 192.168.1.10 no
\nFrom: \/^192\\.168\\.13[4567]\\.\/ no
\nFromOrTo: default yes
\n<\/code><\/p>\nScan Messages = &ScanMsgs<\/code><\/p>\n
package MailScanner::CustomConfig;
\n sub InitScanMsgs {
\n MailScanner::Log::InfoLog(\"Starting ScanMsgs...\");
\n }
\n sub ScanMsgs {
\n my($message) = @_;
\n my $msgid=$message->{id};
\n MailScanner::Log::WarnLog(\"$msgid: ScanMsgs checking.\");
\n return 0;
\n}
\n sub EndScanMsgs {
\n MailScanner::Log::InfoLog(\"Ending ScanMsgs...\");
\n exit;
\n }
\n<\/code><\/p>\nSep 23 17:15:05 MailScanner[22554]: Starting ScanMsgs...
\nSep 23 17:15:05 MailScanner[22554]: 4694D2180A7.AC573: ScanMsgs checking.
\nSep 23 17:15:05 MailScanner[22554]: 4694D2180A7.AC573: ScanMsgs checking.
\nSep 23 17:15:05 MailScanner[22554]: Ending ScanMsgs...<\/code><\/p>\n # Decide if we want to scan this message at all
\n $this->{scanmail} = MailScanner::Config::Value('scanmail', $this);
\n if ($this->{scanmail} =~ \/[12]\/) {
\n $this->{scanmail} = 1;
\n } else {
\n # Make sure it is set to something, and not left as undef.
\n $this->{scanmail} = 0;
\n }
\n if ($this->{scanmail} !~ \/1\/) {
\n $this->{scanvirusonly} = 1;
\n } else {
\n $this->{scanvirusonly} = 0;
\n }
\n<\/code><\/p>\n if (MailScanner::Config::Value(\"scanmail\", $newmessage) =~ \/[12]\/ ||
\n MailScanner::Config::Value(\"virusscan\", $newmessage) =~ \/1\/ ||
\n MailScanner::Config::Value(\"dangerscan\", $newmessage) =~ \/1\/) {
\n<\/code><\/p>\n $newmessage = MailScanner::Message->new($id, $queuedirname, $getipfromheader);<\/code><\/p>\n
\tif ($newmessage->{\"scanmail\"} =~ \/[12]\/ ||
\n\t $newmessage->{\"virusscan\"} =~ \/1\/ ||
\n\t $newmessage->{\"dangerscan\"} =~ \/1\/) {<\/code><\/p>\n