Commit Graph

103 Commits

Author SHA1 Message Date
Simon Rozman
d675646ab8 api: upgrade
Signed-off-by: Simon Rozman <simon@rozman.si>
2021-07-28 20:25:27 +02:00
Simon Rozman
7dffa4be72 vs: move shared configuration to wintun.props and upgrade
Remember to rename wintun.vcxproj.user file in your local working folder
to wintun.props.user manually.

Signed-off-by: Simon Rozman <simon@rozman.si>
2021-07-28 20:22:18 +02:00
Jason A. Donenfeld
899e085a91 api: build with WDK
Makes builds more reproducable, as we can do our next release using the
EWDK, an all-in-one ISO of build tools from Microsoft.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-07-23 20:20:43 +02:00
Jason A. Donenfeld
005af4a9c7 api: use SuggestedInstanceId instead of NetSetupAnticipatedInstanceId
All was well with NetSetupAnticipatedInstanceId, until a bug crept into
recent Windows builds that caused old GUIDs not to be properly removed,
resulting in subsequent adapter creations to fail, because NetSetup
AnticipatedInstanceId considers it fatal when the target GUID
already exists, even if in diminished form.

The initial solution was to detect cruft, and then steal a
TrustedInstaller token and sleuth around the registry cleaning things
up. The horror!

Uncomfortable with this, I reopened IDA and had a look around with fresh
eyes, three years after the original discovery of NetSetupAnticipated
InstanceId. There, I found some interesting behavior in
NetSetupSvcDeviceManager::InstallNetworkInterfaces, which amounts to
something like:

    if (IsSet("RetiredNetCfgInstanceId") {
      if (IsSet("NetSetupAnticipatedInstanceId")
        DeleteAdapter(GetValue("RetiredNetCfgInstanceId"));
      else
        Set("NetSetupAnticipatedInstanceId", GetValue("RetiredNetCfgInstanceId"));
      Delete("RetiredNetCfgInstanceId");
    }
    CreateAdapter = TRUE;
    if (IsSet("NetSetupAnticipatedInstanceId")) {
      Guid = GetValue("NetSetupAnticipatedInstanceId");
      if (AdapterAlreadyExists(Guid))
        CreateAdapter = FALSE;
      else
        SetGuidOfNewAdapter(Guid);
      Delete("NetSetupAnticipatedInstanceId");
    } else if (IsSet("SuggestedInstanceId")) {
      Guid = GetValue("SuggestedInstanceId");
      if (!AdapterAlreadyExists(Guid))
        SetGuidOfNewAdapter(Guid);
      Delete("SuggestedInstanceId");
    }

Thus, one appealing strategy would be to set both NetSetupAnticipated
InstanceId and RetiredInstanceId to the same value, and let the service
handle deleting the old one for us before creating the new one.
However, the cleanup of the old adapter winds up being quasi-
asynchronous, and thus we still wind up in the CreateAdapter = FALSE
case.

So, the remaining strategy is to simply use SuggestedInstanceId instead.
This has the behavior that if there's an adapter already in use, it'll
use a new random GUID. The result is that adapter creation won't fail.

That's not great, but the docs have always made it clear that
"requested" is a best-effort sort of thing. Plus, hopefully the creation
of the new adapter will help nudge the bug a bit and cleanup the old
cruft. In some ways, transitioning from our old strategy of "cudgel the
registry until we get the GUID we want" to "ask politely and accept no
for an answer" is a disappointing regression in functionality. But it
also means we don't need to keep crazy token stealing code around, or
fish around in the registry dangerously. This probably also increases
the likelihood that an adapter will be created during edge cases, which
means fewer errors for users, which could be a good thing. On the
downside, we have the perpetual tensions caused by a system that now
"fails open" instead of "fails closed". But so it goes in Windows land.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-07-09 17:08:28 +02:00
Jason A. Donenfeld
cf6e441ff5 api: log instance id when object file name is empty
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-07-08 03:13:14 +02:00
Jason A. Donenfeld
bf5b170101 api: print correct last error when failing
Prior to the conversion, LastError is ERROR_SUCCESS, so move the logging
to be after the conversion.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-07-08 02:50:57 +02:00
Jason A. Donenfeld
ed2f5cc225 api: don't auto-elevate
There's no longer a need to do this for every API call. This only exists
now for the pnp guid reuse workaround hack.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-06-25 16:18:03 +02:00
Jason A. Donenfeld
479bbdc50a api: only mark GUID as in-use if Status != NotPresent
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-11 19:43:34 +02:00
Jason A. Donenfeld
3c8b92e80e api: use simpler problem status checking
This reworks commit e51b49604b.

Link: https://www.reddit.com/r/WireGuard/comments/n6yocf/unable_to_create_wintun_on_windows_7_laptop_with/
Reported-by: Alirz
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-10 11:23:58 +02:00
Jason A. Donenfeld
1efbd14c2c api: check that GUID is valid before assuming it's in use
ROOT/NET/000X could have been claimed by a different driver, so we want
to double check.

Link: https://lists.zx2c4.com/pipermail/wireguard/2021-May/006716.html
Reported-by: Piotr Sobczak <piotrs@glosol.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-10 11:23:58 +02:00
Jason A. Donenfeld
0c9a87b8a2 api: skip requested GUID if !win10
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-05 11:25:44 +02:00
Jason A. Donenfeld
747ba7121d api: clean up NetSetup2 GUIDs
Recent versions of Windows fail to tidy up, causing issues when reusing
GUIDs. Check to see if a GUID might be orphaned, and forcibly clear out
the registry state if so.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-05 11:17:39 +02:00
Jason A. Donenfeld
e51b49604b api: don't return ERROR_SUCCESS if adapter doesn't come up
Otherwise we fail to remove the zombie adapter, and then the problem
repeats itself. Note that this is part of a larger issue of clearing out
bad GUIDs in NetSetup2 on recent Windows builds

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-05-04 12:20:43 +02:00
Simon Rozman
d35312d33f api: log Windows error message too when creating folder or file fails
Signed-off-by: Simon Rozman <simon@rozman.si>
2021-04-13 15:50:50 -06:00
Simon Rozman
cef7922556 api: elevate to SYSTEM in WintunEnumAdapters()
The WintunEnumAdapters() requires namespace mutex. However,
NamespaceTakePoolMutex() works as SYSTEM user only.

WireGuard is using the WintunEnumAdapters() in its manager service to
cleanup stale adapters. As the WireGuard manager service is running as
SYSTEM, this requirement was not apparent before.

This commit also extends the example project to list its existing
adapters at start.

Signed-off-by: Simon Rozman <simon@rozman.si>
2021-03-08 13:48:29 +01:00
Simon Rozman
bc5cde8916 api: upgrade logging
Log runtime information to quickly check whether the values are sane
when analyzing error logs sent in by users.

Signed-off-by: Simon Rozman <simon@rozman.si>
2021-02-16 04:19:21 +01:00
Simon Rozman
542a281808 api: tighten function parameter code analysis annotations
Signed-off-by: Simon Rozman <simon@rozman.si>
2021-02-04 19:00:17 +01:00
Simon Rozman
7a6bab7f04 api: unify NetCfgInstanceId registry retrieval
Signed-off-by: Simon Rozman <simon@rozman.si>
2021-02-04 18:39:10 +01:00
Jason A. Donenfeld
fb416747dc api: ensure that device object exists before returning from open/create
Some users are seeing errors like this after rebooting from Windows
Update:

2021-01-28 18:39:45.220197: [TUN] Creating Wintun interface
2021-01-28 18:39:49.420116: [TUN] [Wintun] CreateAdapter: Creating adapter
2021-01-28 18:39:53.704007: [TUN] [Wintun] OpenDeviceObject: Failed to connect to adapter: The system cannot find the path specified. (Code 0x00000003)
2021-01-28 18:39:53.704007: [TUN] [Wintun] WintunStartSession: Failed to open adapter device object
2021-01-28 18:39:54.097037: [TUN] Unable to create Wintun interface: Error starting session: The system cannot find the path specified.

It appears that creation of the device object file might happen
asynchronously, so this commit polls for it.

Reported-by: Artem Kuroptev <artem@kuroptev.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-02-03 22:36:41 +01:00
Jason A. Donenfeld
2628412d71 global: bump copyright
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-30 16:45:26 +01:00
Jason A. Donenfeld
49b7692d5b api: use custom devpkey for pool
It seems like the friendly name is still getting reset sometimes. Rather
than swimming upstream, it turns out we can just use a custom devpkey
that, according to msdn, is respected.

https://docs.microsoft.com/en-us/windows-hardware/drivers/install/creating-custom-device-properties

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2021-01-30 16:41:16 +01:00
Jason A. Donenfeld
a9f8b2b764 api: do not make dead gateway detection failures fatal
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-17 16:27:11 +01:00
Simon Rozman
f7c2ea4ded api: retry on ERROR_TRANSACTION_NOT_ACTIVE when disabling dead GW detect
There seems to be a race in the TCP/IP adapter registry key. Sometimes,
the adapter TCP/IP key is created, but setting the value
EnableDeadGWDetect fails with ERROR_TRANSACTION_NOT_ACTIVE.

Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-17 15:30:00 +01:00
Jason A. Donenfeld
fc348f519b api: relax IsPoolMember estimation
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-09 15:34:38 +01:00
Jason A. Donenfeld
0d214d7254 api: do not call UpdateDriverForPlugAndPlayDevicesW
This seems to reset a number of device properties, and our update flow
seems to update old adapters without needing to call this.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-09 15:14:33 +01:00
Jason A. Donenfeld
8ec14e5f6d api: take pool mutex when deleting
This prevents us from racing with driver deletion. Mutexes are
recursive, so we shouldn't deadlock if called from Enum.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-09 13:15:57 +01:00
Jason A. Donenfeld
7c5233a80e api: account for adapter disappearing during deletion
This makes the race less fatal.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-09 13:11:07 +01:00
Jason A. Donenfeld
ed0465b8a7 api: avoid loading version.dll if not used
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-06 10:25:15 +01:00
Jason A. Donenfeld
9f3d466791 api: remove WintunOpenAdapterDeviceObject
Discourage use of kernel interface, which gives us more flexibility if
we ever want to change it.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-05 16:58:43 +01:00
Jason A. Donenfeld
1285b8f528 api: rename WintunGetAdapter to WintunOpenAdapter
"Create" and "Open" natural names for these.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-05 16:58:43 +01:00
Jason A. Donenfeld
c26b16e06f api: CALLBACK_FUNC -> CALLBACK
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-04 16:46:24 +01:00
Jason A. Donenfeld
dc99f96da7 api: rename GetVersion to GetRunningDriverVersion
This makes our intentions a lot more clear, and in case we ever add
other version functions, makes the forward path simpler.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-04 14:53:39 +01:00
Jason A. Donenfeld
5d1efa847f api: use a logging alloc function
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-04 13:21:43 +01:00
Simon Rozman
0a51e26730 api: include the rundll32 helpers the MSVC-typical way
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-04 13:21:42 +01:00
Simon Rozman
552821f59a api: translate NTSTATUS to Win32 error codes
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-04 13:21:42 +01:00
Simon Rozman
f657e6fd27 api: use GetLastError() to report failures like standard Win32
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-04 13:21:42 +01:00
Jason A. Donenfeld
677ba8680f wintun: extract inf driverver at compile time into C header
This requires us to make some insane conversions between INF date,
JavaScript time, and finally Windows file time. The point is to mimic
SystemTimeToFileTime, which is what SpInf.dll's pSetupStringToDriverDate
does on the YYYY-MM-DD from the INF.

The result is that we no longer have to parse an ancient text format in
C at runtime.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 18:29:52 +01:00
Jason A. Donenfeld
90a33d9cc6 api: move undocumented ntdll symbols to ntdll.h
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 15:28:17 +01:00
Jason A. Donenfeld
080b6896e0 api: constify pool argument
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 12:47:26 +01:00
Jason A. Donenfeld
8963f7258e api: remove guid getter
The iphlpapi takes both LUIDs and GUIDs but prefers LUIDs, so exposing
the NET_LUID makes sense. However, we were previously exposing the
configuration GUID, rather than the net GUID, which is confusing, so
just make it all go away.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 12:34:19 +01:00
Jason A. Donenfeld
2af7fbd64a api: use 'open' name since caller must close handle
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 12:31:49 +01:00
Jason A. Donenfeld
7dede73406 api: add pool/driver removal for uninstaller semantics
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 12:27:42 +01:00
Jason A. Donenfeld
64f39cd95d api: only return top two version nibbles
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 11:01:20 +01:00
Simon Rozman
aa6e540811 api: prevent double SetupDiDestroyDriverInfoList calls on error
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-03 10:40:09 +01:00
Jason A. Donenfeld
19d6227c1d api: rundll32: repair token spawning semantics
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 10:34:25 +01:00
Simon Rozman
a73927ea6c api: refactor .inf parsing and check SystemTimeToFileTime for errors
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-03 10:34:23 +01:00
Simon Rozman
77ff03f621 api: simplify IsOurDrvInfoDetail()
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-03 10:34:23 +01:00
Jason A. Donenfeld
1201c9f346 api: ensure more code compiles by using dead code elimination
It'd be nicer to do this via

if (is_defined(HAVE_WHATEVER))

But MSVC won't work with the linux kernel macros for this. Ongoing
research.

Nevertheless, this makes most of the program always pass through the
compiler's type checker, only to have dead code removed later.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 02:25:57 +01:00
Jason A. Donenfeld
353cfa562e api: begin to separate rundll32 jumps
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-03 02:25:20 +01:00
Jason A. Donenfeld
0d7b9c7319 api: free beginning of heap object
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-11-02 23:42:43 +01:00