fusioninventory / fusioninventory-agent

FusionInventory Agent
http://fusioninventory.org/
GNU General Public License v2.0
252 stars 125 forks source link

Office edition doesn't match it's serial number #896

Open eduardomozart opened 3 years ago

eduardomozart commented 3 years ago

Hello,

I'm using GLPI 9.5.4 with FusionInventory 9.5.0+2.0 and FusionInventory Agent 2.6.

When executing a Inventory task into a computer, it's returning the complete and correct Serial Number from the Office installed into the machine, but the Edition doesn't match the installed Office version. E.g. We have Office 2010 Home and Business installed and when typing the Serial Number into 'The Ultimate PID Checker', it detects the Office 2010 Home and Business edition correctly, but FusionInventory Agent reports "Office 2010 Professional" (screenshots below).

2021-02-10 17_10_15-GLPI - Computers - 38

2021-02-10 17_17_48-The Ultimate PID Checker

I'm not sure, but I believe that the Office 2003 and 2007 editions are also being reported with wrong edition. It's being detected even if these Office editions aren't installed anymore into the machine (it's a good thing that it's being reported anyway, I guess).

g-bougard commented 3 years ago

Hi @coldscientist thank you for the reporting. Can you check the registry under: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/Registration and HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/Office/Registration ?

There FULLNAME ans NAME are set from "ProductName", "ConvertToEdition", "ProductNameNonQualified" or "ProductNameVersion". Do you see something weird in that values ? Do you see the expected name in another value ? Can you share a registry export of that keys obfuscating all sensible datas ?

eduardomozart commented 3 years ago

Hello @g-bougard, here I am again.

Sorry for the late reply. I was debugging this issue and could find two main scripts that does the inventory of the Microsoft Office: OfficePack from OCS Inventory NG and ROIScan from Microsoft. ROIScan is the script that can inventory extensive information about Microsoft Office, OfficePack from OCS Inventory does a inventory similar to the one coded into FusionInventory Agent.

I noticed that even OfficePack from OCS Inventory and ProduKey from NirSoft reports the Name of the Office edition wrong. OfficePack reports it wrong because it's value is based into the values of "ProductName" and "ConvertToEdition" from HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration for Office editions that aren't installed into the system anymore, but it should be avoided because these values doesn't really matches the edition of the Microsoft Office installed into the machine.

I created a Pull Request into OfficePack from OCS Inventory - https://github.com/PluginsOCSInventory-NG/officepack/pull/69/files - that documenters most of my findings about this issue. I found out that the most reliable way to detect the Microsoft Office edition (according to Microsoft documentation, that's available into the header of the "msofficekey.vbs" script from the pull request for each Microsoft Office version) is through the Office's ProductCode.

E.g. As stated into my screenshot above, the value "ConvertToEdition" value from "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Registration{90140000-003D-0000-0000-0000000FF1CE}" key returns "Microsoft Office Professional 2010", when in fact the Office edition installed into the machine is "Microsoft Office Home and Business 2010". I tweaked the "msofficekey.vbs" script from OCS Inventory NG a bit and now the script parses the edition based on the GUID of the key that contains the "DigitalProductID" binary value. E.g. Office 2003 "DigitalProductID" value is stored into [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\11.0\Registration{90110416-6000-11D3-8CFE-0150048383C9}] key, so now the codes uses the Product GUID (90110416-6000-11D3-8CFE-0150048383C9) to properly detects the Office edition (based on Microsoft Documentation - the Microsoft documentation link with it's editions well-known GUIDs is available at the header of this script) instead of relying into "ProductName" and "ConvertToEdition" values.

Now the "msofficekey.vbs" script uses a different approach to detect the Office 2010 edition, because for OEMs and FPPs, Microsoft distributed a single ProductCode "003D", reported as "Office 2010 Single Image". It's an edition of Office bundled by OEMs for distribution with newer PCs and Office 2010 owners that bought Microsoft Office as a bootleg (FPP). The Office 2010 Single Image edition allows you to easily convert your Office 2010 after the trial period is over, e.g. the FPP edition of Office 2010 Home and Business have a 30-day trial of Office 2010 Professional, and you can easily enable the Professional features by typing the serial number of this edition of Office. But this "universal" approach has it's caveat, as it shares the same ProductCode for multiple Office editions. So now the "msofficekey.vbs" script parses the "DigitalProductID" from "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration" key to extract it's Office SKU (e.g. "HomeBusinessR" for Microsoft Office 2010 H&B), and compares it with a "Select Case" for well-known SKUs to properly detects the edition of the Office installed into the machine.

Sadly my knowledge about Perl is pretty limited so I can understand it when I read through FusionInventory Agent source code but I didn't really know how to write code into it, it's pretty similar to Python though, but I didn't have much knowledge about Python neither. So I decided to code my findings into "OfficePack" from OCS Inventory NG, so I believe it turns more easier to understand and porting it into FusionInventory-Agent source code. Sadly I can't share my HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration key because it's been using valid serial numbers, but I can test any changes into FusionInventory-Agent source code before they being commited into the main branch.

Now I would like to talk about the "SoftwareLicensingProduct" and "OfficeSoftwareProtectionProduct" WMI classes that we were talking about earlier into the issue #901 (here's a recap):

The SoftwareLicensingProduct WMI class is available only into Windows 7 and higher, but the OfficeSoftwareProtectionProduct WMI class is available into Windows Vista/XP and allows you to get Office keys. The ROIScan (an official microsoft script toolkit) checks for Office subscriptions through SoftwareLicensingProduct WMI class if Windows > 7 and OfficeSoftwareProtectionProduct WMI class if Windows < 7, as can be seen here: https://gist.github.com/joerodgers/b1c6ec34801917d4ec4a700491f8ace3

OSPP.vbs that is embeded into Microsoft Office also uses a similar approach: https://stackoverflow.com/questions/55485073/how-to-programmatically-distinguish-excel-2019-from-2016?rq=1

I searched through the FusionInventory-Agent repository but couldn't find any reference to the OfficeSoftwareProtectionProduct WMI class, maybe it could be added into the source code next to SoftwareLicensingProduct WMI class. I can test this feature if it's added into FusionInventory Agent source code.

I decided that I wouldn't query the "SoftwareLicensingProduct" and "OfficeSoftwareProtectionProduct" WMI classes directly similar to the approach of StackOverflow link above and queried them through OSPP.vbs instead because I didn't want to do a major code change into "msofficekey.vbs" script.

I noticed that Windows XP and Windows Vista machines aren't reporting the Office serial number into the head of "Software" tab (as the first screenshot of this issue). At first, I believe that Windows Vista machine aren't reporting it's Office serial number because there's the issue #901 that we're debugging that Windows Vista clients aren't inventorying 32-bit software. But I noticed that Windows XP machines aren't reporting the Office serial number into GLPI neither.

The Windows XP machines at my environment have Office 2007 installed into them and it's serial number aren't being reported into GLPI. I know that Windows XP isn't a official supported platform anymore and I can live with it.

But the same happens with our Windows Vista machines, that have Office 2007 and Office 2010 installed into them. During our discussion into the issue #901 (see the recap above), I could see into the FusionInventory Agent logs that it queries the "SoftwareLicensingProduct" WMI class but the "OfficeSoftwareProtectionProduct" doesn't. It's a WMI class available into Windows XP/Vista that allows enumerates Office 2007 and 2010 information. I believe it would be interesting querying this class along with the "SoftwareLicensingProduct" WMI class to retrieve Office information.

Here's the ROIScan log and "SoftwareLicensingProduct" and "OfficeSoftwareProtectionProduct" WMI class output from one of my machines with Windows Vista with Office 2010 product installed:

C051_ROIScan.log

OfficeSoftwareProtectionProduct.txt

SoftwareLicensingProduct.txt

I know what you might be thinking: "I will not commit code into FusionInventory Agent to support legacy software", okay, I can feel your pain and I get your point. But let's talk about existing code into FusionInventory Agent. Why the sub _scanOfficeLicences isn't being called if the key HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration exists into Windows XP/Vista? I exported the "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration" from Windows XP machine and imported it into my Windows 10 machine, and when running the FusionInventory Agent, it's reporting the Office serial number from these Office editions even if Office isn't installed into the machine. The same should be happening with Windows XP/Vista machines, because this method doesn't rely on any WMI class, but FusionInventory Agent into Windows XP/Vista isn't reporting any Office serial. The Office software shows up into the software list from "Software" tab, but it's Office serial number isn't being queried from the registry.

In fact, for older version of Office (2013 and older), querying the "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Office/XX.X/Registration" is a best approach than querying the "SoftwareLicensingProduct" and "OfficeSoftwareProtectionProduct" WMI classes because these classes returns only partial Office serial number and there's no Office edition friendly name (e.g. FusionInventory Agent reports Office 2019 as "Office 19, RETAIL channel" without any information about it's edition, it's only possible to know the edition installed querying the software list from "Software" tab). I tweaked the code of "msofficekey.vbs" so it uses the "DisplayName" of the Uninstall key for Office 2019, making it easier detect the Office edition installed into the computer.