From e1740b4dad7b9378cd6e0746220838d2a2516b62 Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Mon, 30 Dec 2024 16:29:43 +0100 Subject: [PATCH] fix: Add support for Trellix/McAfee agent as Antivirus on windows --- Changes | 1 + .../Agent/Task/Inventory/Win32/AntiVirus.pm | 52 +++++++++++++++++-- lib/GLPI/Agent/Tools/Win32.pm | 3 +- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index dec4c118f..561b3a8dd 100644 --- a/Changes +++ b/Changes @@ -35,6 +35,7 @@ inventory: * Fix --partial option when used with glpi-agent script * Update getProcesses() API to permit filtering and report processes only in the same namespace to not list containers processes. Refacto inventory module using this API. +* Add support for Trellix/McAfee agent as Antivirus on windows remoteinventory: * Store remote inventory part checksums in dedicated state files and support maintenance diff --git a/lib/GLPI/Agent/Task/Inventory/Win32/AntiVirus.pm b/lib/GLPI/Agent/Task/Inventory/Win32/AntiVirus.pm index 2e62ca1aa..67cbf93af 100644 --- a/lib/GLPI/Agent/Task/Inventory/Win32/AntiVirus.pm +++ b/lib/GLPI/Agent/Task/Inventory/Win32/AntiVirus.pm @@ -6,6 +6,8 @@ use warnings; use parent 'GLPI::Agent::Task::Inventory::Module'; use UNIVERSAL::require; +use File::Spec; +use File::Basename qw(dirname); use GLPI::Agent::Tools; use GLPI::Agent::Tools::Win32; @@ -160,14 +162,26 @@ sub doInventory { # Cortex XDR support name => "Cortex XDR", service => "cyserver", - command => "C:\\Program Files\\Palo Alto Networks\\Traps\\cytool.exe", + path => "C:\\Program Files\\Palo Alto Networks\\Traps", + command => "cytool.exe", func => \&_setCortexInfos, }, { # BitDefender support name => "Bitdefender Endpoint Security", service => "EPSecurityService", - command => "C:\\Program Files\\Bitdefender\\Endpoint Security\\product.console.exe", + path => "C:\\Program Files\\Bitdefender\\Endpoint Security", + command => "product.console.exe", func => \&_setBitdefenderInfos, + }, { + # Trellix/McAfee support + name => "Trellix", + service => "masvc", + path => [ + "C:\\Program Files\\McAfee\\Agent", + "C:\\Program Files (x86)\\McAfee\\Commmon Framework", + ], + command => "CmdAgent.exe", + func => \&_setMcAfeeInfos, }) { my $antivirus; my $service = $services->{$support->{service}} @@ -176,8 +190,26 @@ sub doInventory { $antivirus->{NAME} = $support->{name} || $service->{NAME}; $antivirus->{ENABLED} = $service->{STATUS} =~ /running/i ? 1 : 0; - if (my $cmd = $support->{command}) { - &{$support->{func}}($antivirus, $logger, $cmd) if canRun($cmd); + if ($support->{command}) { + my @path; + if ($service->{PATHNAME}) { + # First use pathname extracted from service PATHNAME + my ($path) = $service->{PATHNAME} =~ /^"/ ? + $service->{PATHNAME} =~ /^"([^"]+)\"/ : + $service->{PATHNAME} =~ /^(\S+)/ ; + push @path, $path if $path; + } + push @path, ref($support->{path}) ? @{$support->{path}} : $support->{path} + if $support->{path}; + my %tried; + foreach my $path (@path) { + next if $tried{$path}; + $tried{$path} = 1; + my $cmd = File::Spec->catfile($path, $support->{command}); + next unless canRun($cmd); + &{$support->{func}}($antivirus, $logger, $cmd); + last; + } } # avoid duplicates @@ -219,7 +251,17 @@ sub _getAntivirusUninstall { } sub _setMcAfeeInfos { - my ($antivirus) = @_; + my ($antivirus, $logger, $command) = @_; + + if ($command) { + my $version = getFirstMatch( + command => "\"$command\" /i", + pattern => qr/^Version: (.*)$/, + logger => $logger + ); + $antivirus->{VERSION} = $version if $version; + $antivirus->{COMPANY} = "Trellix" unless $antivirus->{COMPANY}; + } my %properties = ( BASE_VERSION => [ qw(AVDatVersion AVDatVersionMinor) ], diff --git a/lib/GLPI/Agent/Tools/Win32.pm b/lib/GLPI/Agent/Tools/Win32.pm index 30fafd984..19cec71e7 100644 --- a/lib/GLPI/Agent/Tools/Win32.pm +++ b/lib/GLPI/Agent/Tools/Win32.pm @@ -707,7 +707,7 @@ sub getServices { foreach my $object (getWMIObjects( class => 'Win32_Service', properties => [ qw/ - Name DisplayName Description State + Name DisplayName Description State PathName / ], %params @@ -718,6 +718,7 @@ sub getServices { NAME => $object->{DisplayName}, DESCRIPTION => $object->{Description} // "", STATUS => $object->{State} // "n/a", + PATHNAME => $object->{PathName} // "", }; }