3838#include <wolfssl/wolfcrypt/logging.h>
3939#include <wolfssl/wolfcrypt/asn_public.h>
4040
41+ #ifdef USE_WINDOWS_API
42+ #ifdef WOLFSSH_CERTS
43+ #include <windows.h>
44+ #include <wincrypt.h>
45+ #include <ncrypt.h>
46+ #ifndef CERT_SYSTEM_STORE_CURRENT_USER
47+ #define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000
48+ #endif
49+ #ifndef CERT_SYSTEM_STORE_LOCAL_MACHINE
50+ #define CERT_SYSTEM_STORE_LOCAL_MACHINE 0x00020000
51+ #endif
52+ #endif /* WOLFSSH_CERTS */
53+ #endif /* USE_WINDOWS_API */
54+
4155#define WOLFSSH_TEST_SERVER
4256#include <wolfssh/test.h>
4357
@@ -340,14 +354,80 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
340354
341355 /* Load in host private key */
342356 if (ret == WS_SUCCESS ) {
357+ #ifdef USE_WINDOWS_API
358+ #ifdef WOLFSSH_CERTS
359+ char * hostKeyStore = wolfSSHD_ConfigGetHostKeyStore (conf );
360+ char * hostKeyStoreSubject = wolfSSHD_ConfigGetHostKeyStoreSubject (conf );
361+ char * hostKeyStoreFlags = wolfSSHD_ConfigGetHostKeyStoreFlags (conf );
343362
344- char * hostKey = wolfSSHD_ConfigGetHostKeyFile (conf );
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+
370+ if (hostKeyStore != NULL && hostKeyStoreSubject != NULL ) {
371+ /* Use cert store host key */
372+ wchar_t * wStoreName = NULL ;
373+ wchar_t * wSubjectName = NULL ;
374+ DWORD dwFlags = CERT_SYSTEM_STORE_CURRENT_USER ;
375+ int storeNameLen , subjectNameLen ;
376+
377+ /* Parse flags if provided */
378+ if (hostKeyStoreFlags != NULL ) {
379+ if (WSTRCMP (hostKeyStoreFlags , "CURRENT_USER" ) == 0 ) {
380+ dwFlags = CERT_SYSTEM_STORE_CURRENT_USER ;
381+ } else if (WSTRCMP (hostKeyStoreFlags , "LOCAL_MACHINE" ) == 0 ) {
382+ dwFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE ;
383+ } else {
384+ dwFlags = (DWORD )atoi (hostKeyStoreFlags );
385+ }
386+ }
387+
388+ /* Convert to wide strings */
389+ storeNameLen = MultiByteToWideChar (CP_UTF8 , 0 , hostKeyStore , -1 , NULL , 0 );
390+ subjectNameLen = MultiByteToWideChar (CP_UTF8 , 0 , hostKeyStoreSubject , -1 , NULL , 0 );
391+
392+ wStoreName = (wchar_t * )WMALLOC (storeNameLen * sizeof (wchar_t ), heap , DYNTYPE_SSHD );
393+ wSubjectName = (wchar_t * )WMALLOC (subjectNameLen * sizeof (wchar_t ), heap , DYNTYPE_SSHD );
394+
395+ if (wStoreName == NULL || wSubjectName == NULL ) {
396+ wolfSSH_Log (WS_LOG_ERROR , "[SSHD] Memory allocation failed for cert store strings" );
397+ ret = WS_MEMORY_E ;
398+ } else {
399+ MultiByteToWideChar (CP_UTF8 , 0 , hostKeyStore , -1 , wStoreName , storeNameLen );
400+ MultiByteToWideChar (CP_UTF8 , 0 , hostKeyStoreSubject , -1 , wSubjectName , subjectNameLen );
401+
402+ ret = wolfSSH_CTX_UsePrivateKey_fromStore (* ctx , wStoreName , dwFlags , wSubjectName );
403+ if (ret != WS_SUCCESS ) {
404+ wolfSSH_Log (WS_LOG_ERROR , "[SSHD] Failed to load host key from certificate store" );
405+ }
406+
407+ WFREE (wStoreName , heap , DYNTYPE_SSHD );
408+ WFREE (wSubjectName , heap , DYNTYPE_SSHD );
409+ }
410+ } else
411+ #else
412+ wolfSSH_Log (WS_LOG_INFO ,
413+ "[SSHD] WOLFSSH_CERTS not defined - cert store support disabled" );
414+ #endif /* WOLFSSH_CERTS */
415+ #else
416+ wolfSSH_Log (WS_LOG_INFO ,
417+ "[SSHD] USE_WINDOWS_API not defined - cert store support disabled" );
418+ #endif /* USE_WINDOWS_API */
419+ {
420+ char * hostKey = wolfSSHD_ConfigGetHostKeyFile (conf );
345421
346- if (hostKey == NULL ) {
347- wolfSSH_Log (WS_LOG_ERROR , "[SSHD] No host private key set" );
348- ret = WS_BAD_ARGUMENT ;
349- }
350- else {
422+ wolfSSH_Log (WS_LOG_INFO ,
423+ "[SSHD] File-based host key path entered. hostKey=%s" ,
424+ hostKey ? hostKey : "(null)" );
425+
426+ if (hostKey == NULL ) {
427+ wolfSSH_Log (WS_LOG_ERROR , "[SSHD] No host private key set" );
428+ ret = WS_BAD_ARGUMENT ;
429+ }
430+ else {
351431 byte * data ;
352432 word32 dataSz = 0 ;
353433
@@ -384,6 +464,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
384464 wc_FreeDer (& der );
385465 }
386466 }
467+ }
387468 }
388469
389470#if defined(WOLFSSH_OSSH_CERTS ) || defined(WOLFSSH_CERTS )
@@ -440,7 +521,7 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
440521 WOLFSSL_CTX * sslCtx ;
441522
442523 wolfSSH_Log (WS_LOG_INFO , "[SSHD] Using system CAs" );
443- sslCtx = wolfSSL_CTX_new (wolfSSLv23_method ());
524+ sslCtx = wolfSSL_CTX_new (wolfSSLv23_server_method ());
444525 if (sslCtx == NULL ) {
445526 wolfSSH_Log (WS_LOG_INFO , "[SSHD] Unable to create temporary CTX" );
446527 ret = WS_FATAL_ERROR ;
@@ -457,13 +538,19 @@ static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx,
457538
458539 if (ret == WS_SUCCESS ) {
459540 if (wolfSSHD_ConfigGetUserCAStore (conf )) {
541+ #if defined(_WIN32 )
460542 if (wolfSSL_CTX_load_windows_user_CA_certs (sslCtx ,
461- wolfSSHD_ConfigGetWinUserStores (conf ),
462- wolfSSHD_ConfigGetWinUserDwFlags (conf ),
463- wolfSSHD_ConfigGetWinUserPvPara (conf )) != WOLFSSL_SUCCESS ) {
543+ wolfSSHD_ConfigGetWinUserStores (conf ),
544+ wolfSSHD_ConfigGetWinUserDwFlags (conf ),
545+ wolfSSHD_ConfigGetWinUserPvPara (conf )) != WOLFSSL_SUCCESS ) {
464546 wolfSSH_Log (WS_LOG_INFO , "[SSHD] Issue loading user CAs" );
465547 ret = WS_FATAL_ERROR ;
466548 }
549+ #else
550+ wolfSSH_Log (WS_LOG_INFO ,
551+ "[SSHD] User CA store is only supported on Windows" );
552+ ret = WS_BAD_ARGUMENT ;
553+ #endif /* _WIN32 */
467554 }
468555 }
469556
@@ -2451,6 +2538,24 @@ static int StartSSHD(int argc, char** argv)
24512538 }
24522539 }
24532540
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+
24542559 if (ret == WS_SUCCESS ) {
24552560 ret = wolfSSHD_ConfigLoad (conf , configFile );
24562561 if (ret != WS_SUCCESS ) {
@@ -2482,10 +2587,6 @@ static int StartSSHD(int argc, char** argv)
24822587 }
24832588 }
24842589
2485- if (logFile == NULL ) {
2486- logFile = stderr ;
2487- }
2488-
24892590 /* run as a daemon or service */
24902591#ifndef WIN32
24912592 if (ret == WS_SUCCESS && isDaemon ) {
0 commit comments