HardwareFingerprint - derekjamescurtis/foss-lock GitHub Wiki
This page is intended to detail the workings of the classes within the HardwareFingerprint namespace.
What is the HardwareFingerprint namespace for?
The namespace contains classes necessary for generating system-unique metrics. In order to do this, the classes poll data from various pieces of hardware within the user's system. As an example, vendor-specific metrics from the processor, the MAC address from the NIC, the system UUID, etc... It's really as simple as that.
Is it cross-platform?
FossLock is, as a project, intended to be cross-platform. Thus it can be implied that the HardwareFingerprint classes are cross-platform as well. The functionality is currently tested on Windows and Linux systems. To be more specific, HardwareFingerprint has been tested on the following operating systems/distributions:
- Windows 7 64-bit (should work on any Windows variant that supports WMI)
- Ubuntu 12.04 Precise Pangolin 64-bit
- Fedora 17 Beefy Miracle 64-bit
- openSUSE 12.1 64-bit
- Debian 6 (squeeze and wheezy, still to be tested on sid) 32 and 64-bit
How does it work?
This question can be answered best by talking about each individual Fingerprint class. Currently there are two classes responsible for getting hardware-specific metrics: WindowsFingerprint and LinuxFingerprint.
WindowsFingerprint
WindowsFingerprint uses Windows Management Instrumentation (WMI) under .NET's System.Management namespace. This method provides a very straightforward and concise way of obtaining metrics from a system's hardware. A general overview of WMI can be found at this MSDN article while the .NET specific implementation details can be found at this MSDN article. Using WMI under .NET guarantees that any variant of Windows that supports the applicable versions of those technologies will be able to utilize the WindowsFingerprint class appropriately.
LinuxFingerprint
By comparison to its Windows counterpart, the LinuxFingerprint class has a lot of issues to contend with.
Under Mono, there is no viable counterpart to WMI that works on Linux systems. By viable counterpart, we mean that there is no library or namespace that provides the same or substantially equivalent functionality. Since that is the case, we're left with calling system binaries which in itself provides several challenges.
The major problem is the availability of any binary on any given Linux distribution. In order to provide the best possible experience, we've taken into account what binaries were most likely to be natively available on an "out-of-the-box" installation. In this way, it then becomes relatively safe for the programmer to make assumptions about the underlying system thus making the overhead of the class smaller. For example, most if not all binaries under GNU coreutils are guaranteed to be available on any given Linux distribution. Therefore, issuing calls to those particular binaries shouldn't cause a problem.
That being said, the reality is that most of the programs that are responsible for polling the hardware-specific metrics don't fall under GNU coreutils. Also, there is no one single natively installed binary that can generate all of the metrics required by LinuxFingerprint in order to maintain functional consistency with its Windows counterpart. For example, even though hwinfo could potentially serve as the entire backend for LinuxFingerprint, it's not actually available on a majority of Linux distributions without having to install it separately through your repository or via source. That factor alone facilitates more complication than necessary on the user's end (something which we're trying to avoid).
Mono provides a facility for forking processes which is provided by the System.Diagnostics namespace: Process and ProcessStartInfo. While these two classes are probably the only reliable way to issue calls to the system, there are some stipulations to using them. First and foremost, these classes are nearly undocumented in the official Mono documentation project which leaves programmers up in the air as to their implementation specifics (which we'll attempt to clear up to some degree here).
ProcessStartInfo provides the facilities to specify which binary to run. The FileName property is where you'll specify the name of the binary while the Arguments property is where you'll specify any flags and additional data for the binary. An issue arises if you need to run multiple binaries using bash featues like pipes. In this case, you need to set the FileName property to bash and set the Arguments property to -c "commands". If this doesn't make sense to you, look at the man pages for bash to see what the -c flag is for. This process would effectively be the same for any other shell and its features (csh, tsch, etc...).
Getting that far solves a deal of problems (especially segregating the required output from a binary) but the only remaining issue is dealing with binaries that require privilege escalation. Most modern Linux distributions, especially those geared toward user friendliness, shy away from having the user create a separate root account and opt instead to simply hide it. In those cases, root doesn't actually have a password and is thus ordinarily inaccessible from commands like su (unless the user is aware enough to assign root a password via sudo). To avoid this, LinuxFingerprint currently relies on sudo via ProcessStartInfo. However, as of the current testing state, it's unclear if one Process validates with sudo if another subsequent Process will have to again (since technically the Processes are not the same) or if sudo will retain the login as it normally does and remain agnostic of the issuing Process so long as it's called within the timeout period.
Here is a list of all binaries that are called by LinuxFingerprint. Utility programs are listed as well.
- bash
- cat
- grep
- sed
- sudo
- ifconfig
- hdparm (Requires root permissions)
If I'm running Linux or Windows under virtualization...
That depends upon your hypervisor. Any testing on a hosted hypervisor (eg. VirtualBox, VMWare) has shown these two classes fail pretty horribly. LinuxFingerprint is guaranteed to not work in this type of environment while WindowsFingerprint isn't able to get most of the data required.
Currently no tests have been done on bare-metal hypervisors (eg. Xen, Citrix, xVM) although it's assumed that if the guest were run with hardware-assisted virtualization (a.k.a. "unmodified guest mode") that most of the functionality would remain the same.