Skip to content

Commit 13c043f

Browse files
add more wolfsshd windows debugging
1 parent af2acf2 commit 13c043f

3 files changed

Lines changed: 154 additions & 6 deletions

File tree

.github/workflows/windows-cert-store-test.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,73 @@ jobs:
12011201
Remove-Item $scriptPath -ErrorAction SilentlyContinue
12021202
Remove-Item $outputFile -ErrorAction SilentlyContinue
12031203
1204+
- name: Dry-run wolfsshd as LocalSystem (cert store diagnostics)
1205+
if: matrix.server_key_source == 'store'
1206+
working-directory: ${{ github.workspace }}\wolfssh
1207+
shell: pwsh
1208+
run: |
1209+
# Run wolfsshd in non-daemon test mode AS LOCALSYSTEM via scheduled
1210+
# task. This captures the exact error that the service would hit.
1211+
$sshdPath = (Get-Content env:SSHD_PATH -ErrorAction SilentlyContinue)
1212+
if (-not $sshdPath -or -not (Test-Path $sshdPath)) {
1213+
Write-Host "Skipping: wolfsshd.exe not found"
1214+
exit 0
1215+
}
1216+
$sshdPathFull = (Resolve-Path $sshdPath).Path
1217+
$configPathFull = (Resolve-Path "sshd_config_test").Path
1218+
$port = ${{env.TEST_PORT}}
1219+
1220+
# Output goes to a temp file that LocalSystem can write to
1221+
$outFile = "$env:TEMP\wolfsshd-localsystem-dryrun.txt"
1222+
1223+
# We wrap the call in cmd /c so stdout+stderr go to the file
1224+
$cmdLine = "`"$sshdPathFull`" -D -t -d -f `"$configPathFull`" -p $port"
1225+
Write-Host "Will run as SYSTEM: $cmdLine"
1226+
1227+
# Create scheduled task to run as SYSTEM
1228+
$taskName = "WolfSSH-DryRunLocalSystem"
1229+
$action = New-ScheduledTaskAction `
1230+
-Execute "cmd.exe" `
1231+
-Argument "/c $cmdLine > `"$outFile`" 2>&1"
1232+
$principal = New-ScheduledTaskPrincipal `
1233+
-UserId "NT AUTHORITY\SYSTEM" `
1234+
-LogonType ServiceAccount -RunLevel Highest
1235+
$settings = New-ScheduledTaskSettingsSet `
1236+
-AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
1237+
1238+
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
1239+
Register-ScheduledTask -TaskName $taskName -Action $action -Principal $principal -Settings $settings | Out-Null
1240+
Start-ScheduledTask -TaskName $taskName
1241+
1242+
# Wait for completion (wolfsshd -t exits quickly)
1243+
$timeout = 30
1244+
$elapsed = 0
1245+
while ($elapsed -lt $timeout) {
1246+
Start-Sleep -Seconds 1
1247+
$elapsed++
1248+
$task = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
1249+
if ($task.State -eq "Ready") { break }
1250+
}
1251+
1252+
# Get exit code
1253+
$taskInfo = Get-ScheduledTaskInfo -TaskName $taskName -ErrorAction SilentlyContinue
1254+
if ($taskInfo) {
1255+
Write-Host "Scheduled task last result: $($taskInfo.LastTaskResult)"
1256+
}
1257+
1258+
# Show output
1259+
Write-Host "=== wolfsshd dry-run as LocalSystem ==="
1260+
if (Test-Path $outFile) {
1261+
Get-Content $outFile
1262+
} else {
1263+
Write-Host "(no output file generated)"
1264+
}
1265+
Write-Host "=== end LocalSystem dry-run ==="
1266+
1267+
# Cleanup
1268+
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
1269+
Remove-Item $outFile -ErrorAction SilentlyContinue
1270+
12041271
- name: Start echoserver with cert store (cert store matrix – more debug logs)
12051272
if: matrix.server_key_source == 'store'
12061273
working-directory: ${{ github.workspace }}\wolfssh
@@ -1393,6 +1460,43 @@ jobs:
13931460
# Clear the env var so cleanup step doesn't try again
13941461
Add-Content -Path $env:GITHUB_ENV -Value "ECHOSERVER_PID="
13951462
1463+
- name: Validate wolfsshd config (non-daemon dry run)
1464+
working-directory: ${{ github.workspace }}\wolfssh
1465+
shell: pwsh
1466+
run: |
1467+
# Run wolfsshd in non-daemon test mode (-D -t -d) to validate
1468+
# config loading and cert store access. This gives us visible
1469+
# stdout/stderr output, unlike the service which logs to
1470+
# OutputDebugString.
1471+
$sshdPath = (Get-Content env:SSHD_PATH)
1472+
if (-not (Test-Path $sshdPath)) {
1473+
Write-Host "Skipping dry-run: wolfsshd.exe not found"
1474+
exit 0
1475+
}
1476+
$configPathFull = (Resolve-Path "sshd_config_test").Path
1477+
$port = ${{env.TEST_PORT}}
1478+
1479+
Write-Host "=== wolfsshd dry-run: $sshdPath -D -t -d -f $configPathFull -p $port ==="
1480+
$proc = Start-Process -FilePath $sshdPath `
1481+
-ArgumentList "-D", "-t", "-d", "-f", $configPathFull, "-p", $port `
1482+
-RedirectStandardOutput "wolfsshd_dryrun_out.txt" `
1483+
-RedirectStandardError "wolfsshd_dryrun_err.txt" `
1484+
-Wait -NoNewWindow -PassThru
1485+
1486+
Write-Host "Exit code: $($proc.ExitCode)"
1487+
Write-Host "=== stdout ==="
1488+
if (Test-Path wolfsshd_dryrun_out.txt) { Get-Content wolfsshd_dryrun_out.txt }
1489+
Write-Host "=== stderr ==="
1490+
if (Test-Path wolfsshd_dryrun_err.txt) { Get-Content wolfsshd_dryrun_err.txt }
1491+
Write-Host "=== end dry-run ==="
1492+
1493+
if ($proc.ExitCode -ne 0) {
1494+
Write-Host "WARNING: wolfsshd dry-run failed (exit $($proc.ExitCode))"
1495+
Write-Host "The service will likely also fail to start."
1496+
} else {
1497+
Write-Host "wolfsshd dry-run succeeded - config is valid"
1498+
}
1499+
13961500
- name: Start wolfSSHd as Windows service
13971501
working-directory: ${{ github.workspace }}\wolfssh
13981502
shell: pwsh
@@ -1501,6 +1605,10 @@ jobs:
15011605
# Create the service with proper binpath
15021606
# Note: sc.exe requires the binPath to have the executable path and arguments
15031607
# The entire command line goes in binPath, with the exe path in quotes
1608+
# We do NOT include -E <log> here because LocalSystem only has RX on
1609+
# the wolfssh directory and cannot create a log file. Debug output
1610+
# from the service goes to OutputDebugString; for visible diagnostics
1611+
# we rely on the "Validate wolfsshd config" dry-run step.
15041612
$binPath = "`"$sshdPathFull`" -f `"$configPathFull`" -p ${{env.TEST_PORT}}"
15051613
Write-Host "Creating service with binpath: $binPath"
15061614

apps/wolfsshd/configuration.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,17 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
406406
{OPT_ACCEPT_ENV, "AcceptEnv"},
407407
{OPT_PROTOCOL, "Protocol"},
408408
{OPT_LOGIN_GRACE_TIME, "LoginGraceTime"},
409-
{OPT_HOST_KEY, "HostKey"},
409+
/* HostKeyStore* must come BEFORE HostKey because the config parser uses
410+
* strncmp with the option-name length. If HostKey (7 chars) appeared
411+
* first, "HostKeyStore …" would match "HostKey" as a prefix. */
410412
#ifdef USE_WINDOWS_API
411413
#ifdef WOLFSSH_CERTS
412414
{OPT_HOST_KEY_STORE, "HostKeyStore"},
413415
{OPT_HOST_KEY_STORE_SUBJECT, "HostKeyStoreSubject"},
414416
{OPT_HOST_KEY_STORE_FLAGS, "HostKeyStoreFlags"},
415417
#endif /* WOLFSSH_CERTS */
416418
#endif /* USE_WINDOWS_API */
419+
{OPT_HOST_KEY, "HostKey"},
417420
{OPT_PASSWORD_AUTH, "PasswordAuthentication"},
418421
{OPT_PORT, "Port"},
419422
{OPT_PERMIT_ROOT, "PermitRootLogin"},
@@ -1096,13 +1099,19 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
10961099
#ifdef USE_WINDOWS_API
10971100
#ifdef WOLFSSH_CERTS
10981101
case OPT_HOST_KEY_STORE:
1102+
wolfSSH_Log(WS_LOG_INFO,
1103+
"[SSHD] Parsed HostKeyStore = '%s'", value);
10991104
ret = SetFileString(&(*conf)->hostKeyStore, value, (*conf)->heap);
11001105
break;
11011106
case OPT_HOST_KEY_STORE_SUBJECT:
1107+
wolfSSH_Log(WS_LOG_INFO,
1108+
"[SSHD] Parsed HostKeyStoreSubject = '%s'", value);
11021109
ret = SetFileString(&(*conf)->hostKeyStoreSubject, value,
11031110
(*conf)->heap);
11041111
break;
11051112
case OPT_HOST_KEY_STORE_FLAGS:
1113+
wolfSSH_Log(WS_LOG_INFO,
1114+
"[SSHD] Parsed HostKeyStoreFlags = '%s'", value);
11061115
ret = SetFileString(&(*conf)->hostKeyStoreFlags, value,
11071116
(*conf)->heap);
11081117
break;

apps/wolfsshd/wolfsshd.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,14 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
359359
char* hostKeyStore = wolfSSHD_ConfigGetHostKeyStore(conf);
360360
char* hostKeyStoreSubject = wolfSSHD_ConfigGetHostKeyStoreSubject(conf);
361361
char* hostKeyStoreFlags = wolfSSHD_ConfigGetHostKeyStoreFlags(conf);
362-
362+
363+
wolfSSH_Log(WS_LOG_INFO,
364+
"[SSHD] Cert store code compiled in. "
365+
"hostKeyStore=%s, hostKeyStoreSubject=%s, hostKeyStoreFlags=%s",
366+
hostKeyStore ? hostKeyStore : "(null)",
367+
hostKeyStoreSubject ? hostKeyStoreSubject : "(null)",
368+
hostKeyStoreFlags ? hostKeyStoreFlags : "(null)");
369+
363370
if (hostKeyStore != NULL && hostKeyStoreSubject != NULL) {
364371
/* Use cert store host key */
365372
wchar_t* wStoreName = NULL;
@@ -401,11 +408,21 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
401408
WFREE(wSubjectName, heap, DYNTYPE_SSHD);
402409
}
403410
} else
411+
#else
412+
wolfSSH_Log(WS_LOG_INFO,
413+
"[SSHD] WOLFSSH_CERTS not defined - cert store support disabled");
404414
#endif /* WOLFSSH_CERTS */
415+
#else
416+
wolfSSH_Log(WS_LOG_INFO,
417+
"[SSHD] USE_WINDOWS_API not defined - cert store support disabled");
405418
#endif /* USE_WINDOWS_API */
406419
{
407420
char* hostKey = wolfSSHD_ConfigGetHostKeyFile(conf);
408421

422+
wolfSSH_Log(WS_LOG_INFO,
423+
"[SSHD] File-based host key path entered. hostKey=%s",
424+
hostKey ? hostKey : "(null)");
425+
409426
if (hostKey == NULL) {
410427
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] No host private key set");
411428
ret = WS_BAD_ARGUMENT;
@@ -2521,6 +2538,24 @@ static int StartSSHD(int argc, char** argv)
25212538
}
25222539
}
25232540

2541+
if (logFile == NULL) {
2542+
logFile = stderr;
2543+
}
2544+
#ifdef _WIN32
2545+
/* The early -D detection (wide-string comparison of cmdArgs before
2546+
* conversion) may have set ServiceDebugCb even when -D was supplied.
2547+
* Now that mygetopt has been processed, restore the file-based
2548+
* callback in any case where output should go to logFile:
2549+
* - isDaemon==0 → running interactively, logs to logFile (stderr)
2550+
* - isDaemon==1 but -E was used → logs to the specified file
2551+
* This must happen BEFORE config/SetupCTX so their log messages are
2552+
* captured in the file (or stderr) rather than lost to
2553+
* OutputDebugString. */
2554+
if (!isDaemon || logFile != stderr) {
2555+
wolfSSH_SetLoggingCb(wolfSSHDLoggingCb);
2556+
}
2557+
#endif
2558+
25242559
if (ret == WS_SUCCESS) {
25252560
ret = wolfSSHD_ConfigLoad(conf, configFile);
25262561
if (ret != WS_SUCCESS) {
@@ -2552,10 +2587,6 @@ static int StartSSHD(int argc, char** argv)
25522587
}
25532588
}
25542589

2555-
if (logFile == NULL) {
2556-
logFile = stderr;
2557-
}
2558-
25592590
/* run as a daemon or service */
25602591
#ifndef WIN32
25612592
if (ret == WS_SUCCESS && isDaemon) {

0 commit comments

Comments
 (0)