Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSM packaging #106

Merged
merged 19 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dist/**
*.pyc
*.tar.gz
tap-windows-*.exe
tap-windows-*.msm

# builttap.py-generated files
src/config.h
Expand All @@ -16,4 +17,8 @@ src/Release
src/Debug
src/x64
src/arm64
src/smvbuild.log
src/smvstats.txt
src/tap0901.DVL.XML
.vs
*.vcxproj.user
9 changes: 5 additions & 4 deletions COPYING
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ tap-windows6 license
The source and object code of the tap-windows6 project
is Copyright (C) 2002-2014 OpenVPN Technologies, Inc. The
NSIS installer is Copyright (C) 2014 OpenVPN Technologies,
Inc. and (C) 2012 Alon Bar-Lev. Both are released under the
GPL version 2. See COPYRIGHT.GPL for the full GPL license.
The licensors also make the following statement borrowed
from the SPICE project:
Inc. and (C) 2012 Alon Bar-Lev. The installer.dll MSI helper
is Copyright (C) 2018-2019 WireGuard LLC. All are released
under the GPL version 2. See COPYRIGHT.GPL for the full GPL
license. The licensors also make the following statement
borrowed from the SPICE project:

With respect to binaries built using the Microsoft(R)
Windows Driver Kit (WDK), GPLv2 does not extend to any code
Expand Down
107 changes: 81 additions & 26 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The prerequisites for building are:
- Git (not strictly required, but useful for running commands using bundled bash shell)
- MakeNSIS (optional)
- Prebuilt tapinstall.exe binaries (optional)
- Visual Studio 2019 and WiX Toolset for MSM packaging (optional)

Make sure you add Python's install directory (usually c:\\python27) to the PATH
environment variable.
Expand All @@ -44,6 +45,7 @@ View build script options::
--sdk=SDK SDK to use for building: ewdk or wdk, default=ewdk
--sign sign the driver files
-p, --package generate an NSIS installer from the compiled files
-m, --package-msm generate a MSM installer from the compiled files
--cert=CERT Common name of code signing certificate,
default=openvpn
--certfile=CERTFILE Path to the code signing certificate
Expand All @@ -68,17 +70,17 @@ Building tapinstall (optional)
------------------------------

The easiest way to build tapinstall is to clone the Microsoft driver samples
and copy the source for devcon.exe into the tap-windows6 tree. Using PowerShell:
::
git clone https://github.com/Microsoft/Windows-driver-samples
Copy-Item -Recurse Windows-driver-samples/setup/devcon tap-windows6
cd tap-windows6
python.exe buildtap.py -b --ti=devcon
and copy the source for devcon.exe into the tap-windows6 tree. Using PowerShell::

$ git clone https://github.com/Microsoft/Windows-driver-samples
$ Copy-Item -Recurse Windows-driver-samples/setup/devcon tap-windows6
$ cd tap-windows6
$ python.exe buildtap.py -b --ti=devcon

The build system also supports reuse of pre-built tapinstall.exe executables.
To make sure the buildsystem finds the executables, create the following
directory structure under tap-windows6 directory:
::
directory structure under tap-windows6 directory::

devcon
├── Release
│ └── devcon.exe
Expand Down Expand Up @@ -130,9 +132,8 @@ The recommended procedure is to use pre-built, cross-signed devcon.exe and use
the WDK-generated key for signing the driver.

First setup the directory with prebuilt devcon as described above.
Then run the build with the --hlk option:
Then run the build with the --hlk option::

::
$ python.exe buildtap.py -c -b --ti=devcon-prebuilt --hlk

Release signing
Expand All @@ -157,33 +158,33 @@ run as Administrator; according to Microsoft documentation Inf2Cat, which
Cross-Sign.ps1 uses to create (unsigned) catalog files, needs to run with
administrator privileges.

First produce cross-signed drivers and installers (Windows 7/8/8.1/Server 2012r2):
::
$ python.exe buildtap.py -c -b --ti=devcon
sign\Cross-Sign.ps1 -SourceDir dist -Force
python.exe buildtap.py -p --ti=devcon
$ Get-Item tap-windows*.exe|sign\Sign-File.ps1
First produce cross-signed drivers and installers (Windows 7/8/8.1/Server 2012r2)::

$ python.exe buildtap.py -c -b --ti=devcon
$ sign\Cross-Sign.ps1 -SourceDir dist -Force
$ python.exe buildtap.py -p --ti=devcon
$ Get-Item tap-windows*.exe|sign\Sign-File.ps1

Note that the "-Force" option for Cross-Sign.ps1 is *required* except in the
unlikely case you're appending a signature.

Next produce a driver submission cabinet files for attestation signing:
::
$ sign\Create-DriverSubmission.ps1
$ Get-ChildItem -Path disk1|sign\Sign-File.ps1
Next produce a driver submission cabinet files for attestation signing::

$ sign\Create-DriverSubmission.ps1
$ Get-ChildItem -Path disk1|sign\Sign-File.ps1

Three architecture-specific (i386, amd64, arm64) cabinet files are created.
Submit these to Windows Dev Center for attestation signing. Take care to only
request signatures applicable for each architecture.

After downloading the attestation-signed drivers as zip files put them into
a temporary directory under the tap-windows6 directory. Then extract the drivers
into the "dist" directory, produce an installer and sign it:
::
$ cd tap-windows6
$ Get-ChildItem -Path tempdir -Filter "*.zip"|sign\Extract-DriverSubmission.ps1
$ python.exe buildtap.py -p --ti=devcon
$ Get-Item tap-windows*.exe|sign\Sign-File.ps1
into the "dist" directory, produce an installer and sign it::

$ cd tap-windows6
$ Get-ChildItem -Path tempdir -Filter "*.zip"|sign\Extract-DriverSubmission.ps1
$ python.exe buildtap.py -p --ti=devcon
$ Get-Item tap-windows*.exe|sign\Sign-File.ps1

Note that these steps will fail unless cross-signed tapinstall.exe is present
in each architecture-specific directory (i386, amd64, arm64) under the "dist"
Expand All @@ -210,6 +211,60 @@ any attempt to timestamp the driver will fail. For this reason configure your
outbound proxy server before starting the build. Note that the command prompt
also needs to be restarted to make use of new proxy settings.

MSM packaging
-------------

In order to build the MSM packages build and sign the driver first:

- Build the TAP driver with buildtap.py and "-b" flag.
- EV-sign the drivers
- WHQL/Attestation-sign the drivers

Place the signed drivers in a directory structure under tap-windows6
directory. Each platform directory should contain the EV-signed driver with a
"win10" subdirectory containing WHQL/Attestation signed driver for that
platform::

dist
├── amd64
│ ├── win10
│ │ ├── OemVista.inf
│ │ ├── tap0901.cat
│ │ └── tap0901.sys
│ ├── OemVista.inf
│ ├── tap0901.cat
│ └── tap0901.sys
├── arm64
│ ├── win10
│ │ ├── OemVista.inf
│ │ ├── tap0901.cat
│ │ └── tap0901.sys
│ └── (Note: EV-signed driver for arm64 is not used.)
└── i386
├── win10
│ ├── OemVista.inf
│ ├── tap0901.cat
│ └── tap0901.sys
├── OemVista.inf
├── tap0901.cat
└── tap0901.sys

Building MSM packages requires Visual Studio 2019 (EWDK is not sufficient) and
the WiX Toolset installed. In a Developer Command Prompt for Visual Studio
2019, run::

$ python buildtap.py -m --sdk=wdk

This will compile the installer.dll file with embedded drivers and package it
as a platform-dependent tap-windows-<version>-<platform>.msm files.

As the WiX Toolset does not support the arm64 platform yet, only amd64 and
i386 MSM files are built.

Optional: Consider EV-signing the MSM packages before deploying them. Thou,
MSM signature is ignored when merging MSM into MSI package, users get a choice
to validate the integrity of the downloaded MSM packages manually.

License
-------

Expand Down
19 changes: 19 additions & 0 deletions buildtap.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def __init__(self, opt):
raise ValueError("source directory undefined")
self.top = os.path.realpath(opt.src) # top-level dir
self.src = os.path.join(self.top, 'src') # src/openvpn dir
self.msm = os.path.join(self.top, 'msm') # msm dir
if opt.tapinstall:
self.top_tapinstall = os.path.realpath(opt.tapinstall) # tapinstall dir
devcon_project_file = os.path.join(self.top_tapinstall, "devcon.sln")
Expand Down Expand Up @@ -197,6 +198,8 @@ def config_tap(self):
self.preprocess(kv, os.path.join(self.src, "OemVista.inf"))
self.preprocess(kv, os.path.join(self.src, "tap-windows6.vcxproj"))
self.preprocess(kv, os.path.join(self.src, "config.h"))
self.preprocess(kv, os.path.join(self.msm, "config.props"))
self.preprocess(kv, os.path.join(self.msm, "resource.rc"))

# build a "msbuild" file using (E)WDK
def build_ewdk(self, project_file, arch):
Expand Down Expand Up @@ -332,6 +335,18 @@ def package(self):
if self.codesign:
self.sign(installer_file)

# build MSM installer
def package_msm(self):
self.config_tap()
project_file = os.path.join(self.msm, "installer.vcxproj")
for arch in ("i386", "amd64"): #self.architectures_supported
print("***** BUILD MSM arch=%s" % (arch,))
self.run_ewdk('msbuild.exe %s /t:MSM /p:Configuration=%s /p:Platform=%s' % (
project_file,
self.configuration,
self.architecture_platform_map[arch]
))

# like find . | sort
def enum_tree(self, dir):
data = []
Expand Down Expand Up @@ -482,6 +497,8 @@ def sign_verify_ti(self, arch):
default=False, help="sign the driver files")
op.add_option("-p", "--package", action="store_true", dest="package",
help="generate an NSIS installer from the compiled files")
op.add_option("-m", "--package-msm", action="store_true", dest="package_msm",
help="generate a MSM installer from the compiled files")
op.add_option("--cert", dest="cert", metavar="CERT",
default=cert,
help="Common name of code signing certificate, default=%s" % (cert,))
Expand Down Expand Up @@ -511,3 +528,5 @@ def sign_verify_ti(self, arch):
btw.build()
if opt.package:
btw.package()
if opt.package_msm:
btw.package_msm()
6 changes: 6 additions & 0 deletions msm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/ARM64
/Debug
/Release
/x64
/config.props
/resource.rc
28 changes: 28 additions & 0 deletions msm/config.props.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-License-Identifier: GPL-2.0

Copyright (C) 2020 Simon Rozman. All Rights Reserved.
-->
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProductName>@PRODUCT_NAME@</ProductName>
<ProductPublisher>@PRODUCT_PUBLISHER@</ProductPublisher>
<ProductVersion>@PRODUCT_VERSION@</ProductVersion>
<ProductVersionResource>@PRODUCT_VERSION_RESOURCE@</ProductVersionResource>
<ProductTapWinComponentId>@PRODUCT_TAP_WIN_COMPONENT_ID@</ProductTapWinComponentId>
<ProductTapWinMajor>@PRODUCT_TAP_WIN_MAJOR@</ProductTapWinMajor>
<ProductTapWinMinor>@PRODUCT_TAP_WIN_MINOR@</ProductTapWinMinor>
<ProductTapWinRevision>@PRODUCT_TAP_WIN_REVISION@</ProductTapWinRevision>
<ProductTapWinBuild>@PRODUCT_TAP_WIN_BUILD@</ProductTapWinBuild>
<ProductTapWinProvider>@PRODUCT_TAP_WIN_PROVIDER@</ProductTapWinProvider>
<ProductTapWinCharacteristics>@PRODUCT_TAP_WIN_CHARACTERISTICS@</ProductTapWinCharacteristics>
<ProductTapWinDeviceDescription>@PRODUCT_TAP_WIN_DEVICE_DESCRIPTION@</ProductTapWinDeviceDescription>
<ProductTapWinReldate>@PRODUCT_TAP_WIN_RELDATE@</ProductTapWinReldate>

<WixCandleFlags>$(WixCandleFlags) -dPRODUCT_NAME="@PRODUCT_NAME@"</WixCandleFlags>
<WixCandleFlags>$(WixCandleFlags) -dPRODUCT_PUBLISHER="@PRODUCT_PUBLISHER@"</WixCandleFlags>
<WixCandleFlags>$(WixCandleFlags) -dPRODUCT_VERSION="@PRODUCT_VERSION@"</WixCandleFlags>
<WixCandleFlags>$(WixCandleFlags) -dPRODUCT_TAP_WIN_COMPONENT_ID="@PRODUCT_TAP_WIN_COMPONENT_ID@"</WixCandleFlags>
</PropertyGroup>
</Project>
21 changes: 21 additions & 0 deletions msm/dllmain.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
*/

#include "pch.h"

BOOL APIENTRY
DllMain(_In_ HMODULE hModule, _In_ DWORD ul_reason_for_call, _In_opt_ LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
ResourceModule = hModule;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
3 changes: 3 additions & 0 deletions msm/exports.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EXPORTS
MsiEvaluate
MsiProcess
21 changes: 21 additions & 0 deletions msm/framework.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>

#include <NTSecAPI.h>
#include <SetupAPI.h>
#include <newdev.h>
#include <Shlwapi.h>
#include <Psapi.h>
#include <sddl.h>
#include <devguid.h>
#include <ndisguid.h>
#include <cfgmgr32.h>
#include <WinCrypt.h>
#include <Msi.h>
#include <MsiQuery.h>

#include <tchar.h>
#include <stdio.h>
Loading