Secure FTP Plugin for Total Commander

π Table of Contents
- Feature Overview
- Architecture
- File Transfer Capabilities
- Authentication System
- Security & Password Storage
- Connection Management
- Module Map
- System Requirements
- Roadmap
Feature Overview
This plugin is a complete C++20 rewrite of the original SFTP plugin by Christian Ghisler (creator of Total Commander). The original C implementation served as the foundation, but has been completely re-engineered with modern C++ patterns, enhanced security features, and extended functionality.
This plugin targets Total Commander on Windows x64 and provides comprehensive secure file transfer capabilities:
Core Transfer Protocols
- SFTP (primary) with resume support and streaming transfers
- SCP (native) with >2GB file detection for 64-bit servers
- Shell Transfer Fallback (DD/base64) for restricted hosts blocking SFTP/SCP
Authentication Methods
- Password authentication with Keyboard-Interactive support
- Public key authentication (PEM/OpenSSH format)
- Native PPK v2/v3 decoding without external tools
- Pageant (SSH Agent) integration with auto-launch
Advanced Features
- Session import from PuTTY and WinSCP registry
- Comprehensive proxy support (HTTP CONNECT, SOCKS4/4a/5)
- Remote checksum calculation (MD5, SHA1, SHA256, SHA512)
- Automatic UTF-8 and line ending detection
- Host key fingerprint verification
Design Priorities
- Practical interoperability on heterogeneous SSH servers
- Deterministic failure behavior (timeouts, cleanup, no hidden loops)
- Modern C++ architecture with RAII and interface abstraction
- Zero external dependencies beyond statically-linked libssh2
Architecture
Layered Structure
WFX API Layer
β
Plugin Entry Points (FsFindFirst/FsGetFile/FsPutFile/FsExecuteFile/...)
β
βββββββββββββββββββββββββββββββββββββββββββ
β Business Logic Layer β
β ββ Connection/Auth β
β ββ Transfer/RemoteOps β
β ββ UI Separation (IUserFeedback) β
βββββββββββββββββββββββββββββββββββββββββββ
β
ISshBackend Interface (ISshSession/ISshChannel/ISftpHandle)
β
Libssh2Backend Implementation (libssh2)
Why This Architecture Matters
Backend Abstraction via ISshBackend
Polymorphic interfaces (ISshSession, ISshChannel, ISftpHandle) decouple the plug-in from direct libssh2 calls. This enables:
- Future backend migration without rewriting business logic
- Potential multi-backend support (libssh2, libssh, etc.)
- Easier unit testing via mock implementations
RAII Memory Management
Extensive use of std::unique_ptr for session/channel objects and handle_util::AutoHandle<HANDLE> for Windows file handles eliminates memory leaks common in older Total Commander plugins.
UI Separation via IUserFeedback
The IUserFeedback pattern (implemented by WindowsUserFeedback) separates transfer/connection logic from MessageBox dialogs, improving background thread stability in Total Commander's multi-threaded environment.
Connection Lifecycle
Operational Requirements:
- No unbounded EAGAIN loops
- Readiness checks in all network loops
- Stage timeout per critical phase (connect/auth/read)
- Cleanup on every failing exit path
File Transfer Capabilities
Standard SFTP & Native SCP
| Feature | Description |
|---|---|
| SFTP Protocol | Full support for downloading/uploading via SFTP subsystem |
| SCP Protocol | Native SCP for servers without SFTP |
| Transfer Resume | Resume interrupted SFTP transfers |
| Encoding Detection | Auto-detect UTF-8 and line endings (CRLF vs LF) |
| Permissions | Remote chmod for file permissions |
| Timestamps | touch command support via SCP console |
Shell DD / Base64 Fallback (New!)
Advanced workaround for servers with blocked SFTP subsystem and unavailable scp command. Uses hidden interactive channel for transfers.
Upload Path:
- Split local data into chunks
- Base64 encode each chunk
- Send via
printf '%s' | base64 -dthrough shell channel - Decode and append server-side
Download Path:
- Try fast path via
cat - Fallback to
base64 -w 0when needed - Incremental decode (streaming, no full-file buffering)
Throughput Note: Base64 adds ~33% overhead. Native SFTP/SCP is faster. Shell fallback is compatibility-first, not speed-first.
SCP > 2GB File Support
| Detection Method | Implementation |
|---|---|
| 64-bit Server Check | file and which scp commands |
| Transfer Mode | Automatic adjustment for large files |
| Fallback | Shell transfer if SCP limit detected |
Remote Checksum Support
Calculate file hashes directly on the server without local computation:
| Algorithm | Command |
|---|---|
| MD5 | md5sum / md5 -q |
| SHA1 | sha1sum / sha1 -q |
| SHA256 | sha256sum / shasum -a 256 |
| SHA512 | sha512sum / shasum -a 512 |
Authentication System
Supported Methods
- Password - Traditional password authentication
- Keyboard-Interactive - With password change request handling
- PEM (OpenSSH) - Traditional private key format
- PPK v2/v3 - Native PuTTY format decoding (New!)
- Pageant - SSH Agent integration
Native PPK v2 & v3 Decoder (New!)
Revolutionary native parsing of PuTTY Private Key files without external tools:
| Component | Implementation |
|---|---|
| Key Derivation | Windows BCrypt + Argon2d/i/id |
| Dynamic Loading | argon2.dll loaded on-demand |
| Encryption | AES-256-CBC support |
| MAC Validation | HMAC-SHA-256 verification |
| Output Format | Traditional PEM for libssh2 |
Authentication Fallback Strategy
Key-Path Validation (Fail-Fast)
| Condition | Behavior |
|---|---|
Missing privkeyfile |
Immediate local error (no fallback stall) |
Missing pubkeyfile (explicit) |
Immediate local error |
| Invalid PPK format | Precise error with MAC/KDF details |
This avoids minute-long UI freezes on impossible auth attempts.
Pageant Integration
- Full integration with PuTTY Pageant
- Auto-launch
pageant.lnkwhen needed - Seamless fallback to file-based auth if agent unavailable
Security & Password Storage
Storage Modes
| Mode | Format | Description |
|---|---|---|
| TC Master | password=! |
Total Commander CryptProc API |
| DPAPI | password=dpapi:... |
Windows DPAPI user-scoped |
| Plaintext | password=plain:... |
Explicit marker (controlled fallback) |
| Legacy XOR | (legacy) | Read-only compatibility |
Security Enhancements
| Feature | Implementation |
|---|---|
| Primary Encryption | DPAPI (CryptProtectData) |
| TC Integration | CryptProc API when available |
| Legacy Support | XOR read-only (compatibility) |
| PPK v3 Keys | Argon2 key derivation |
| Memory Handling | Secure zeroing of sensitive buffers |
Connection Management
Session Import (New!)
Import configurations from Windows Registry:
| Source | Registry Path |
|---|---|
| PuTTY | HKCU\Software\SimonTatham\PuTTY\Sessions |
| WinSCP | HKCU\Software\Martin Prikryl\WinSCP 2\Sessions |
Import Features:
- Non-conflicting conversion to plugin INI format
- Preserves connectivity fields (host, port, user, keys)
- No auto-connect side effects during import
Proxy Support
| Type | Authentication |
|---|---|
| HTTP CONNECT | Basic auth |
| SOCKS4 | None |
| SOCKS4a | None |
| SOCKS5 | None / Username-Password |
Network Features
- IPv4 / IPv6 dual-stack support
- Custom port configuration
- Host key verification with fingerprint storage
- First-time connection warnings
- Fingerprint changed alerts
Shell Engineering Highlights
Marker-Aware SCP Parsing
Real-world SSH servers differ in shell behavior. KVC handles edge cases:
| Technique | Purpose |
|---|---|
__WFX_LIST_BEGIN__ |
Directory listing start marker |
__WFX_LIST_END__ |
Directory listing end marker |
echo $? |
Exit code detection |
| Defensive parsing | Skip echoed commands/prompts |
Restricted Shell Handling
| Scenario | Solution |
|---|---|
| Blocked SFTP | Shell transfer fallback |
No scp command |
cat / dd / base64 |
| Noisy prompts | Buffer filtering |
| Delayed output | Staggered read timeouts |
Module Map (for Maintainers)
| Module | Responsibility | C++ Modernization Status |
|---|---|---|
| SftpConnection.cpp | Connect lifecycle, auth orchestration | RAII session management |
| SftpAuth.cpp | Auth methods, PPK conversion | Native PPK v2/v3 decoder |
| SftpTransfer.cpp | Upload/download, fallback wiring | Streaming buffers |
| SftpRemoteOps.cpp | Listing, remote operations | Marker-aware parsing |
| SftpShell.cpp | Shell channel execution | EAGAIN loop guards |
| SessionImport.cpp | PuTTY/WinSCP import | Registry β INI conversion |
| PpkConverter.cpp | PPK β PEM conversion | BCrypt + Argon2 |
| Libssh2Backend.cpp | SSH backend implementation | ISshBackend interface |
| PluginEntryPoints.cpp | TC WFX API entry points | Legacy C interface |
| WindowsUserFeedback.cpp | UI separation | IUserFeedback pattern |
| CoreUtils.cpp | Utility functions (BASE64, time, strings) | Modern C++20 |
| FtpDirectoryParser.cpp | Directory listing parser | Unicode helpers |
System Requirements
| Component | Requirement |
|---|---|
| Operating System | Windows 7 or later (10/11 recommended) |
| Total Commander | Version 9.0 or later (x64) |
| Compiler | Visual Studio 2026 (v145 toolset), C++20 |
| Dependencies | libssh2 (statically linked) |
| Optional | argon2.dll (for PPK v3 with Argon2) |
| APIs | Windows BCrypt, DPAPI |
Packaging
Distribution package contents:
| File | Purpose |
|---|---|
sftpplug.wfx64 |
x64 binary plugin |
pluginst.inf |
Total Commander auto-install |
| No external DLLs | libssh2 statically linked |
Roadmap
Completed / Stable
- Backend abstraction layer (ISshBackend)
- Native PPK v2/v3 conversion with Argon2
- Shell DD/base64 fallback transfer
- Session import (WinSCP/PuTTY)
- Remote checksum support (MD5/SHA1/SHA256/SHA512)
- SCP >2GB file detection
- DPAPI + TC password manager integration
- x64 packaging flow
In Progress
- Splitting oversized legacy functions
- C-style buffer cleanup to safer C++ constructs
- UI/business-logic decoupling (WFX constraints)
Deferred (Intentional)
- Full rewrite of legacy parser modules
- Multi-platform support (Linux/macOS)
- Alternative backend (libssh)