|
Automating Norton AntiVirus Definition Downloads by PHP Script
Written by Tony Bhimani
June 23, 2006
Requirements
*nix based Operating System
PHP 3, 4, 5
PHPMailer
Download the source code: fetchavdefs.tar.gz
I wrote this script for my work over a year ago. Its purpose is to download
the latest Symantec Norton AntiVirus definition file from their website
and store it on our shared Windows drive accessed through Samba. Once
the file is downloaded an email is sent out to all employees with the
link to the file instructing them to install it. Clicking the link will
launch the executable and update Norton with the latest virus definition.
This process may sound familiar and Symantec already has something like
this called Live Update (minus the email notifications and shared drive
part). So why don't we use that instead of the script? The problem is
we have a terribly slow connection and downloading an 11+ meg file sucks
up all the bandwidth. My work is still stuck in the dark ages and isn't
necessarily willing to upgrade our internet connection. You know how companies
are, it's all about the bottom line. Even though everyone complains about
how slow it is nothing is being done about it. Being the proactive person
I am, I wrote this script to fetch the latest virus definition. It runs
via crontab in the morning before anyone gets to work. Although this script
was written to fetch virus definitions you can easily modify it for your
own needs.
Installation
Extract the archive to a directory like /root/scripts/avupdates or somewhere
else of your choice. You'll need to edit fetchavdefs.php and change some
variables that are at the top of the PHP script. They're listed below.
$defFileDest => destination directory where the file will be moved
to after it's downloaded
$smtpHost => SMTP mail host that notification emails will be relayed
through
$fromEmail => from address for notification emails (typically admin@yourdomain.com)
You'll also need to download a copy of PHPMailer if you'll be using the
email notifications. Be sure to change the path of the require statement
on line 124 of the script. There are also a couple of text files called
lastdef.txt and recipients.txt. The lastdef.txt file holds the name of
the last successfully downloaded virus definition file. It's used to track
if the file has already been downloaded and skips it if it has been. The
recipients.txt file maintains the list of email addresses to send notifications
to (employee email addresses). You'll need to edit this file and enter
each email address on a line of its own. If you don't plan on sending
notifications then comment out the line of code on line 117. The last
step is to chmod 755 the PHP script so it's executable.
Setting up the Cron job
Assuming you installed the script and related files to /root/scripts/avupdates
then you can add a cron job for fetchavdefs.php to /etc/crontab like so.
00 6 * * * root /root/scripts/avupdates/fetchavdefs.php > /dev/null
2>&1
The script will run each morning at 6am and won't send any PHP error
output as emails to root (if you want to receive the emails then remove
the > /dev/null 2>&1).
Summary
Automating a file download can easily be accomplished through a PHP script
like this. Scripts are great for automating trivial tasks like file downloads,
sending email notifications, optimizing databases, exporting data, performing
backups, and many other things. You don't necessarily have to use PHP
to create these scripts. Perl is a powerful language that can also be
used. I like to mix things up and depending on the task I may use one
language over the other. In this case I chose PHP since I'm much more
familiar with it. The automated antivirus file download script highlights
using regular expressions to extract URL's from HTML code, tracking a
past file download and ignoring any duplicate downloads, removing the
old definition files to conserve disk space, and using the PHPMailer package
to send out emails in HTML format.
Source Code:
#!/usr/bin/php -q
<?php
$defFileTemp = "/tmp";
$defFileDest = "/path/Virus Defs"; // edit this: change to path of file storage
$smtpHost = "smtp.yourdomain.com"; // edit this: change your your smtp mail server
$fromEmail = "noreply@youdomain.com"; // edit this: change to from email address
//ini_set("memory_limit", "16M");
// HREF URL Extractor RegExp from http://www.onaje.com/php/article.php4/46
// regular expression <\s*a\s+[^>]*href\s*=\s*[\"']?([^\"' >]+)[\"' >]
$href_regex ="<"; // 1 start of the tag
$href_regex .="\s*"; // 2 zero or more whitespace
$href_regex .="a"; // 3 the a of the <a> tag itself
$href_regex .="\s+"; // 4 one or more whitespace
$href_regex .="[^>]*"; // 5 zero or more of any character that is _not_ the end of the tag
$href_regex .="href"; // 6 the href bit of the tag
$href_regex .="\s*"; // 7 zero or more whitespace
$href_regex .="="; // 8 the = of the tag
$href_regex .="\s*"; // 9 zero or more whitespace
$href_regex .="[\"']?"; // 10 none or one of " or '
$href_regex .="("; // 11 opening parenthesis, start of the bit we want to capture
$href_regex .="[^\"' >]+"; // 12 one or more of any character _except_ our closing characters
$href_regex .=")"; // 13 closing parenthesis, end of the bit we want to capture
$href_regex .="[\"' >]"; // 14 closing chartacters of the bit we want to capture
$regex = "/"; // regex start delimiter
$regex .= $href_regex; //
$regex .= "/"; // regex end delimiter
$regex .= "i"; // Pattern Modifier - makes regex case insensative
$regex .= "s"; // Pattern Modifier - makes a dot metacharater in the pattern
// match all characters, including newlines
$regex .= "U"; // Pattern Modifier - makes the regex ungready
// get the last file we nabbed (AV)
$cwd = getcwd();
$lastDefFile = "{$cwd}/lastdef.txt";
if (file_exists($lastDefFile)) {
$handle = fopen($lastDefFile, "r");
while (!feof($handle)) {
$prevDefFile .= fread($handle, 8192);
}
fclose($handle);
}
// get the symantec virus defs content
$handle = fopen("http://securityresponse.symantec.com/avcenter/download/pages/US-N95.html", "r");
$vdefhtml = "";
while (!feof($handle)) {
$vdefhtml .= fread($handle, 8192);
}
fclose($handle);
// grab all the links from the symantec html page
if (preg_match_all($regex, $vdefhtml, $links)) {
// go through all the links looking for the right one
for ($i=0; $i<sizeof($links[1]); $i++) {
// if the url has i32.exe in it, it is the one we are looking for
if (strpos($links[1][$i],"i32.exe") !== false) {
// get the AV definition exe url and file name
$defFileURL = trim($links[1][$i]);
$defFile = basename($defFileURL);
break;
}
}
// if the def file from symantec's html code and the local file match
// then exit since we already grabbed that file
if ($prevDefFile == $defFile) {
exit;
} else {
// if the def just happens to exist, delete it
$tmpfile = "{$defFileTemp}/{$defFile}";
if (file_exists($tmpfile)) {
if (unlink($tmpfile) == false) { die("ERROR: failed to delete $tmpfile"); }
}
// download the AV definition exe file
$handle1 = @fopen($defFileURL, "rb");
if (!$handle1) { die("ERROR: failed to open $defFileURL"); }
$handle2 = @fopen($tmpfile, "w+b");
if (!$handle2) { die("ERROR: failed to open $tmpfile"); }
while (!feof($handle1)) {
// read the remote file
$avExeFileChunk = fread($handle1, 8192);
// write the file chunk to the hard drive
fwrite($handle2, $avExeFileChunk);
}
// close the output file and input file
fclose($handle2);
fclose($handle1);
// move the av def exe to the shared location
$tmpfile = "{$defFileTemp}/{$defFile}";
$newfile = "{$defFileDest}/{$defFile}";
if (file_exists($newfile)) {
unlink($newfile);
rename($tmpfile, $newfile);
} else {
rename($tmpfile, $newfile);
}
// kill the old av file to conserve space
if ($prevDefFile != "") {
$oldfile = "{$defFileDest}/{$prevDefFile}";
unlink($oldfile);
}
// update the last file downloaded file (AV)
$handle = fopen($lastDefFile, "w+");
fwrite($handle, $defFile);
fclose($handle);
// shoot out an email to everyone
// (comment out the line below if you don't want to send notifications)
sendDefAlertEmail();
}
}
function sendDefAlertEmail() {
global $defFile;
// include the mailer script (edit this to your location of PHPMailer)
require("phpmailer/class.phpmailer.php");
$mail = new PHPMailer();
$cwd = getcwd();
$rcptFile = "{$cwd}/recipients.txt";
// load all recipients from text file
if (file_exists($rcptFile)) {
$recipients = file($rcptFile);
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = $smtpHost; // specify main and backup server
// $mail->SMTPAuth = true; // turn on SMTP authentication
// $mail->Username = ""; // SMTP username
// $mail->Password = ""; // SMTP password
$mail->From = $fromEmail;
$mail->FromName = "";
// build recipient list
for ($i=0; $i<sizeof($recipients); $i++) { // add the to address(es)
$mailto_address = trim($recipients[$i]);
if ($mailto_address != "") { $mail->AddAddress($mailto_address); }
}
// set some vars
$mail->IsHTML(true);
// $mail->WordWrap = 100; // set word wrap to 100 characters
$mail->Subject = "Employees: Update Your Anti-Virus Definition";
$mail->Body =
"
<html>
<head>
<title>Employees: Update Your Anti-Virus Definition</title>
</head>
<body>
<font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">
<p>To: All Employees</p>
<p>A new Anti-Virus definition is available.<br>
Please install this <strong>ASAP</strong> to keep your virus protection up to
date.</p>
<p>Click on this link <a href=\"Z:\\Virus Defs\\".$defFile."\">Z:\Virus Defs\\".$defFile."</a>
to start the installation.</p>
<p><u>Instructions</u><br>
1. Click the link above to start the virus definition update<br>
2. Click the <strong>OPEN</strong> button to download the virus definition update<br>
3. If prompted, click <strong>YES</strong> to the security warning window<br>
4. Click <strong>YES</strong> to the SARC Intelligent Updater window<br>
5. Click <strong>OK</strong> to complete the update</p>
<p><strong><font color=\"#FF0000\">Please be patient throughout the installation process.</font></strong></p>
<p>Thank you,</p>
<p>The Management</p>
</font>
</body>
</html>
";
if(!$mail->Send()) {
die("The message could not be sent.\nMailer Error: ".$mail->ErrorInfo);
}
// clean up
$mail->ClearAllRecipients();
$mail->SmtpClose();
} else {
die("ERROR: Recipients file could not be found");
}
}
?>
|
This page has been viewed 4,096 times |
|