Skip to content

wolfsshd: complete the Windows user profile fallback - #1243

Open
yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/13326
Open

wolfsshd: complete the Windows user profile fallback#1243
yosuke-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
yosuke-wolfssl:fix/13326

Conversation

@yosuke-wolfssl

Copy link
Copy Markdown
Contributor

Problem

_GetHomeDirectory() on wolfsshd's Windows path zero-initializes PROFILEINFO but never sets dwSize, which LoadUserProfileW() rejects with ERROR_INVALID_PARAMETER. That fallback runs whenever SHGetKnownFolderPath(FOLDERID_Profile) cannot resolve the user — the case for any account with no profile on the host, since the network logon wolfsshd performs does not create one. Every consumer of the home directory then fails and the login is refused:

Call site Uses the home directory for
CheckPublicKeyWIN() locating authorized_keys
SFTP_Subsystem() SFTP default path
SHELL_Subsystem() shell working directory

Both Windows CI workflows already work around this by hand-writing a ProfileList\<SID>\ProfileImagePath entry so the fallback is never taken.

Two further defects on the same path:

  • The home directory came from ExpandEnvironmentStringsW(L"%USERPROFILE%"), which expands against the service account's environment. With dwSize fixed the fallback would start succeeding and hand C:\Windows\system32\config\systemprofile back as every user's home, including to SearchForPubKey().
  • The loaded hive was never unloaded; the code carried a @TODO asking whether it should be.

Fix (apps/wolfsshd/auth.c)

  • dwSize is set before LoadUserProfileW(), and the load is guarded on auth->profile == NULL so a second call cannot orphan the first hive handle.
  • GetUserProfileDirectoryW() on the auth token replaces the %USERPROFILE% expansion.
  • WOLFSSHD_AUTH.profile holds the hive for the connection; wolfSSHD_AuthCloseToken() unloads it before closing the token.
  • RevertToSelf() moves ahead of the token close in SHELL_Subsystem()'s cleanup (wolfsshd.c) — UnloadUserProfile() needs the service account's SE_RESTORE_NAME/SE_BACKUP_NAME, which the impersonated user's token lacks.

Closes f-13326, and covers the wrong-home-directory and hive-leak defects on the same path, which were not separately filed.

Tests (.github/workflows/windows-sftp.yml)

New no_profile matrix job creates testuser with net user /add alone — no home directory, no ACL grant, no ProfileList entry — then runs the SFTP pwd/ls flow and an exec session via client.exe -c. It asserts the session lands in testuser's own profile rather than systemprofile, that NTUSER.DAT was created, and that the hive leaves HKEY_USERS after disconnect. The exec session is what reaches SHELL_Subsystem()'s cleanup: without the RevertToSelf() move the unload fails with ERROR_ACCESS_DENIED and the job fails on the hive still being loaded.

Verification

  • MSVC Debug x64: wolfsshd.exe and the full solution build clean, no warnings on the changed files; unit-test and api-test pass.
  • GCC preflight: lint clean, 6/6 configs.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Sep 8, 2026
Copilot AI lite review requested due to automatic review settings September 8, 2026 05:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes directly address the documented Windows failure mode, add proper resource cleanup, and include targeted CI coverage for the previously untested no-profile scenario.

Pull request overview

This PR fixes wolfsshd’s Windows home-directory fallback so that accounts without a pre-existing local profile can successfully log in and get a correct per-user home directory (instead of the service account’s), while also ensuring the temporary profile hive is unloaded at session teardown.

Changes:

  • Fix _GetHomeDirectory() fallback by correctly initializing PROFILEINFO.dwSize, loading the user profile at most once per session, and using GetUserProfileDirectoryW() (token-based) instead of %USERPROFILE%.
  • Track the loaded user profile hive in WOLFSSHD_AUTH.profile and unload it in wolfSSHD_AuthCloseToken().
  • Add a new Windows CI “no_profile” job that validates profile creation, correct landing directory, and hive unload after disconnect.
File summaries
File Description
apps/wolfsshd/wolfsshd.c Reorders RevertToSelf() ahead of token/profile teardown so profile unloading has required service privileges.
apps/wolfsshd/auth.c Fixes Windows profile-loading fallback and adds per-session profile hive tracking + unloading on token close.
.github/workflows/windows-sftp.yml Adds a matrix job covering a user with no pre-existing Windows profile and asserts creation + cleanup behavior.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1243

Scan targets checked: wolfssh-bugs, wolfssh-src

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread apps/wolfsshd/auth.c
Comment thread apps/wolfsshd/auth.c
- _GetHomeDirectoryEx sets PROFILEINFO.dwSize, loads the profile only
  on its loadProfile argument, and reads the home directory with
  GetUserProfileDirectoryW instead of expanding %USERPROFILE%.
- _GetHomeDirectory and _GetHomeDirectoryPreAuth wrap it with that
  argument set and clear; CheckPublicKeyWIN takes the pre-auth one.
- WOLFSSHD_AUTH holds the loaded hive; wolfSSHD_AuthCloseToken
  unloads it before closing the token, calling RegCloseKey when the
  unload fails.
- The Windows shell cleanup calls RevertToSelf() before closing the
  auth token rather than after.
- windows-sftp.yml gains a no_profile job: testuser is created with
  net user alone, and an exec session builds the profile, runs as
  testuser, and releases the hive.

Issue: F-13326
Comment thread apps/wolfsshd/auth.c
Comment thread apps/wolfsshd/auth.c

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #1243

Scan targets checked: wolfssh-bugs, wolfssh-src

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

@wolfSSL-Fenrir-bot
wolfSSL-Fenrir-bot dismissed their stale review September 8, 2026 07:18

Fenrir's latest completed scan found no issues; clearing the prior automated change request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants