From 904470d9a96142cad355c59fe654f9b9819215ba Mon Sep 17 00:00:00 2001 From: Tess Gauthier Date: Mon, 11 Oct 2021 17:46:32 -0400 Subject: [PATCH] Telemetry (#529) --- contrib/win32/openssh/MicrosoftTelemetry.h | 87 +++++++ contrib/win32/openssh/OpenSSHBuildHelper.psm1 | 55 +++-- contrib/win32/openssh/paths.targets | 2 +- contrib/win32/openssh/sshTelemetry.c | 218 ++++++++++++++++++ contrib/win32/openssh/sshTelemetry.h | 30 +++ contrib/win32/openssh/sshTelemetryInternal.h | 8 + contrib/win32/openssh/win32iocompat.vcxproj | 4 + .../openssh/win32iocompat.vcxproj.filters | 4 + contrib/win32/win32compat/w32-doexec.c | 2 + kex.c | 26 +++ sshconnect.c | 10 + sshconnect2.c | 42 ++++ sshd.c | 8 + 13 files changed, 472 insertions(+), 24 deletions(-) create mode 100644 contrib/win32/openssh/MicrosoftTelemetry.h create mode 100644 contrib/win32/openssh/sshTelemetry.c create mode 100644 contrib/win32/openssh/sshTelemetry.h create mode 100644 contrib/win32/openssh/sshTelemetryInternal.h diff --git a/contrib/win32/openssh/MicrosoftTelemetry.h b/contrib/win32/openssh/MicrosoftTelemetry.h new file mode 100644 index 000000000..b5e6944af --- /dev/null +++ b/contrib/win32/openssh/MicrosoftTelemetry.h @@ -0,0 +1,87 @@ +/* ++ + +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the MIT License. See LICENSE in the project root for license information. + +Module Name: + + TraceLoggingConfig.h + +Abstract: + + Macro definitions used by this project's TraceLogging ETW providers: + + - Configuration macros that select the ETW Provider Groups to be used by + this project. + - Constants for tags that are commonly used in Microsoft's + TraceLogging-based ETW. + + Different versions of this file use different definitions for the + TraceLoggingOption configuration macros. The definitions in this file are + empty. As a result, providers using this configuration file will not join + any ETW Provider Groups and will not be given any special treatment by + group-sensitive ETW listeners. + +Environment: + + User mode or kernel mode. + +--*/ + +#pragma once + +// Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition +// in this file configures the provider as a normal (non-telemetry) provider. +#define TraceLoggingOptionMicrosoftTelemetry() \ + // Empty definition for TraceLoggingOptionMicrosoftTelemetry + +// Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition +// in this file configures the provider as a normal (non-telemetry) provider. +#define TraceLoggingOptionWindowsCoreTelemetry() \ + // Empty definition for TraceLoggingOptionWindowsCoreTelemetry + +// Event privacy tags. Use the PDT macro values for the tag parameter, e.g.: +// TraceLoggingWrite(..., +// TelemetryPrivacyDataTag(PDT_BrowsingHistory | PDT_ProductAndServiceUsage), +// ...); +#define TelemetryPrivacyDataTag(tag) TraceLoggingUInt64((tag), "PartA_PrivTags") +#define PDT_BrowsingHistory 0x0000000000000002u +#define PDT_DeviceConnectivityAndConfiguration 0x0000000000000800u +#define PDT_InkingTypingAndSpeechUtterance 0x0000000000020000u +#define PDT_ProductAndServicePerformance 0x0000000001000000u +#define PDT_ProductAndServiceUsage 0x0000000002000000u +#define PDT_SoftwareSetupAndInventory 0x0000000080000000u + +// Event categories specified via keywords, e.g.: +// TraceLoggingWrite(..., +// TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), +// ...); +#define MICROSOFT_KEYWORD_CRITICAL_DATA 0x0000800000000000 // Bit 47 +#define MICROSOFT_KEYWORD_MEASURES 0x0000400000000000 // Bit 46 +#define MICROSOFT_KEYWORD_TELEMETRY 0x0000200000000000 // Bit 45 +#define MICROSOFT_KEYWORD_RESERVED_44 0x0000100000000000 // Bit 44 (reserved for future assignment) + +// Event categories specified via event tags, e.g.: +// TraceLoggingWrite(..., +// TraceLoggingEventTag(MICROSOFT_EVENTTAG_REALTIME_LATENCY), +// ...); +#define MICROSOFT_EVENTTAG_DROP_USER_IDS 0x00008000 +#define MICROSOFT_EVENTTAG_AGGREGATE 0x00010000 +#define MICROSOFT_EVENTTAG_DROP_PII_EXCEPT_IP 0x00020000 +#define MICROSOFT_EVENTTAG_COSTDEFERRED_LATENCY 0x00040000 +#define MICROSOFT_EVENTTAG_CORE_DATA 0x00080000 +#define MICROSOFT_EVENTTAG_INJECT_XTOKEN 0x00100000 +#define MICROSOFT_EVENTTAG_REALTIME_LATENCY 0x00200000 +#define MICROSOFT_EVENTTAG_NORMAL_LATENCY 0x00400000 +#define MICROSOFT_EVENTTAG_CRITICAL_PERSISTENCE 0x00800000 +#define MICROSOFT_EVENTTAG_NORMAL_PERSISTENCE 0x01000000 +#define MICROSOFT_EVENTTAG_DROP_PII 0x02000000 +#define MICROSOFT_EVENTTAG_HASH_PII 0x04000000 +#define MICROSOFT_EVENTTAG_MARK_PII 0x08000000 + +// Field categories specified via field tags, e.g.: +// TraceLoggingWrite(..., +// TraceLoggingString(szUser, "UserName", "User's name", MICROSOFT_FIELDTAG_HASH_PII), +// ...); +#define MICROSOFT_FIELDTAG_DROP_PII 0x04000000 +#define MICROSOFT_FIELDTAG_HASH_PII 0x08000000 diff --git a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 index 5c9f2f165..a6b66409e 100644 --- a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 +++ b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 @@ -1,4 +1,4 @@ -Set-StrictMode -Version 2.0 +Set-StrictMode -Version 2.0 If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path} Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force @@ -150,6 +150,7 @@ function Start-OpenSSHBootstrap [bool] $silent = -not $script:Verbose Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent + $Win10SDKVerChoco = "10.1.17763.1" $machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE') $newMachineEnvironmentPath = $machinePath @@ -205,26 +206,36 @@ function Start-OpenSSHBootstrap } $vcVars = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat" - $sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs" + $sdkVersion = Get-Windows10SDKVersion + $env:vctargetspath = "${env:ProgramFiles(x86)}\MSBuild\Microsoft.Cpp\v4.0\v140" + + if ($sdkVersion -eq $null) + { + $packageName = "windows-sdk-10.1" + Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..." + choco install $packageName --version=$Win10SDKVerChoco -y --force --limitoutput --execution-timeout 120 2>&1 >> $script:BuildLogFile + } + + if (-not (Test-Path $env:vctargetspath)) + { + Write-BuildMsg -AsInfo -Message "installing visualcpp-build-tools" + choco install visualcpp-build-tools --version 14.0.25420.1 -y --force --limitoutput --execution-timeout 120 2>&1 >> $script:BuildLogFile + } + #use vs2017 build tool if exists if($VS2017Path -ne $null) { - If (-not (Test-Path $sdkPath)) - { - $packageName = "windows-sdk-8.1" - Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..." - choco install $packageName -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile - } + if(-not (Test-Path $VcVars)) { Write-BuildMsg -AsError -ErrorAction Stop -Message "VC++ 2015.3 v140 toolset are not installed." } } - elseIf (($VS2015Path -eq $null) -or (-not (Test-Path $VcVars)) -or (-not (Test-Path $sdkPath))) { + elseIf (($VS2015Path -eq $null) -or (-not (Test-Path $VcVars))) { $packageName = "vcbuildtools" Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..." - choco install $packageName -ia "/InstallSelectableItems VisualCppBuildTools_ATLMFC_SDK;VisualCppBuildTools_NETFX_SDK;Win81SDK_CppBuildSKUV1" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile + choco install $packageName -ia "/InstallSelectableItems VisualCppBuildTools_ATLMFC_SDK;VisualCppBuildTools_NETFX_SDK" -y --force --limitoutput --execution-timeout 120 2>&1 >> $script:BuildLogFile $errorCode = $LASTEXITCODE if ($errorCode -eq 3010) { @@ -272,7 +283,7 @@ function Start-OpenSSHBootstrap { $packageName = "windows-sdk-10.1" Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..." - choco install $packageName --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile + choco install $packageName --version=$Win10SDKVerChoco --force --limitoutput --execution-timeout 120 2>&1 >> $script:BuildLogFile } } @@ -577,6 +588,7 @@ function Start-OpenSSHBuild } Write-BuildMsg -AsInfo -Message "Starting Open SSH build; Build Log: $($script:BuildLogFile)." + Write-BuildMsg -AsInfo -Message "$msbuildCmd $cmdMsg" & "$msbuildCmd" $cmdMsg $errorCode = $LASTEXITCODE @@ -622,20 +634,17 @@ function Get-VS2015BuildToolPath } function Get-Windows10SDKVersion -{ +{ + #Temporary fix - Onecore builds are failing with latest windows 10 SDK (10.0.18362.0) + $requiredSDKVersion = [version]"10.0.17763.0" ## Search for latest windows sdk available on the machine - $windowsSDKPath = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\Lib" - $minSDKVersion = [version]"10.0.14393.0" - $versionsAvailable = @() - #Temporary fix - Onecore builds are failing with latest widows 10 SDK (10.0.18362.0) - $maxSDKVersion = [version]"10.0.17763.0" - $versionsAvailable = Get-ChildItem $windowsSDKPath | ? {$_.Name.StartsWith("10.")} | % {$version = [version]$_.Name; if(($version.CompareTo($minSDKVersion) -ge 0) -and ($version.CompareTo($maxSDKVersion) -le 0)) {$version}} - if(0 -eq $versionsAvailable.count) - { - return $null + $windowsSDKPath = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\bin\$requiredSDKVersion\x86\register_app.vbs" + if (test-path $windowsSDKPath) { + return $requiredSDKVersion + } + else { + return $null } - $versionsAvailable = $versionsAvailable | Sort-Object -Descending - return $versionsAvailable[0] } function Get-BuildLogFile diff --git a/contrib/win32/openssh/paths.targets b/contrib/win32/openssh/paths.targets index 0ab26fb09..74212fb52 100644 --- a/contrib/win32/openssh/paths.targets +++ b/contrib/win32/openssh/paths.targets @@ -18,7 +18,7 @@ $(SolutionDir)\ZLib\bin\arm\ true libcrypto.lib; - 8.1 + 10.0.17763.0 bcrypt.lib;Userenv.lib;Crypt32.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Netapi32.lib;Rpcrt4.lib;ntdll.lib false diff --git a/contrib/win32/openssh/sshTelemetry.c b/contrib/win32/openssh/sshTelemetry.c new file mode 100644 index 000000000..2ebe55c3e --- /dev/null +++ b/contrib/win32/openssh/sshTelemetry.c @@ -0,0 +1,218 @@ +/* +* Author: Tess Gauthier +* +* Copyright(c) 2021 Microsoft Corp. +* All rights reserved +* +* Misc Unix POSIX routine implementations for Windows +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met : +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and / or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +this file defines functions to collect Microsoft Telemetry, +which will only be sent for Windows In-Box releases. +GitHub releases will not send any Telemetry. +*/ + +#include +#include +#include + +#include "sshTelemetry.h" +#include "sshTelemetryInternal.h" + +// {0d986661-0dd7-561a-b15b-fcc1cd46d2bb} +TRACELOGGING_DEFINE_PROVIDER( + g_hProvider1, + "Microsoft.Windows.Win32OpenSSH", + (0x0d986661, 0x0dd7, 0x561a, 0xb1, 0x5b, 0xfc, 0xc1, 0xcd, 0x46, 0xd2, 0xbb), + TraceLoggingOptionMicrosoftTelemetry()); + +void send_auth_telemetry(const int status, const char* auth_type) +{ + /* + registering only needs to be done once per process but + since these functions are used by multiple processes + and we need to unregister so the ETW process knows + not to do any callbacks, registering and unregistering + is done after each tracelogging call for safety + */ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "Auth", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingInt16(status, "success"), + TraceLoggingString(auth_type, "authType") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_encryption_telemetry(const char* direction, + const char* cipher, const char* kex, const char* mac, + const char* comp, const char* host_key, + const char** cproposal, const char** sproposal) +{ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "Encryption", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(direction, "direction"), + TraceLoggingString(cipher, "cipher"), + TraceLoggingString(kex, "kex"), + TraceLoggingString(mac, "mac"), + TraceLoggingString(comp, "compression"), + TraceLoggingString(host_key, "hostKey"), + TraceLoggingString(cproposal[0], "clientProposedKex"), + TraceLoggingString(cproposal[1], "clientProposedHostKeys"), + TraceLoggingString(cproposal[2], "clientProposedCiphersCtos"), + TraceLoggingString(cproposal[3], "clientProposedCiphersStoc"), + TraceLoggingString(cproposal[4], "clientProposedMACsCtos"), + TraceLoggingString(cproposal[5], "clientProposedMACsStoc"), + TraceLoggingString(cproposal[6], "clientProposedCompressionCtos"), + TraceLoggingString(cproposal[7], "clientProposedCompressionStoc"), + TraceLoggingString(sproposal[0], "serverProposedKex"), + TraceLoggingString(sproposal[1], "serverProposedHostKeys"), + TraceLoggingString(sproposal[2], "serverProposedCiphersCtos"), + TraceLoggingString(sproposal[3], "serverProposedCiphersStoc"), + TraceLoggingString(sproposal[4], "serverProposedMACsCtos"), + TraceLoggingString(sproposal[5], "serverProposedMACsCtoc"), + TraceLoggingString(sproposal[6], "serverProposedCompressionCtos"), + TraceLoggingString(sproposal[7], "serverProposedCompressionStoc") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_pubkey_telemetry(const char* pubKeyStatus) +{ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "PublicKey", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(pubKeyStatus, "status") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_shell_telemetry(const int pty, const int shell_type) +{ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "Shell", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingInt16(pty, "PTY"), + TraceLoggingInt16(shell_type, "type") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_pubkey_sign_telemetry(const char* pubKeySignStatus) +{ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "PubkeySigning", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(pubKeySignStatus, "status") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_ssh_connection_telemetry(const char* conn, const char* port) +{ + int isCustomPort = 0; + if (strcmp(port, "22") != 0) { + isCustomPort = 1; + } + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "Connection", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(conn, "status"), + TraceLoggingBool(isCustomPort, "isCustomSSHServerPort") + ); + TraceLoggingUnregister(g_hProvider1); +} + +void send_sshd_config_telemetry(const int num_auth_methods, + const char** auth_methods) +{ + char* auth_buffer = NULL; + if (num_auth_methods == 0) { + auth_buffer = (char*)malloc(5 * sizeof(char)); + strcpy_s(auth_buffer, 5, "none"); + } + else { + // concatenate all the auth methods into a + // single string to pass to tracelogging + size_t buffer_size = (size_t)num_auth_methods; + for (int i = 0; i < num_auth_methods; i++) { + buffer_size += strlen(auth_methods[i]); + } + auth_buffer = (char*)malloc((buffer_size + 1) * sizeof(char)); + auth_buffer[0] = '\0'; + for (int i = 0; i < num_auth_methods; i++) { + strcat_s(auth_buffer, buffer_size, auth_methods[i]); + if (i < num_auth_methods - 1) { + strcat_s(auth_buffer, buffer_size, ","); + } + } + } + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "SSHD", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(auth_buffer, "authMethods") + ); + TraceLoggingUnregister(g_hProvider1); + free(auth_buffer); +} + +void send_ssh_version_telemetry(const char* ssh_version, const char* peer_version, + const char* remote_protocol_supported) +{ + TraceLoggingRegister(g_hProvider1); + TraceLoggingWrite( + g_hProvider1, + "Startup", + TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TraceLoggingString(ssh_version, "ourVersion"), + TraceLoggingString(remote_protocol_supported, "remoteProtocolError"), + TraceLoggingString(peer_version, "peerVersion") + ); + TraceLoggingUnregister(g_hProvider1); +} + diff --git a/contrib/win32/openssh/sshTelemetry.h b/contrib/win32/openssh/sshTelemetry.h new file mode 100644 index 000000000..d63c7df4e --- /dev/null +++ b/contrib/win32/openssh/sshTelemetry.h @@ -0,0 +1,30 @@ +#pragma once + +// sends authentication type and status +void send_auth_telemetry(const int status, const char* auth_type); + +// sends crypto information like cipher, kex, and mac +void send_encryption_telemetry(const char* direction, + const char* cipher, const char* kex, const char* mac, + const char* comp, const char* host_key, + const char** cproposal, const char** sproposal); + +// sends status if using key-based auth +void send_pubkey_telemetry(const char* pubKeyStatus); + +// sends shell configuration and if pty session is used +void send_shell_telemetry(const int pty, const int shell_type); + +// sends signing status if using key-based auth +void send_pubkey_sign_telemetry(const char* pubKeySignStatus); + +// sends connection status from ssh client +void send_ssh_connection_telemetry(const char* conn, const char* port); + +// sends ports and auth methods configured by sshd +void send_sshd_config_telemetry(const int num_auth_methods, + const char** auth_methods); + +// sends version and peer version from ssh & sshd +void send_ssh_version_telemetry(const char* ssh_version, + const char* peer_version, const char* remote_protocol_supported); diff --git a/contrib/win32/openssh/sshTelemetryInternal.h b/contrib/win32/openssh/sshTelemetryInternal.h new file mode 100644 index 000000000..0d04e13aa --- /dev/null +++ b/contrib/win32/openssh/sshTelemetryInternal.h @@ -0,0 +1,8 @@ +#pragma once + +#include // Defines macros used by TraceLoggingProvider.h +#include "TraceLoggingProvider.h" // The native TraceLogging API +#include "MicrosoftTelemetry.h" + +// Forward-declare the g_hProvider1 variable that you will use for tracing +TRACELOGGING_DECLARE_PROVIDER(g_hProvider1); \ No newline at end of file diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj index ad06c481c..910a40595 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj +++ b/contrib/win32/openssh/win32iocompat.vcxproj @@ -312,6 +312,7 @@ + @@ -361,6 +362,9 @@ + + + diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters index 1ed3e9307..c727e636b 100644 --- a/contrib/win32/openssh/win32iocompat.vcxproj.filters +++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters @@ -24,6 +24,7 @@ + @@ -155,6 +156,9 @@ inc + + + diff --git a/contrib/win32/win32compat/w32-doexec.c b/contrib/win32/win32compat/w32-doexec.c index e3a94de74..fdbd8898a 100644 --- a/contrib/win32/win32compat/w32-doexec.c +++ b/contrib/win32/win32compat/w32-doexec.c @@ -38,6 +38,7 @@ #include "servconf.h" #include "pal_doexec.h" #include "misc_internal.h" +#include "sshTelemetry.h" #ifndef SUBSYSTEM_NONE #define SUBSYSTEM_NONE 0 @@ -315,6 +316,7 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) { else shell_command_option_local = "-c"; debug3("shell_option: %s", shell_command_option_local); + send_shell_telemetry(pty, shell_type); if (pty) { fcntl(s->ptyfd, F_SETFD, FD_CLOEXEC); diff --git a/kex.c b/kex.c index 709a0ec63..c01c5228e 100644 --- a/kex.c +++ b/kex.c @@ -42,6 +42,10 @@ #include #endif +#ifdef WINDOWS +#include "sshTelemetry.h" +#endif + #include "ssh.h" #include "ssh2.h" #include "atomicio.h" @@ -965,6 +969,14 @@ kex_choose_conf(struct ssh *ssh) newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "", newkeys->comp.name); +#ifdef WINDOWS + send_encryption_telemetry(ctos ? "ctos" : "stoc", + newkeys->enc.name, kex->name ? kex->name : "(no match)", + authlen == 0 ? newkeys->mac.name : "", + newkeys->comp.name, + kex->hostkey_alg ? kex->hostkey_alg : "(no match)", + my, peer); +#endif } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { @@ -1319,6 +1331,11 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, &remote_major, &remote_minor, remote_version) != 3) { error("Bad remote protocol version identification: '%.100s'", peer_version_string); +#ifdef WINDOWS + send_ssh_version_telemetry(our_version_string, peer_version_string, + "Bad remote protocol version identification"); +#endif + invalid: send_error(ssh, "Invalid SSH identification string."); r = SSH_ERR_INVALID_FORMAT; @@ -1344,6 +1361,10 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, error("Protocol major versions differ: %d vs. %d", PROTOCOL_MAJOR_2, remote_major); send_error(ssh, "Protocol major versions differ."); +#ifdef WINDOWS + send_ssh_version_telemetry(our_version_string, + peer_version_string, "Protocol major versions differ"); +#endif r = SSH_ERR_NO_PROTOCOL_VERSION; goto out; } @@ -1366,6 +1387,11 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, logit("Remote version \"%.100s\" uses unsafe RSA signature " "scheme; disabling use of RSA keys", remote_version); } + +#ifdef WINDOWS + send_ssh_version_telemetry(our_version_string, + peer_version_string, "none"); +#endif /* success */ r = 0; out: diff --git a/sshconnect.c b/sshconnect.c index 087d2c373..1ae69ef4d 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -49,6 +49,10 @@ # include #endif +#ifdef WINDOWS +#include "sshTelemetry.h" +#endif + #include "xmalloc.h" #include "hostfile.h" #include "ssh.h" @@ -543,10 +547,16 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, if (sock == -1) { error("ssh: connect to host %s port %s: %s", host, strport, errno == 0 ? "failure" : strerror(errno)); +#ifdef WINDOWS + send_ssh_connection_telemetry(strerror(errno), strport); +#endif return -1; } debug("Connection established."); +#ifdef WINDOWS + send_ssh_connection_telemetry("Connection established.", strport); +#endif /* Set SO_KEEPALIVE if requested. */ if (want_keepalive && diff --git a/sshconnect2.c b/sshconnect2.c index a53ab95db..a33daa5fa 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -76,6 +76,10 @@ #include "ssh-sk.h" #include "sk-api.h" +#ifdef WINDOWS +#include "sshTelemetry.h" +#endif + #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -487,6 +491,9 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); +#ifdef WINDOWS + send_auth_telemetry(authctxt.success, authctxt.success ? authctxt.method->name : "NULL"); +#endif if (!authctxt.success) fatal("Authentication failed."); debug("Authentication succeeded (%s).", authctxt.method->name); @@ -704,22 +711,45 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) int r; if (authctxt == NULL) +#ifdef WINDOWS + { + send_pubkey_telemetry("input_userauth_pk_ok: no authentication context"); fatal("input_userauth_pk_ok: no authentication context"); + } +#else + fatal("input_userauth_pk_ok: no authentication context"); +#endif if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) +#ifdef WINDOWS + { + send_pubkey_telemetry("failure"); goto done; + } +#else + goto done; +#endif if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { +#ifdef WINDOWS + send_pubkey_telemetry("server sent unknown pkalg"); +#endif debug_f("server sent unknown pkalg %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { +#ifdef WINDOWS + send_pubkey_telemetry("no key from blob"); +#endif debug_r(r, "no key from blob. pkalg %s", pkalg); goto done; } if (key->type != pktype) { +#ifdef WINDOWS + send_pubkey_telemetry("type mistmatch for decoded key"); +#endif error("input_userauth_pk_ok: type mismatch " "for decoded key (received %d, expected %d)", key->type, pktype); @@ -746,6 +776,9 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) } ident = format_identity(id); debug("Server accepts key: %s", ident); +#ifdef WINDOWS + send_pubkey_telemetry("success"); +#endif sent = sign_and_send_pubkey(ssh, id); r = 0; done: @@ -1395,6 +1428,9 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) signature = NULL; if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, id->key)) == NULL) { +#ifdef WINDOWS + send_pubkey_sign_telemetry("no mutual signature supported"); +#endif error_f("no mutual signature supported"); goto out; } @@ -1439,6 +1475,9 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) loc, sshkey_type(id->key), fp); continue; } +#ifdef WINDOWS + send_pubkey_sign_telemetry("signing failed"); +#endif error_fr(r, "signing failed for %s \"%s\"%s", sshkey_type(sign_id->key), sign_id->filename, id->agent_fd != -1 ? " from agent" : ""); @@ -1466,6 +1505,9 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) /* success */ sent = 1; +#ifdef WINDOWS + send_pubkey_sign_telemetry("success"); +#endif out: free(fp); diff --git a/sshd.c b/sshd.c index 915f3a23b..44a1557ca 100644 --- a/sshd.c +++ b/sshd.c @@ -85,6 +85,10 @@ #include #endif +#ifdef WINDOWS +#include "sshTelemetry.h" +#endif + #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" @@ -2226,6 +2230,10 @@ main(int ac, char **av) debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); +#ifdef WINDOWS + send_sshd_config_telemetry(options.num_auth_methods, + options.auth_methods); +#endif /* Store privilege separation user for later use if required. */ privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {