wolfSSHd port to Windows

handling of terminal size adjustments

stub case for ECH virtual terminal command
pull/512/head
JacobBarthelmeh 2023-04-24 06:42:53 -06:00
parent 47001e0d92
commit ab742ca766
24 changed files with 2042 additions and 291 deletions

1
.gitignore vendored
View File

@ -76,6 +76,7 @@ client.plist
*.vcxproj.filters *.vcxproj.filters
*.opensdf *.opensdf
*.pdb *.pdb
.vs
Debug Debug
Release Release
DLL Debug DLL Debug

View File

@ -22,6 +22,10 @@
#include <config.h> #include <config.h>
#endif #endif
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#endif
#ifdef WOLFSSH_SSHD #ifdef WOLFSSH_SSHD
#ifdef __linux__ #ifdef __linux__
@ -30,7 +34,10 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#endif #endif
#ifndef _WIN32
#include <unistd.h> #include <unistd.h>
#endif
#include <wolfssh/ssh.h> #include <wolfssh/ssh.h>
#include <wolfssh/internal.h> #include <wolfssh/internal.h>
@ -69,6 +76,9 @@ struct WOLFSSHD_AUTH {
CallbackCheckPassword checkPasswordCb; CallbackCheckPassword checkPasswordCb;
CallbackCheckPublicKey checkPublicKeyCb; CallbackCheckPublicKey checkPublicKeyCb;
const WOLFSSHD_CONFIG* conf; const WOLFSSHD_CONFIG* conf;
#if defined(_WIN32)
HANDLE token; /* a users token */
#endif
int gid; int gid;
int uid; int uid;
int sGid; /* saved gid */ int sGid; /* saved gid */
@ -143,12 +153,13 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
word32 keySz) word32 keySz)
{ {
int ret = WSSHD_AUTH_SUCCESS; int ret = WSSHD_AUTH_SUCCESS;
char* type; char* type = NULL;
char* keyCandBase64; /* cand == candidate */ char* keyCandBase64 = NULL; /* cand == candidate */
word32 keyCandBase64Sz; word32 keyCandBase64Sz;
byte* keyCand = NULL; byte* keyCand = NULL;
word32 keyCandSz; word32 keyCandSz = 0;
char* last; char* last = NULL;
enum { enum {
#ifdef WOLFSSH_CERTS #ifdef WOLFSSH_CERTS
NUM_ALLOWED_TYPES = 9 NUM_ALLOWED_TYPES = 9
@ -329,7 +340,7 @@ static int CheckPasswordHashUnix(const char* input, char* stored)
} }
#endif /* WOLFSSH_HAVE_LIBCRYPT || WOLFSSH_HAVE_LIBLOGIN */ #endif /* WOLFSSH_HAVE_LIBCRYPT || WOLFSSH_HAVE_LIBLOGIN */
static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz) static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz, WOLFSSHD_AUTH* authCtx)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
char* pwStr = NULL; char* pwStr = NULL;
@ -413,32 +424,13 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz)
WFREE(storedHashCpy, NULL, DYNTYPE_STRING); WFREE(storedHashCpy, NULL, DYNTYPE_STRING);
} }
WOLFSSH_UNUSED(authCtx);
return ret; return ret;
} }
#endif /* WOLFSSH_USE_PAM */ #endif /* WOLFSSH_USE_PAM */
#endif /* !_WIN32 */ #endif /* !_WIN32 */
#ifndef _WIN32
static int CheckUserUnix(const char* name) {
int ret = WSSHD_AUTH_FAILURE;
struct passwd* pwInfo;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Unix check user");
errno = 0;
pwInfo = getpwnam(name);
if (pwInfo == NULL) {
if (errno != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error calling getpwnam for user "
"%s.", name);
ret = WS_FATAL_ERROR;
}
}
else {
ret = WSSHD_AUTH_SUCCESS;
}
return ret;
}
static const char authKeysDefault[] = ".ssh/authorized_keys"; static const char authKeysDefault[] = ".ssh/authorized_keys";
static char authKeysPattern[MAX_PATH_SZ] = { 0 }; static char authKeysPattern[MAX_PATH_SZ] = { 0 };
@ -451,6 +443,7 @@ void SetAuthKeysPattern(const char* pattern)
} }
} }
static int ResolveAuthKeysPath(const char* homeDir, char* resolved) static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
@ -496,23 +489,111 @@ static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
return ret; return ret;
} }
static int CheckPublicKeyUnix(const char* name, static int SearchForPubKey(const char* path, const WS_UserAuthData_PublicKey* pubKeyCtx)
const WS_UserAuthData_PublicKey* pubKeyCtx,
const char* usrCaKeysFile)
{ {
int ret = WSSHD_AUTH_SUCCESS; int ret = WSSHD_AUTH_SUCCESS;
int rc; char authKeysPath[MAX_PATH_SZ];
struct passwd* pwInfo; WFILE *f = XBADFILE;
char* authKeysFile = NULL;
XFILE f = XBADFILE;
char* lineBuf = NULL; char* lineBuf = NULL;
char* current; char* current;
word32 currentSz; word32 currentSz;
int foundKey = 0; int foundKey = 0;
char authKeysPath[MAX_PATH_SZ]; int rc = 0;
WMEMSET(authKeysPath, 0, sizeof(authKeysPath));
rc = ResolveAuthKeysPath(path, authKeysPath);
if (rc != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to resolve authorized keys"
" file path.");
ret = rc;
}
if (ret == WSSHD_AUTH_SUCCESS) {
if (WFOPEN(&f, authKeysPath, "rb") != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
authKeysPath);
ret = WS_BAD_FILE_E;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
if (lineBuf == NULL) {
ret = WS_MEMORY_E;
}
}
while (ret == WSSHD_AUTH_SUCCESS &&
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)XSTRLEN(current);
/* remove leading spaces */
while (currentSz > 0 && current[0] == ' ') {
currentSz = currentSz - 1;
current = current + 1;
}
if (currentSz <= 1) {
continue; /* empty line */
}
if (current[0] == '#') {
continue; /* commented out line */
}
rc = CheckAuthKeysLine(current, currentSz, pubKeyCtx->publicKey,
pubKeyCtx->publicKeySz);
if (rc == WSSHD_AUTH_SUCCESS) {
foundKey = 1;
break;
}
else if (rc < 0) {
ret = rc;
break;
}
}
if (f != XBADFILE) {
WFCLOSE(f);
}
if (ret == WSSHD_AUTH_SUCCESS && !foundKey) {
ret = WSSHD_AUTH_FAILURE;
}
return ret;
}
#ifndef _WIN32
static int CheckUserUnix(const char* name) {
int ret = WSSHD_AUTH_FAILURE;
struct passwd* pwInfo;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Unix check user");
errno = 0;
pwInfo = getpwnam(name);
if (pwInfo == NULL) {
if (errno != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error calling getpwnam for user "
"%s.", name);
ret = WS_FATAL_ERROR;
}
}
else {
ret = WSSHD_AUTH_SUCCESS;
}
return ret;
}
static int CheckPublicKeyUnix(const char* name,
const WS_UserAuthData_PublicKey* pubKeyCtx,
const char* usrCaKeysFile, WOLFSSHD_AUTH* authCtx)
{
int ret = WSSHD_AUTH_SUCCESS;
struct passwd* pwInfo;
#ifdef WOLFSSH_OSSH_CERTS #ifdef WOLFSSH_OSSH_CERTS
if (pubKeyCtx->isOsshCert) { if (pubKeyCtx->isOsshCert) {
int rc;
byte* caKey = NULL; byte* caKey = NULL;
word32 caKeySz; word32 caKeySz;
const byte* caKeyType = NULL; const byte* caKeyType = NULL;
@ -584,79 +665,352 @@ static int CheckPublicKeyUnix(const char* name,
} }
if (ret == WSSHD_AUTH_SUCCESS) { if (ret == WSSHD_AUTH_SUCCESS) {
WMEMSET(authKeysPath, 0, sizeof(authKeysPath)); ret = SearchForPubKey(pwInfo->pw_dir, pubKeyCtx);
rc = ResolveAuthKeysPath(pwInfo->pw_dir, authKeysPath);
if (rc != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed to resolve authorized keys"
" file path.");
ret = rc;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
f = XFOPEN(authKeysPath, "rb");
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to open %s",
authKeysPath);
ret = WS_BAD_FILE_E;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
lineBuf = (char*)WMALLOC(MAX_LINE_SZ, NULL, DYNTYPE_BUFFER);
if (lineBuf == NULL) {
ret = WS_MEMORY_E;
}
}
while (ret == WSSHD_AUTH_SUCCESS &&
(current = XFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)XSTRLEN(current);
/* remove leading spaces */
while (currentSz > 0 && current[0] == ' ') {
currentSz = currentSz - 1;
current = current + 1;
}
if (currentSz <= 1) {
continue; /* empty line */
}
if (current[0] == '#') {
continue; /* commented out line */
}
rc = CheckAuthKeysLine(current, currentSz, pubKeyCtx->publicKey,
pubKeyCtx->publicKeySz);
if (rc == WSSHD_AUTH_SUCCESS) {
foundKey = 1;
break;
}
else if (rc < 0) {
ret = rc;
break;
}
} }
} }
if (f != XBADFILE) { WOLFSSH_UNUSED(usrCaKeysFile);
XFCLOSE(f); WOLFSSH_UNUSED(authCtx);
}
if (ret == WSSHD_AUTH_SUCCESS && !foundKey) {
ret = WSSHD_AUTH_FAILURE;
}
if (lineBuf != NULL) {
WFREE(lineBuf, NULL, DYNTYPE_BUFFER);
}
if (authKeysFile != NULL) {
WFREE(authKeysFile, NULL, DYNTYPE_STRING);
}
(void)usrCaKeysFile;
return ret; return ret;
} }
#endif /* !_WIN32*/ #endif /* !_WIN32*/
#ifdef _WIN32
#include <ntstatus.h>
#include <Ntsecapi.h>
#include <Shlobj.h>
#include <UserEnv.h>
#include <KnownFolders.h>
#define MAX_USERNAME 256
static int _GetHomeDirectory(WOLFSSHD_AUTH* auth, const char* usr, WCHAR* out, int outSz)
{
int ret = WS_SUCCESS;
WCHAR usrW[MAX_USERNAME];
wchar_t* homeDir;
HRESULT hr;
size_t wr;
/* convert user name to Windows wchar type */
mbstowcs_s(&wr, usrW, MAX_USERNAME, usr, MAX_USERNAME-1);
hr = SHGetKnownFolderPath((REFKNOWNFOLDERID)&FOLDERID_Profile,
0, wolfSSHD_GetAuthToken(auth), &homeDir);
if (SUCCEEDED(hr)) {
wcscpy_s(out, outSz, homeDir);
CoTaskMemFree(homeDir);
}
else {
PROFILEINFO pInfo = { sizeof(PROFILEINFO) };
/* failed with get known folder path, try with loading the user profile */
pInfo.dwFlags = PI_NOUI;
pInfo.lpUserName = usrW;
if (LoadUserProfileW(wolfSSHD_GetAuthToken(auth), &pInfo) != TRUE) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error %d loading user %s", GetLastError(), usr);
ret = WS_FATAL_ERROR;
}
/* get home directory env. for user */
if (ret == WS_SUCCESS &&
ExpandEnvironmentStringsW(L"%USERPROFILE%", out, outSz) == 0) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error getting user %s's home path", usr);
ret = WS_FATAL_ERROR;
}
/* @TODO is unload of user needed here?
UnloadUserProfileW(wolfSSHD_GetAuthToken(conn->auth), pInfo.hProfile);
*/
}
return ret;
}
int wolfSSHD_GetHomeDirectory(WOLFSSHD_AUTH* auth, WOLFSSH* ssh, WCHAR* out, int outSz)
{
return _GetHomeDirectory(auth, wolfSSH_GetUsername(ssh), out, outSz);
}
/* Returns the users token from LogonUserW call */
HANDLE wolfSSHD_GetAuthToken(const WOLFSSHD_AUTH* auth)
{
if (auth == NULL)
return NULL;
return auth->token;
}
static int CheckPasswordWIN(const char* usr, const byte* pw, word32 pwSz, WOLFSSHD_AUTH* authCtx)
{
int ret;
WCHAR* usrW = NULL;
WCHAR* pwW = NULL;
WCHAR dmW[] = L"."; /* currently hard set to use local domain */
size_t usrWSz = 0;
int pwWSz = 0;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Windows check password");
ret = WSSHD_AUTH_SUCCESS;
usrWSz = WSTRLEN(usr) * sizeof(WCHAR);
usrW = (WCHAR*)WMALLOC(usrWSz + 1, authCtx->heap, DYNTYPE_SSHD);
if (usrW == NULL) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Ran out of memory");
ret = WSSHD_AUTH_FAILURE;
}
if (ret == WSSHD_AUTH_SUCCESS) {
size_t wr = 0;
if (mbstowcs_s(&wr, usrW, usrWSz, usr, usrWSz-1) != 0) {
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
pwWSz = MultiByteToWideChar(CP_UTF8, 0, pw, pwSz, NULL, 0);
if (pwWSz <= 0) {
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
pwW = (WCHAR*)WMALLOC((pwWSz * sizeof(WCHAR)) + sizeof(WCHAR), authCtx->heap, DYNTYPE_SSHD);
if (pwW == NULL) {
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
if (MultiByteToWideChar(CP_UTF8, 0, pw, pwSz, pwW, pwWSz) != pwSz) {
ret = WSSHD_AUTH_FAILURE;
}
else {
pwW[pwWSz] = L'\0';
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
if (LogonUserExExW(usrW, dmW, pwW, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, NULL,
&authCtx->token, NULL, NULL, NULL, NULL) != TRUE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Windows failed with error %d when login in as user %s, "
"bad username or password", GetLastError(), usr);
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Check user is allowed to 'Log on as batch job'");
ret = WSSHD_AUTH_FAILURE;
}
}
if (usrW != NULL) {
WFREE(usrW, authCtx->heap, DYNTYPE_SSHD);
}
if (pwW != NULL) {
WFREE(pwW, authCtx->heap, DYNTYPE_SSHD);
}
return ret;
}
static int CheckUserWIN(const char* name)
{
int ret = WSSHD_AUTH_FAILURE;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Windows user check happens with password/public key check");
ret = WSSHD_AUTH_SUCCESS;
return ret;
}
/* Helper function to setup the user token in cases where public key
* auth is used. Return WSSHD_AUTH_SUCCESS on success */
static int SetupUserTokenWin(const char* usr,
const WS_UserAuthData_PublicKey* pubKeyCtx,
const char* usrCaKeysFile, WOLFSSHD_AUTH* authCtx)
{
int ret;
WCHAR* usrW = NULL;
WCHAR dmW[] = L"."; /* currently hard set to use local domain */
ULONG rc;
HANDLE lsaHandle = NULL;
ULONG authId = 0;
void* authInfo = NULL;
ULONG authInfoSz = 0;
TOKEN_SOURCE sourceContext;
size_t usrWSz;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Windows public key get user token");
ret = WSSHD_AUTH_SUCCESS;
usrWSz = WSTRLEN(usr);
usrW = (WCHAR*)WMALLOC((usrWSz + 1) * sizeof(WCHAR), NULL, DYNTYPE_SSHD);
if (usrW == NULL) {
ret = WS_MEMORY_E;
}
if (ret == WSSHD_AUTH_SUCCESS) {
size_t wr;
if (mbstowcs_s(&wr, usrW, usrWSz + 1, usr, usrWSz) != 0) {
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
LSA_OPERATIONAL_MODE oMode;
LSA_STRING processName;
WMEMSET(&processName, 0, sizeof(LSA_STRING));
processName.Buffer = "wolfsshd";
processName.Length = (USHORT)WSTRLEN("wolfsshd");
processName.MaximumLength = processName.Length + 1;
if ((rc = LsaRegisterLogonProcess(&processName, &lsaHandle, &oMode)) != STATUS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] LSA Register Logon Process Error %d", LsaNtStatusToWinError(rc));
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
LSA_STRING authName;
WMEMSET(&authName, 0, sizeof(LSA_STRING));
authName.Buffer = MSV1_0_PACKAGE_NAME;
authName.Length = (USHORT)WSTRLEN(MSV1_0_PACKAGE_NAME);
authName.MaximumLength = authName.Length + 1;
if (rc = LsaLookupAuthenticationPackage(lsaHandle, &authName, &authId) != STATUS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] LSA Lookup Authentication Package Error %d", rc);
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
/* size of logon struct plus computer and user name */
authInfoSz = (ULONG)(sizeof(MSV1_0_S4U_LOGON) +
(wcslen(usrW) + wcslen(dmW)) * sizeof(wchar_t));
authInfo = (void*)WMALLOC(authInfoSz, NULL, DYNTYPE_SSHD);
if (authInfo == NULL) {
ret = WSSHD_AUTH_FAILURE;
}
else {
MSV1_0_S4U_LOGON* l;
WMEMSET(authInfo, 0, authInfoSz);
l = (MSV1_0_S4U_LOGON*)authInfo;
l->MessageType = MsV1_0S4ULogon;
/* write user name after the MSV1_0_S4U_LOGON structure in buffer */
l->UserPrincipalName.Length = (USHORT)(wcslen(usrW) * sizeof(wchar_t));
l->UserPrincipalName.MaximumLength = l->UserPrincipalName.Length;
l->UserPrincipalName.Buffer = (WCHAR*)((byte*)l + sizeof(MSV1_0_S4U_LOGON));
memcpy_s(l->UserPrincipalName.Buffer, l->UserPrincipalName.Length, usrW, l->UserPrincipalName.Length);
/* write domain name after the user name in buffer */
l->DomainName.Length = (USHORT)(wcslen(dmW) * sizeof(wchar_t));
l->DomainName.MaximumLength = l->UserPrincipalName.Length;
l->DomainName.Buffer = (WCHAR*)((byte*)(l->UserPrincipalName.Buffer) + l->UserPrincipalName.Length);
memcpy_s(l->DomainName.Buffer, l->DomainName.Length, dmW, l->DomainName.Length);
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
strcpy_s(sourceContext.SourceName, TOKEN_SOURCE_LENGTH, "sshd");
if (AllocateLocallyUniqueId(&sourceContext.SourceIdentifier) != TRUE) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Windows failed to allocate locally unique source context id");
ret = WSSHD_AUTH_FAILURE;
}
}
if (ret == WSSHD_AUTH_SUCCESS) {
LSA_STRING originName;
NTSTATUS subStatus;
QUOTA_LIMITS quotas;
DWORD profileSz;
PKERB_INTERACTIVE_PROFILE profile = NULL;
LUID logonId = { 0, 0 };
WMEMSET(&originName, 0, sizeof(LSA_STRING));
originName.Buffer = "wolfsshd";
originName.Length = (USHORT)WSTRLEN("wolfsshd");
originName.MaximumLength = originName.Length + 1;
if ((rc = LsaLogonUser(lsaHandle, &originName, Network, authId, authInfo, authInfoSz, NULL, &sourceContext, &profile, &profileSz, &logonId, &authCtx->token, &quotas, &subStatus)) != STATUS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Windows failed with status %X, SubStatus %d, when login in as user %s",
rc, subStatus, usr);
ret = WSSHD_AUTH_FAILURE;
}
/* currently not using the profile returned, free it here */
if (profile != NULL) {
LsaFreeReturnBuffer(profile);
}
}
if (authInfo != NULL) {
WFREE(authInfo, NULL, DYNTYPE_SSHD);
}
if (lsaHandle != NULL) {
LsaDeregisterLogonProcess(lsaHandle);
}
return ret;
}
/* Uses Windows LSA for getting an impersination token */
static int CheckPublicKeyWIN(const char* usr,
const WS_UserAuthData_PublicKey* pubKeyCtx,
const char* usrCaKeysFile, WOLFSSHD_AUTH* authCtx)
{
int ret;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Windows check public key");
ret = SetupUserTokenWin(usr, pubKeyCtx,usrCaKeysFile, authCtx);
/* after successful logon check the public key sent */
if (ret == WSSHD_AUTH_SUCCESS) {
WCHAR h[MAX_PATH];
if (_GetHomeDirectory(authCtx, usr, h, MAX_PATH) == WS_SUCCESS) {
CHAR r[MAX_PATH];
size_t rSz;
if (wcstombs_s(&rSz, r, MAX_PATH, h, MAX_PATH - 1) != 0) {
ret = WSSHD_AUTH_FAILURE;
}
if (ret == WSSHD_AUTH_SUCCESS) {
r[rSz-1] = L'\0';
ret = SearchForPubKey(r, pubKeyCtx);
if (ret != WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Failed to find public key for user %s", usr);
ret = WSSHD_AUTH_FAILURE;
}
}
}
else {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Windows failed to get home directory for user %s",
usr);
ret = WSSHD_AUTH_FAILURE;
}
}
return ret;
}
#endif /* _WIN32*/
/* return WOLFSSH_USERAUTH_SUCCESS on success */ /* return WOLFSSH_USERAUTH_SUCCESS on success */
static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth) static int DoCheckUser(const char* usr, WOLFSSHD_AUTH* auth)
@ -734,7 +1088,7 @@ static int RequestAuthentication(WS_UserAuthData* authData,
} }
else { else {
rc = authCtx->checkPasswordCb(usr, authData->sf.password.password, rc = authCtx->checkPasswordCb(usr, authData->sf.password.password,
authData->sf.password.passwordSz); authData->sf.password.passwordSz, authCtx);
if (rc == WSSHD_AUTH_SUCCESS) { if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password ok."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Password ok.");
} }
@ -832,12 +1186,26 @@ static int RequestAuthentication(WS_UserAuthData* authData,
!wolfSSHD_ConfigGetAuthKeysFileSet(authCtx->conf)) { !wolfSSHD_ConfigGetAuthKeysFileSet(authCtx->conf)) {
wolfSSH_Log(WS_LOG_INFO, wolfSSH_Log(WS_LOG_INFO,
"[SSHD] Relying on CA for public key check"); "[SSHD] Relying on CA for public key check");
#ifdef WIN32
/* Still need to get users token on Windows */
rc = SetupUserTokenWin(usr, &authData->sf.publicKey,
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf), authCtx);
if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Got users token ok.");
ret = WOLFSSH_USERAUTH_SUCCESS; ret = WOLFSSH_USERAUTH_SUCCESS;
} }
else {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error getting users token.");
ret = WOLFSSH_USERAUTH_FAILURE;
}
#else
ret = WOLFSSH_USERAUTH_SUCCESS;
#endif
}
else { else {
/* if not a certificate then parse through authorized key file */ /* if not a certificate then parse through authorized key file */
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey, rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf)); wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf), authCtx);
if (rc == WSSHD_AUTH_SUCCESS) { if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
ret = WOLFSSH_USERAUTH_SUCCESS; ret = WOLFSSH_USERAUTH_SUCCESS;
@ -939,7 +1307,9 @@ static int SetDefaultUserCheck(WOLFSSHD_AUTH* auth)
int ret = WS_NOT_COMPILED; int ret = WS_NOT_COMPILED;
#ifdef _WIN32 #ifdef _WIN32
/* TODO: Implement for Windows. */ wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Windows user name check");
auth->checkUserCb = CheckUserWIN;
ret = WS_SUCCESS;
#else #else
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Unix user name check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting default Unix user name check");
auth->checkUserCb = CheckUserUnix; auth->checkUserCb = CheckUserUnix;
@ -955,7 +1325,9 @@ static int SetDefaultPasswordCheck(WOLFSSHD_AUTH* auth)
int ret = WS_NOT_COMPILED; int ret = WS_NOT_COMPILED;
#ifdef _WIN32 #ifdef _WIN32
/* TODO: Add CheckPasswordWin. */ wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Windows password check");
auth->checkPasswordCb = CheckPasswordWIN;
ret = WS_SUCCESS;
#elif defined(WOLFSSH_USE_PAM) #elif defined(WOLFSSH_USE_PAM)
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting PAM password check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting PAM password check");
auth->checkPasswordCb = CheckPasswordPAM; auth->checkPasswordCb = CheckPasswordPAM;
@ -974,7 +1346,9 @@ static int SetDefaultPublicKeyCheck(WOLFSSHD_AUTH* auth)
int ret = WS_NOT_COMPILED; int ret = WS_NOT_COMPILED;
#ifdef _WIN32 #ifdef _WIN32
/* TODO: Implement for Windows. */ wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Windows public key check");
auth->checkPublicKeyCb = CheckPublicKeyWIN;
ret = WS_SUCCESS;
#else #else
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix public key check"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Setting Unix public key check");
auth->checkPublicKeyCb = CheckPublicKeyUnix; auth->checkPublicKeyCb = CheckPublicKeyUnix;
@ -983,6 +1357,33 @@ static int SetDefaultPublicKeyCheck(WOLFSSHD_AUTH* auth)
return ret; return ret;
} }
static int SetDefualtUserID(WOLFSSHD_AUTH* auth)
{
#ifdef _WIN32
/* TODO: Implement for Windows. */
return 0;
#else
struct passwd* pwInfo;
const char* usr = "sshd";
int ret = WS_SUCCESS;
pwInfo = getpwnam(usr);
if (pwInfo == NULL) {
/* user name not found on system */
wolfSSH_Log(WS_LOG_INFO, "[SSHD] No sshd user found to use");
ret = WS_FATAL_ERROR;
}
if (ret == WS_SUCCESS) {
auth->gid = pwInfo->pw_gid;
auth->uid = pwInfo->pw_uid;
auth->sGid = getgid();
auth->sUid = getuid();
}
return ret;
#endif
}
/* Sets the default functions to be used for authentication of peer. /* Sets the default functions to be used for authentication of peer.
* Later the default functions could be overriden if needed. * Later the default functions could be overriden if needed.
@ -994,8 +1395,6 @@ WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf)
auth = (WOLFSSHD_AUTH*)WMALLOC(sizeof(WOLFSSHD_AUTH), heap, DYNTYPE_SSHD); auth = (WOLFSSHD_AUTH*)WMALLOC(sizeof(WOLFSSHD_AUTH), heap, DYNTYPE_SSHD);
if (auth != NULL) { if (auth != NULL) {
int ret; int ret;
struct passwd* pwInfo;
const char* usr = "sshd";
auth->heap = heap; auth->heap = heap;
auth->conf = conf; auth->conf = conf;
@ -1026,21 +1425,13 @@ WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf)
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
pwInfo = getpwnam(usr); ret = SetDefualtUserID(auth);
if (pwInfo == NULL) { if (ret != WS_SUCCESS) {
/* user name not found on system */ wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting default "
wolfSSH_Log(WS_LOG_INFO, "[SSHD] No sshd user found to use"); "user ID.");
ret = WS_FATAL_ERROR;
} }
} }
if (ret == WS_SUCCESS) {
auth->gid = pwInfo->pw_gid;
auth->uid = pwInfo->pw_uid;
auth->sGid = getgid();
auth->sUid = getuid();
}
/* error case in setting one of the default callbacks */ /* error case in setting one of the default callbacks */
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
(void)wolfSSHD_AuthFreeUser(auth); (void)wolfSSHD_AuthFreeUser(auth);
@ -1069,6 +1460,7 @@ int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth)
int ret = 0; int ret = 0;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Attempting to raise permissions level"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Attempting to raise permissions level");
#ifndef WIN32
if (auth) { if (auth) {
if (setegid(auth->sGid) != 0) { if (setegid(auth->sGid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error rasing gid"); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error rasing gid");
@ -1083,6 +1475,7 @@ int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth)
else { else {
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
} }
#endif
return ret; return ret;
} }
@ -1092,6 +1485,7 @@ int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth)
int wolfSSHD_AuthReducePermissionsUser(WOLFSSHD_AUTH* auth, WUID_T uid, int wolfSSHD_AuthReducePermissionsUser(WOLFSSHD_AUTH* auth, WUID_T uid,
WGID_T gid) WGID_T gid)
{ {
#ifndef WIN32
if (setregid(gid, gid) != 0) { if (setregid(gid, gid) != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user gid"); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user gid");
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
@ -1101,6 +1495,7 @@ int wolfSSHD_AuthReducePermissionsUser(WOLFSSHD_AUTH* auth, WUID_T uid,
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user uid"); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting user uid");
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
#endif
(void)auth; (void)auth;
return WS_SUCCESS; return WS_SUCCESS;
} }
@ -1113,6 +1508,7 @@ int wolfSSHD_AuthReducePermissions(WOLFSSHD_AUTH* auth)
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
flag = wolfSSHD_ConfigGetPrivilegeSeparation(auth->conf); flag = wolfSSHD_ConfigGetPrivilegeSeparation(auth->conf);
#ifndef WIN32
if (flag == WOLFSSHD_PRIV_SEPARAT || flag == WOLFSSHD_PRIV_SANDBOX) { if (flag == WOLFSSHD_PRIV_SEPARAT || flag == WOLFSSHD_PRIV_SANDBOX) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Lowering permissions level"); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Lowering permissions level");
if (auth) { if (auth) {
@ -1130,23 +1526,26 @@ int wolfSSHD_AuthReducePermissions(WOLFSSHD_AUTH* auth)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
} }
} }
#endif
return ret; return ret;
} }
#ifndef WIN32
#if defined(__OSX__) || defined( __APPLE__) #if defined(__OSX__) || defined( __APPLE__)
#define WGETGROUPLIST(x,y,z,w) getgrouplist((x),(y),(int*)(z),(w)) #define WGETGROUPLIST(x,y,z,w) getgrouplist((x),(y),(int*)(z),(w))
#else #else
#define WGETGROUPLIST(x,y,z,w) getgrouplist((x),(y),(z),(w)) #define WGETGROUPLIST(x,y,z,w) getgrouplist((x),(y),(z),(w))
#endif #endif
#endif /* WIN32 */
/* sets the extended groups the user is in, returns WS_SUCCESS on success */ /* sets the extended groups the user is in, returns WS_SUCCESS on success */
int wolfSSHD_AuthSetGroups(const WOLFSSHD_AUTH* auth, const char* usr, int wolfSSHD_AuthSetGroups(const WOLFSSHD_AUTH* auth, const char* usr,
WGID_T gid) WGID_T gid)
{ {
int ret = WS_SUCCESS;
#ifndef WIN32
int grpListSz = 0; int grpListSz = 0;
gid_t* grpList = NULL; gid_t* grpList = NULL;
int ret = WS_SUCCESS;
#if defined(__QNX__) || defined(__QNXNTO__) #if defined(__QNX__) || defined(__QNXNTO__)
/* QNX does not support getting the exact group list size ahead of time, /* QNX does not support getting the exact group list size ahead of time,
@ -1183,7 +1582,11 @@ int wolfSSHD_AuthSetGroups(const WOLFSSHD_AUTH* auth, const char* usr,
WFREE(grpList, auth->heap, DYNTYPE_SSHD); WFREE(grpList, auth->heap, DYNTYPE_SSHD);
} }
} }
#else
WOLFSSH_UNUSED(auth);
WOLFSSH_UNUSED(usr);
WOLFSSH_UNUSED(gid);
#endif
return ret; return ret;
} }
@ -1207,14 +1610,18 @@ WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
const char* localAdr, word16* localPort, const char* RDomain, const char* localAdr, word16* localPort, const char* RDomain,
const char* adr) const char* adr)
{ {
struct group* g = NULL;
WOLFSSHD_CONFIG* ret = NULL; WOLFSSHD_CONFIG* ret = NULL;
if (auth != NULL) { if (auth != NULL) {
struct passwd *p_passwd;
char* gName = NULL; char* gName = NULL;
if (usr != NULL) { if (usr != NULL) {
#ifdef WIN32
//LogonUserEx()
#else
struct passwd* p_passwd;
struct group* g = NULL;
p_passwd = getpwnam((const char *)usr); p_passwd = getpwnam((const char *)usr);
if (p_passwd == NULL) { if (p_passwd == NULL) {
return NULL; return NULL;
@ -1225,6 +1632,7 @@ WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
return NULL; return NULL;
} }
gName = g->gr_name; gName = g->gr_name;
#endif
} }
ret = wolfSSHD_GetUserConf(auth->conf, usr, gName, host, localAdr, ret = wolfSSHD_GetUserConf(auth->conf, usr, gName, host, localAdr,

View File

@ -46,7 +46,7 @@ typedef int (*CallbackCheckUser)(const char* usr);
* found, and negative values if an error occurs during checking. * found, and negative values if an error occurs during checking.
*/ */
typedef int (*CallbackCheckPassword)(const char* usr, const byte* psw, typedef int (*CallbackCheckPassword)(const char* usr, const byte* psw,
word32 pswSz); word32 pswSz, WOLFSSHD_AUTH* authCtx);
/* /*
* Returns WSSHD_AUTH_SUCCESS if public key ok, WSSHD_AUTH_FAILURE if key not * Returns WSSHD_AUTH_SUCCESS if public key ok, WSSHD_AUTH_FAILURE if key not
@ -54,7 +54,7 @@ typedef int (*CallbackCheckPassword)(const char* usr, const byte* psw,
*/ */
typedef int (*CallbackCheckPublicKey)(const char* usr, typedef int (*CallbackCheckPublicKey)(const char* usr,
const WS_UserAuthData_PublicKey* pubKey, const WS_UserAuthData_PublicKey* pubKey,
const char* usrCaKeysFile); const char* usrCaKeysFile, WOLFSSHD_AUTH* authCtx);
WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf); WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf);
int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth); int wolfSSHD_AuthFreeUser(WOLFSSHD_AUTH* auth);
@ -69,4 +69,8 @@ WOLFSSHD_CONFIG* wolfSSHD_AuthGetUserConf(const WOLFSSHD_AUTH* auth,
const char* usr, const char* host, const char* usr, const char* host,
const char* localAdr, word16* localPort, const char* RDomain, const char* localAdr, word16* localPort, const char* RDomain,
const char* adr); const char* adr);
#ifdef _WIN32
HANDLE wolfSSHD_GetAuthToken(const WOLFSSHD_AUTH* auth);
int wolfSSHD_GetHomeDirectory(WOLFSSHD_AUTH* auth, WOLFSSH* ssh, WCHAR* out, int outSz);
#endif
#endif /* WOLFAUTH_H */ #endif /* WOLFAUTH_H */

View File

@ -22,6 +22,10 @@
#include <config.h> #include <config.h>
#endif #endif
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#endif
#ifdef WOLFSSH_SSHD #ifdef WOLFSSH_SSHD
/* functions for parsing out options from a config file and for handling loading /* functions for parsing out options from a config file and for handling loading
* key/certs using the env. filesystem */ * key/certs using the env. filesystem */
@ -47,7 +51,10 @@
#endif #endif
#include "configuration.h" #include "configuration.h"
#ifndef WIN32
#include <dirent.h> #include <dirent.h>
#endif
struct WOLFSSHD_CONFIG { struct WOLFSSHD_CONFIG {
void* heap; void* heap;
@ -854,7 +861,7 @@ static int AddRestrictedCase(WOLFSSHD_CONFIG* config, const char* mtch,
* and makes it point to the newly created conf node */ * and makes it point to the newly created conf node */
static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz) static int HandleMatch(WOLFSSHD_CONFIG** conf, const char* value, int valueSz)
{ {
WOLFSSHD_CONFIG* newConf; WOLFSSHD_CONFIG* newConf = NULL;
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
if (conf == NULL || *conf == NULL || value == NULL) { if (conf == NULL || *conf == NULL || value == NULL) {
@ -1096,7 +1103,7 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
*/ */
int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename) int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
{ {
XFILE f; WFILE *f;
WOLFSSHD_CONFIG* currentConfig; WOLFSSHD_CONFIG* currentConfig;
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
char buf[MAX_LINE_SIZE]; char buf[MAX_LINE_SIZE];
@ -1105,8 +1112,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
if (conf == NULL || filename == NULL) if (conf == NULL || filename == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
f = XFOPEN(filename, "rb"); if (WFOPEN(&f, filename, "rb") != 0) {
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s", wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s",
filename); filename);
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -1124,7 +1130,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
current = current + 1; current = current + 1;
} }
if (currentSz <= 1) { if (currentSz <= 2) { /* \n or \r\n */
continue; /* empty line */ continue; /* empty line */
} }
@ -1138,7 +1144,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
break; break;
} }
} }
XFCLOSE(f); WFCLOSE(f);
SetAuthKeysPattern(conf->authKeysFile); SetAuthKeysPattern(conf->authKeysFile);

File diff suppressed because it is too large Load Diff

View File

@ -188,6 +188,52 @@ typedef struct thread_args {
#define THREAD_RET_SUCCESS 0 #define THREAD_RET_SUCCESS 0
#endif #endif
#ifndef _MSC_VER
#include <semaphore.h>
static sem_t windowSem;
/* capture window change signales */
static void WindowChangeSignal(int sig)
{
sem_post(&windowSem);
(void)sig;
}
static int sendCurrentWindowSize(thread_args* args)
{
struct winsize windowSize = {0,0,0,0};
int ret;
wc_LockMutex(&args->lock);
ioctl(STDOUT_FILENO, TIOCGWINSZ, &windowSize);
ret = wolfSSH_ChangeTerminalSize(args->ssh,
windowSize.ws_col, windowSize.ws_row,
windowSize.ws_xpixel, windowSize.ws_ypixel);
wc_UnLockMutex(&args->lock);
return ret;
}
/* thread for handling window size adjustments */
static THREAD_RET windowMonitor(void* in)
{
thread_args* args;
int ret;
args = (thread_args*)in;
do {
sem_wait(&windowSem);
ret = sendCurrentWindowSize(args);
(void)ret;
} while (1);
return THREAD_RET_SUCCESS;
}
#endif
static THREAD_RET readInput(void* in) static THREAD_RET readInput(void* in)
{ {
byte buf[256]; byte buf[256];
@ -240,7 +286,7 @@ static THREAD_RET readInput(void* in)
static THREAD_RET readPeer(void* in) static THREAD_RET readPeer(void* in)
{ {
byte buf[80]; byte buf[256];
int bufSz = sizeof(buf); int bufSz = sizeof(buf);
thread_args* args = (thread_args*)in; thread_args* args = (thread_args*)in;
int ret = 0; int ret = 0;
@ -257,6 +303,13 @@ static THREAD_RET readPeer(void* in)
FD_SET(fd, &readSet); FD_SET(fd, &readSet);
FD_SET(fd, &errSet); FD_SET(fd, &errSet);
#ifdef USE_WINDOWS_API
/* set handle to use for window resize */
wc_LockMutex(&args->lock);
wolfSSH_SetTerminalResizeCtx(args->ssh, stdoutHandle);
wc_UnLockMutex(&args->lock);
#endif
while (ret >= 0) { while (ret >= 0) {
bytes = select(fd + 1, &readSet, NULL, &errSet, NULL); bytes = select(fd + 1, &readSet, NULL, &errSet, NULL);
wc_LockMutex(&args->lock); wc_LockMutex(&args->lock);
@ -271,7 +324,13 @@ static THREAD_RET readPeer(void* in)
if (ret < 0) if (ret < 0)
err_sys("Extended data read failed."); err_sys("Extended data read failed.");
buf[bufSz - 1] = '\0'; buf[bufSz - 1] = '\0';
#ifdef USE_WINDOWS_API
fprintf(stderr, "%s", buf); fprintf(stderr, "%s", buf);
#else
if (write(STDERR_FILENO, buf, ret) < 0) {
perror("Issue with stderr write ");
}
#endif
} while (ret > 0); } while (ret > 0);
} }
else if (ret <= 0) { else if (ret <= 0) {
@ -334,7 +393,9 @@ static THREAD_RET readPeer(void* in)
fflush(stdout); fflush(stdout);
} }
#else #else
printf("%s", buf); if (write(STDOUT_FILENO, buf, ret) < 0) {
perror("write to stdout error ");
}
fflush(stdout); fflush(stdout);
#endif #endif
} }
@ -636,7 +697,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
} }
else else
#endif #endif
{ if (pubKeyName) {
ret = ClientUsePubKey(pubKeyName, userEcc); ret = ClientUsePubKey(pubKeyName, userEcc);
} }
if (ret != 0) { if (ret != 0) {
@ -735,18 +796,43 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (cmd != NULL || keepOpen == 1) { if (cmd != NULL || keepOpen == 1) {
#if defined(_POSIX_THREADS) #if defined(_POSIX_THREADS)
thread_args arg; thread_args arg;
pthread_t thread[2]; pthread_t thread[3];
arg.ssh = ssh; arg.ssh = ssh;
wc_InitMutex(&arg.lock); wc_InitMutex(&arg.lock);
pthread_create(&thread[0], NULL, readInput, (void*)&arg); sem_init(&windowSem, 0, 0);
pthread_create(&thread[1], NULL, readPeer, (void*)&arg);
pthread_join(thread[1], NULL); /* send current terminal size */
ret = sendCurrentWindowSize(&arg);
signal(SIGWINCH, WindowChangeSignal);
pthread_create(&thread[0], NULL, windowMonitor, (void*)&arg);
pthread_create(&thread[1], NULL, readInput, (void*)&arg);
pthread_create(&thread[2], NULL, readPeer, (void*)&arg);
pthread_join(thread[2], NULL);
pthread_cancel(thread[0]); pthread_cancel(thread[0]);
pthread_cancel(thread[1]);
sem_destroy(&windowSem);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
thread_args arg; thread_args arg;
HANDLE thread[2]; HANDLE thread[2];
/* send the console size to server */
{
CONSOLE_SCREEN_BUFFER_INFO cs;
word32 col = 80, row = 24;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cs) == 0) {
fprintf(stderr, "Failed to get the current console size\r\n");
fprintf(stderr, "Using default col = 80 row = 24\r\n");
}
else {
col = cs.srWindow.Right - cs.srWindow.Left + 1;
row = cs.srWindow.Bottom - cs.srWindow.Top + 1;
}
wolfSSH_ChangeTerminalSize(ssh, col, row, 0, 0);
}
arg.ssh = ssh; arg.ssh = ssh;
arg.rawMode = rawMode; arg.rawMode = rawMode;
wc_InitMutex(&arg.lock); wc_InitMutex(&arg.lock);
@ -792,6 +878,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
#endif #endif
} }
ret = wolfSSH_shutdown(ssh); ret = wolfSSH_shutdown(ssh);
/* do not continue on with shutdown process if peer already disconnected */
if (ret != WS_SOCKET_ERROR_E && wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
err_sys("Sending the shutdown messages failed."); err_sys("Sending the shutdown messages failed.");
} }
@ -799,11 +887,12 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
err_sys("Failed to listen for close messages from the peer."); err_sys("Failed to listen for close messages from the peer.");
} }
}
WCLOSESOCKET(sockFd); WCLOSESOCKET(sockFd);
wolfSSH_free(ssh); wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx); wolfSSH_CTX_free(ctx);
if (ret != WS_SUCCESS) if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E)
err_sys("Closing client stream failed. Connection could have been closed by peer"); err_sys("Closing client stream failed");
ClientFreeBuffers(pubKeyName, privKeyName); ClientFreeBuffers(pubKeyName, privKeyName);
#if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) #if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)

View File

@ -310,6 +310,8 @@ THREAD_RETURN WOLFSSH_THREAD scp_client(void* args)
err_sys("Couldn't copy the file."); err_sys("Couldn't copy the file.");
ret = wolfSSH_shutdown(ssh); ret = wolfSSH_shutdown(ssh);
/* do not continue on with shutdown process if peer already disconnected */
if (ret != WS_SOCKET_ERROR_E && wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
err_sys("Sending the shutdown messages failed."); err_sys("Sending the shutdown messages failed.");
} }
@ -317,10 +319,11 @@ THREAD_RETURN WOLFSSH_THREAD scp_client(void* args)
if (ret != WS_SUCCESS && ret != WS_CHANNEL_CLOSED) { if (ret != WS_SUCCESS && ret != WS_CHANNEL_CLOSED) {
err_sys("Failed to listen for close messages from the peer."); err_sys("Failed to listen for close messages from the peer.");
} }
}
WCLOSESOCKET(sockFd); WCLOSESOCKET(sockFd);
wolfSSH_free(ssh); wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx); wolfSSH_CTX_free(ctx);
if (ret != WS_SUCCESS) if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E)
err_sys("Closing scp stream failed. Connection could have been closed by peer"); err_sys("Closing scp stream failed. Connection could have been closed by peer");
ClientFreeBuffers(pubKeyName, privKeyName); ClientFreeBuffers(pubKeyName, privKeyName);

View File

@ -1032,6 +1032,7 @@ static int doAutopilot(int cmd, char* local, char* remote)
} }
if (remoteAbsPath) { if (remoteAbsPath) {
/* use remote absolute path if provided */
WMEMSET(fullpath, 0, sizeof(fullpath)); WMEMSET(fullpath, 0, sizeof(fullpath));
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1); WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1);
} }
@ -1332,7 +1333,11 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
WFREE(workingDir, NULL, DYNAMIC_TYPE_TMP_BUFFER); WFREE(workingDir, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
if (wolfSSH_shutdown(ssh) != WS_SUCCESS) { if (wolfSSH_shutdown(ssh) != WS_SUCCESS) {
printf("error with wolfSSH_shutdown(), already disconnected?\n"); int rc;
rc = wolfSSH_get_error(ssh);
if (rc != WS_SOCKET_ERROR_E && rc != WS_EOF)
printf("error with wolfSSH_shutdown()\n");
} }
} }
WCLOSESOCKET(sockFd); WCLOSESOCKET(sockFd);

View File

@ -55,3 +55,19 @@ This value is used in the debugging environment for the echoserver's
When you run the echoserver from the debugger, it finds the wolfSSL When you run the echoserver from the debugger, it finds the wolfSSL
DLL in that directory. DLL in that directory.
SSHD Service
-----------
Creating a new servie
`sc.exe create wolfSSHd binpath=D:\work\wolfssh\ide\winvs\Debug\x64\wolfsshd.exe`
Starting wolfSSHd service run the following command in an adminstrator power shell session:
`sc.exe start wolfSSHd -f <sshd_config fils> -h <optionally load host key> -p <optional port number>`
To stop the service run the following in an adminstrator power shell session:
`sc.exe stop wolfSSHd`
To delete the service run
`sc.exe delete wolfSSHd`

View File

@ -18,3 +18,5 @@ EXTRA_DIST+= ide/winvs/testsuite/testsuite.vcxproj
EXTRA_DIST+= ide/winvs/testsuite/testsuite.vcxproj.user EXTRA_DIST+= ide/winvs/testsuite/testsuite.vcxproj.user
EXTRA_DIST+= ide/winvs/wolfsftp-client/wolfsftp-client.vcxproj EXTRA_DIST+= ide/winvs/wolfsftp-client/wolfsftp-client.vcxproj
EXTRA_DIST+= ide/winvs/wolfsftp-client/wolfsftp-client.vcxproj.user EXTRA_DIST+= ide/winvs/wolfsftp-client/wolfsftp-client.vcxproj.user
EXTRA_DIST+= ide/winvs/wolfsshd/wolfsshd.vcxproj
EXTRA_DIST+= ide/winvs/wolfsshd/wolfsshd.vcxproj.user

View File

@ -13,6 +13,7 @@
#define HAVE_AESGCM #define HAVE_AESGCM
#define HAVE_HASHDRBG #define HAVE_HASHDRBG
#define WOLFSSL_AES_COUNTER #define WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_SHA384 #define WOLFSSL_SHA384
#define WOLFSSL_SHA512 #define WOLFSSL_SHA512
#define NO_PSK #define NO_PSK
@ -23,9 +24,58 @@
#define NO_MD4 #define NO_MD4
#define WC_RSA_BLINDING #define WC_RSA_BLINDING
#define WOLFSSL_PUBLIC_MP #define WOLFSSL_PUBLIC_MP
#define SINGLE_THREADED
#define WC_NO_HARDEN #define WC_NO_HARDEN
#define WOLFSSH_TERM #define WOLFSSH_TERM
#ifndef WOLFSSH_TERM
/* Threading is needed for opening a psuedo terminal in the examples */
#define SINGLE_THREADED
#endif
/* adding X509 support */
#if 0
/* Uses CertManager which is in the TLS layer */
#undef WOLFCRYPT_ONLY
#undef WOLFSSL_CERT_GEN
#define WOLFSSL_CERT_GEN
/* Used for comparing IP of peer with IP found in certificate */
#undef WOLFSSL_IP_ALT_NAME
#define WOLFSSL_IP_ALT_NAME
#undef HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS
#undef OPENSSL_ALL
#define OPENSSL_ALL
/* Turn off additional FPKI support checks (Federal PKI) on certificates */
#undef WOLFSSH_NO_FPKI
#define WOLFSSH_NO_FPKI
#undef WOLFSSH_CERTS
#define WOLFSSH_CERTS
#endif
/* default SSHD options */
#if 0
#undef WOLFSSH_SSHD
#define WOLFSSH_SSHD
/* handle shell connections */
#undef WOLFSSH_SHELL
#define WOLFSSH_SHELL
/* handle SCP connection requests */
#undef WOLFSSH_SCP
#define WOLFSSH_SCP
/* handle SFTP connection requests */
#undef WOLFSSH_SFTP
#define WOLFSSH_SFTP
#endif
#endif /* _WIN_USER_SETTINGS_H_ */ #endif /* _WIN_USER_SETTINGS_H_ */

View File

@ -21,6 +21,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsuite", "testsuite\test
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfsftp-client", "wolfsftp-client\wolfsftp-client.vcxproj", "{8DD810D6-159B-4C40-B682-FCA11F9B3680}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfsftp-client", "wolfsftp-client\wolfsftp-client.vcxproj", "{8DD810D6-159B-4C40-B682-FCA11F9B3680}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfsshd", "wolfsshd\wolfsshd.vcxproj", "{9A31DAB4-6292-4ECB-BE35-C60D925C571E}"
ProjectSection(ProjectDependencies) = postProject
{7C2CCF0D-A155-4914-BD1C-9A47C0530E65} = {7C2CCF0D-A155-4914-BD1C-9A47C0530E65}
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -141,6 +146,22 @@ Global
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.Build.0 = Release|Win32 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.Build.0 = Release|Win32
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.ActiveCfg = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.ActiveCfg = Release|x64
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.Build.0 = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.Build.0 = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|Win32.ActiveCfg = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|Win32.Build.0 = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|x64.ActiveCfg = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|x64.Build.0 = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|Win32.ActiveCfg = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|Win32.Build.0 = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|x64.ActiveCfg = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|x64.Build.0 = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|Win32.ActiveCfg = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|Win32.Build.0 = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|x64.ActiveCfg = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|x64.Build.0 = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|Win32.ActiveCfg = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|Win32.Build.0 = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|x64.ActiveCfg = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -35,12 +35,14 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\..\src\certman.c" />
<ClCompile Include="..\..\..\src\internal.c" /> <ClCompile Include="..\..\..\src\internal.c" />
<ClCompile Include="..\..\..\src\io.c" /> <ClCompile Include="..\..\..\src\io.c" />
<ClCompile Include="..\..\..\src\keygen.c" /> <ClCompile Include="..\..\..\src\keygen.c" />
<ClCompile Include="..\..\..\src\log.c" /> <ClCompile Include="..\..\..\src\log.c" />
<ClCompile Include="..\..\..\src\port.c" /> <ClCompile Include="..\..\..\src\port.c" />
<ClCompile Include="..\..\..\src\ssh.c" /> <ClCompile Include="..\..\..\src\ssh.c" />
<ClCompile Include="..\..\..\src\wolfscp.c" />
<ClCompile Include="..\..\..\src\wolfsftp.c" /> <ClCompile Include="..\..\..\src\wolfsftp.c" />
<ClCompile Include="..\..\..\src\wolfterm.c" /> <ClCompile Include="..\..\..\src\wolfterm.c" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\apps\wolfsshd\auth.c" />
<ClCompile Include="..\..\..\apps\wolfsshd\configuration.c" />
<ClCompile Include="..\..\..\apps\wolfsshd\wolfsshd.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{9a31dab4-6292-4ecb-be35-c60d925c571e}</ProjectGuid>
<RootNamespace>wolfsshd</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v100</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v100</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v100</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v100</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Debug\Win32;..\Debug\Win32</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Release\Win32;..\Release\Win32</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WOLFSSL_USER_SETTINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..;..\..\..;..\..\..\..\wolfssl;..\..\..\apps\wolfsshd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Debug\x64;..\Debug\x64</AdditionalLibraryDirectories>
<AdditionalDependencies>wolfssl.lib;wolfssh.lib;ws2_32.lib;secur32.lib;userenv.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WOLFSSL_USER_SETTINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..;..\..\..;..\..\..\..\wolfssl;..\..\..\apps\wolfsshd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>wolfssl.lib;wolfssh.lib;ws2_32.lib;secur32.lib;userenv.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Release\x64;..\Release\x64</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -630,6 +630,35 @@ void CtxResourceFree(WOLFSSH_CTX* ctx)
} }
#ifdef WOLFSSH_TERM
/* default terminal resize handling callbacks */
#ifdef USE_WINDOWS_API
static int WS_WindowsTermResize(WOLFSSH* ssh, word32 col, word32 row, word32 colP,
word32 rowP, void* usrCtx)
{
HPCON* term = (HPCON*)usrCtx;
int ret = WS_SUCCESS;
if (term != NULL) {
HRESULT ret;
COORD sz;
sz.X = col;
sz.Y = row;
ret = ResizePseudoConsole(*term, sz);
if (ret != S_OK) {
WLOG(WS_LOG_ERROR, "Issue with pseudo console resize");
ret = WS_FATAL_ERROR;
}
}
return ret;
}
#endif
#endif /* WOLFSSH_TERM */
WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx) WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
{ {
#if defined(STM32F2) || defined(STM32F4) || defined(FREESCALE_MQX) #if defined(STM32F2) || defined(STM32F4) || defined(FREESCALE_MQX)
@ -722,6 +751,12 @@ WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
ssh->agentEnabled = ctx->agentEnabled; ssh->agentEnabled = ctx->agentEnabled;
#endif #endif
#ifdef WOLFSSH_TERM
#if defined(USE_WINDOWS_API)
ssh->termResizeCb = WS_WindowsTermResize;
#endif
#endif
if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS || if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS ||
BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS || BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS ||
BufferInit(&ssh->extDataBuffer, 0, ctx->heap) != WS_SUCCESS) { BufferInit(&ssh->extDataBuffer, 0, ctx->heap) != WS_SUCCESS) {
@ -6731,7 +6766,7 @@ static int DoChannelRequest(WOLFSSH* ssh,
char term[32]; char term[32];
word32 termSz; word32 termSz;
word32 widthChar, heightRows, widthPixels, heightPixels; word32 widthChar, heightRows, widthPixels, heightPixels;
word32 modesSz; byte opCode = 0;
termSz = (word32)sizeof(term); termSz = (word32)sizeof(term);
ret = GetString(term, &termSz, buf, len, &begin); ret = GetString(term, &termSz, buf, len, &begin);
@ -6743,8 +6778,14 @@ static int DoChannelRequest(WOLFSSH* ssh,
ret = GetUint32(&widthPixels, buf, len, &begin); ret = GetUint32(&widthPixels, buf, len, &begin);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetUint32(&heightPixels, buf, len, &begin); ret = GetUint32(&heightPixels, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&modesSz, buf, len, &begin); /* itterate over op codes */
if (ret == WS_SUCCESS) {
do {
opCode = buf[begin];
begin++;
} while (opCode != 0 && begin < len);
}
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, " term = %s", term); WLOG(WS_LOG_DEBUG, " term = %s", term);
@ -6752,7 +6793,14 @@ static int DoChannelRequest(WOLFSSH* ssh,
WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows); WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows);
WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels); WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels);
WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels); WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels);
WLOG(WS_LOG_DEBUG, " modes = %u", (modesSz - 1) / 5); ssh->curX = widthChar;
ssh->curY = heightRows;
if (ssh->termResizeCb) {
if (ssh->termResizeCb(ssh, widthChar, heightRows, widthPixels,
heightPixels, ssh->termCtx) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
}
}
} }
} }
else else
@ -6802,6 +6850,34 @@ static int DoChannelRequest(WOLFSSH* ssh,
WLOG(WS_LOG_AGENT, "Agent callback not set, not using."); WLOG(WS_LOG_AGENT, "Agent callback not set, not using.");
} }
#endif /* WOLFSSH_AGENT */ #endif /* WOLFSSH_AGENT */
#ifdef WOLFSSH_SHELL
else if (WSTRNCMP(type, "window-change", typeSz) == 0) {
word32 widthChar, heightRows, widthPixels, heightPixels;
ret = GetUint32(&widthChar, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&heightRows, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&widthPixels, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&heightPixels, buf, len, &begin);
if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, " widthChar = %u", widthChar);
WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows);
WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels);
WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels);
ssh->curX = widthChar;
ssh->curY = heightRows;
if (ssh->termResizeCb) {
if (ssh->termResizeCb(ssh, widthChar, heightRows, widthPixels,
heightPixels, ssh->termCtx) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
}
}
}
}
#endif
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
@ -12906,6 +12982,68 @@ static int CreateMode(WOLFSSH* ssh, byte* mode)
} }
int SendChannelTerminalResize(WOLFSSH* ssh, word32 columns, word32 rows,
word32 widthPixels, word32 heightPixels)
{
int ret = WS_SUCCESS;
byte* output;
word32 idx;
WOLFSSH_CHANNEL* channel = NULL;
const char* cType = "window-change";
word32 typeSz = 0;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh,
ssh->defaultPeerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
if (ret == WS_SUCCESS) {
typeSz = (word32)sizeof(cType) - 1;
ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ +
typeSz + BOOLEAN_SZ + (4 * UINT32_SZ));
}
if (ret == WS_SUCCESS) {
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_REQUEST;
c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ;
c32toa(typeSz, output + idx);
idx += LENGTH_SZ;
WMEMCPY(output + idx, cType, typeSz);
idx += typeSz;
output[idx++] = 0;
c32toa(columns, output + idx);
idx += UINT32_SZ;
c32toa(rows, output + idx);
idx += UINT32_SZ;
c32toa(widthPixels, output + idx);
idx += UINT32_SZ;
c32toa(heightPixels, output + idx);
idx += UINT32_SZ;
ssh->outputBuffer.length = idx;
WLOG(WS_LOG_INFO, "Sending Channel Request: ");
WLOG(WS_LOG_INFO, " channelId = %u", channel->peerChannel);
WLOG(WS_LOG_INFO, " type = %s", cType);
WLOG(WS_LOG_INFO, " wantReply = %u", 0);
ret = BundlePacket(ssh);
}
if (ret == WS_SUCCESS)
ret = wolfSSH_SendPacket(ssh);
return ret;
}
/* sends request for pseudo-terminal (rfc 4254) /* sends request for pseudo-terminal (rfc 4254)
* returns WS_SUCCESS on success */ * returns WS_SUCCESS on success */
int SendChannelTerminalRequest(WOLFSSH* ssh) int SendChannelTerminalRequest(WOLFSSH* ssh)

View File

@ -1316,6 +1316,41 @@ void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH* ssh)
} }
/* Used to resize terminal window with shell connections
* returns WS_SUCCESS on success */
int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32 columns, word32 rows,
word32 widthPixels, word32 heightPixels)
{
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChangeWindowDimension()");
if (ssh == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
ret = SendChannelTerminalResize(ssh, columns, rows, widthPixels,
heightPixels);
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChangeWindowDimension(), ret = %d",
ret);
return ret;
}
void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh, WS_CallbackTerminalSize cb)
{
ssh->termResizeCb = cb;
}
void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx)
{
ssh->termCtx = usrCtx;
}
/* Used to set the channel request type sent in wolfSSH connect. The default /* Used to set the channel request type sent in wolfSSH connect. The default
* type set is shell if this function is not called. * type set is shell if this function is not called.
* *

View File

@ -1095,7 +1095,7 @@ static int ScpCheckForRename(WOLFSSH* ssh, int cmdSz)
WSTRNCPY(buf, ssh->scpBasePath, cmdSz); WSTRNCPY(buf, ssh->scpBasePath, cmdSz);
buf[sz] = '\0'; buf[sz] = '\0';
WSTRNCAT(buf, "/..", sizeof("/..")); WSTRNCAT(buf, "/..", DEFAULT_SCP_MSG_SZ);
idx = wolfSSH_CleanPath(ssh, buf); idx = wolfSSH_CleanPath(ssh, buf);
if (idx < 0) { if (idx < 0) {
@ -1143,7 +1143,7 @@ static int ScpCheckForRename(WOLFSSH* ssh, int cmdSz)
WLOG(WS_LOG_DEBUG, "scp: renaming from %s to %s", WLOG(WS_LOG_DEBUG, "scp: renaming from %s to %s",
ssh->scpFileName, ssh->scpBasePath + idx); ssh->scpFileName, ssh->scpBasePath + idx);
ssh->scpFileReName = ssh->scpFileName; ssh->scpFileReName = ssh->scpFileName;
WSTRNCPY(ssh->scpFileName, ssh->scpBasePath + idx, sz); WSTRNCPY(ssh->scpFileName, ssh->scpBasePath + idx, sz + 1);
ssh->scpFileName[sz] = '\0'; ssh->scpFileName[sz] = '\0';
ssh->scpFileNameSz = sz; ssh->scpFileNameSz = sz;
*((char*)ssh->scpBasePath + idx) = '\0'; *((char*)ssh->scpBasePath + idx) = '\0';
@ -1158,15 +1158,16 @@ static int ScpCheckForRename(WOLFSSH* ssh, int cmdSz)
* returns WS_SUCCESS on success */ * returns WS_SUCCESS on success */
static int ParseBasePathHelper(WOLFSSH* ssh, int cmdSz) static int ParseBasePathHelper(WOLFSSH* ssh, int cmdSz)
{ {
int ret = 0; int ret;
ret = ScpCheckForRename(ssh, cmdSz); ret = ScpCheckForRename(ssh, cmdSz);
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
{ if (ret == WS_SUCCESS) {
ScpSendCtx ctx; ScpSendCtx ctx;
WMEMSET(&ctx, 0, sizeof(ScpSendCtx)); WMEMSET(&ctx, 0, sizeof(ScpSendCtx));
if (ScpPushDir(&ctx, ssh->scpBasePath, ssh->ctx->heap) != WS_SUCCESS) { if (ScpPushDir(&ctx, ssh->scpBasePath, ssh->ctx->heap) != WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "scp : issue opening base dir"); WLOG(WS_LOG_DEBUG, "scp : issue opening base dir");
ret = WS_FATAL_ERROR;
} }
else { else {
ret = ScpPopDir(&ctx, ssh->ctx->heap); ret = ScpPopDir(&ctx, ssh->ctx->heap);
@ -1261,7 +1262,8 @@ int ParseScpCommand(WOLFSSH* ssh)
ssh->scpBasePath = cmd + idx; ssh->scpBasePath = cmd + idx;
#endif #endif
ret = ParseBasePathHelper(ssh, cmdSz); ret = ParseBasePathHelper(ssh, cmdSz);
if (wolfSSH_CleanPath(ssh, (char*)ssh->scpBasePath) < 0) if (ret == WS_SUCCESS &&
wolfSSH_CleanPath(ssh, (char*)ssh->scpBasePath) < 0)
ret = WS_FATAL_ERROR; ret = WS_FATAL_ERROR;
} }
break; break;
@ -1766,29 +1768,42 @@ static INLINE int wolfSSH_LastError(void)
return errno; return errno;
} }
/* set file access and modification times /* set file access and modification times
* Returns WS_SUCCESS on success, or negative upon error */ * Returns WS_SUCCESS on success, or negative upon error */
static int SetTimestampInfo(const char* fileName, word64 mTime, word64 aTime) static int SetTimestampInfo(const char* fileName, word64 mTime, word64 aTime)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
#ifdef USE_WINDOWS_API
struct _utimbuf tmp;
int fd;
#else
struct timeval tmp[2]; struct timeval tmp[2];
#endif
if (fileName == NULL) if (fileName == NULL)
ret= WS_BAD_ARGUMENT; ret= WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
#ifdef USE_WINDOWS_API
tmp.actime = aTime;
tmp.modtime = mTime;
_sopen_s(&fd, fileName, _O_RDWR, _SH_DENYNO, 0);
_futime(fd, &tmp);
_close(fd);
#else
tmp[0].tv_sec = (time_t)aTime; tmp[0].tv_sec = (time_t)aTime;
tmp[0].tv_usec = 0; tmp[0].tv_usec = 0;
tmp[1].tv_sec = (time_t)mTime; tmp[1].tv_sec = (time_t)mTime;
tmp[1].tv_usec = 0; tmp[1].tv_usec = 0;
ret = WUTIMES(fileName, tmp); ret = WUTIMES(fileName, tmp);
#endif
} }
return ret; return ret;
} }
/* Default SCP receive callback, called by wolfSSH when application has called /* Default SCP receive callback, called by wolfSSH when application has called
* wolfSSH_accept() and a new SCP request has been received for an incomming * wolfSSH_accept() and a new SCP request has been received for an incomming
* file or directory. * file or directory.
@ -2079,7 +2094,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
return ret; return ret;
} }
static int GetFileSize(WFILE* fp, word32* fileSz) static int _GetFileSize(WFILE* fp, word32* fileSz)
{ {
if (fp == NULL || fileSz == NULL) if (fp == NULL || fileSz == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
@ -2103,6 +2118,22 @@ static int GetFileStats(ScpSendCtx* ctx, const char* fileName,
} }
/* get file stats for times and mode */ /* get file stats for times and mode */
#if defined(USE_WINDOWS_API)
BOOL error;
error = !WS_GetFileAttributesExA(fileName, &ctx->s, NULL);
if (error)
return WS_BAD_FILE_E;
*aTime = ((word64)ctx->s.ftLastAccessTime.dwHighDateTime << 32) |
(word64)ctx->s.ftLastAccessTime.dwLowDateTime;
*mTime = ((word64)ctx->s.ftLastWriteTime.dwHighDateTime << 32) |
(word64)ctx->s.ftLastWriteTime.dwLowDateTime;
*fileMode = 0555 |
(ctx->s.dwFileAttributes | FILE_ATTRIBUTE_READONLY ? 0 : 0200);
*fileMode |= (ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0x4000 : 0;
#else
if (WSTAT(fileName, &ctx->s) < 0) { if (WSTAT(fileName, &ctx->s) < 0) {
ret = WS_BAD_FILE_E; ret = WS_BAD_FILE_E;
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
@ -2112,7 +2143,8 @@ static int GetFileStats(ScpSendCtx* ctx, const char* fileName,
ret = WS_SUCCESS; ret = WS_SUCCESS;
} }
#endif #endif
} else { }
else {
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
if (ctx->s.fattribute & ARDONLY) { if (ctx->s.fattribute & ARDONLY) {
*fileMode = 0x124; /* octal 444 */ *fileMode = 0x124; /* octal 444 */
@ -2132,6 +2164,7 @@ static int GetFileStats(ScpSendCtx* ctx, const char* fileName,
*fileMode = ctx->s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); *fileMode = ctx->s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
#endif #endif
} }
#endif
return ret; return ret;
} }
@ -2155,6 +2188,24 @@ static ScpDir* ScpNewDir(const char* path, void* heap)
} }
entry->next = NULL; entry->next = NULL;
#ifdef USE_WINDOWS_API
{
char sPath[MAX_PATH];
int isDir;
/* add wildcard to get full directory */
WSNPRINTF(sPath, MAX_PATH, "%s/*", path);
entry->dir = (HANDLE)WS_FindFirstFileA(sPath,
sPath, sizeof(sPath), &isDir, heap);
if (entry->dir == INVALID_HANDLE_VALUE) {
WFREE(entry, heap, DYNTYPE_SCPDIR);
WLOG(WS_LOG_ERROR, scpError, "opendir failed on directory",
WS_INVALID_PATH_E);
return NULL;
}
}
#else
if (WOPENDIR(NULL, heap, &entry->dir, path) != 0 if (WOPENDIR(NULL, heap, &entry->dir, path) != 0
#ifndef WOLFSSL_NUCLEUS #ifndef WOLFSSL_NUCLEUS
|| entry->dir == NULL || entry->dir == NULL
@ -2165,7 +2216,7 @@ static ScpDir* ScpNewDir(const char* path, void* heap)
WS_INVALID_PATH_E); WS_INVALID_PATH_E);
return NULL; return NULL;
} }
#endif
return entry; return entry;
} }
@ -2209,7 +2260,11 @@ int ScpPopDir(ScpSendCtx* ctx, void* heap)
} }
if (entry != NULL) { if (entry != NULL) {
#ifdef USE_WINDOWS_API
FindClose(entry->dir);
#else
WCLOSEDIR(&entry->dir); WCLOSEDIR(&entry->dir);
#endif
WFREE(entry, heap, DYNTYPE_SCPDIR); WFREE(entry, heap, DYNTYPE_SCPDIR);
} }
@ -2268,6 +2323,31 @@ static int FindNextDirEntry(ScpSendCtx* ctx)
} }
} }
ctx->nextError = 1; ctx->nextError = 1;
#elif defined(USE_WINDOWS_API)
do {
char realFileName[MAX_PATH];
int sz;
if (WS_FindNextFileA(ctx->currentDir->dir,
realFileName, sizeof(realFileName)) == 0) {
return WS_FATAL_ERROR;
}
sz = (int)WSTRLEN(realFileName);
if (ctx->entry != NULL) {
WFREE(ctx->entry, NULL, DYNTYPE_SCPDIR);
ctx->entry = NULL;
}
ctx->entry = (char*)WMALLOC(sz + 1, NULL, DYNTYPE_SCPDIR);
if (ctx->entry == NULL) {
return WS_MEMORY_E;
}
WMEMCPY(ctx->entry, realFileName, sz);
ctx->entry[sz] = '\0';
} while ((ctx->entry != NULL) &&
(WSTRNCMP(ctx->entry, ".", 1) == 0 ||
WSTRNCMP(ctx->entry, "..", 2) == 0));
#else #else
do { do {
ctx->entry = WREADDIR(&ctx->currentDir->dir); ctx->entry = WREADDIR(&ctx->currentDir->dir);
@ -2293,6 +2373,8 @@ int ScpFileIsDir(ScpSendCtx* ctx)
{ {
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
return (ctx->s.fattribute & ADIRENT); return (ctx->s.fattribute & ADIRENT);
#elif defined(USE_WINDOWS_API)
return (ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
#else #else
return S_ISDIR(ctx->s.st_mode); return S_ISDIR(ctx->s.st_mode);
#endif #endif
@ -2302,6 +2384,8 @@ static int ScpFileIsFile(ScpSendCtx* ctx)
{ {
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
return (ctx->s.fattribute != ADIRENT); return (ctx->s.fattribute != ADIRENT);
#elif defined(USE_WINDOWS_API)
return ((ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
#else #else
return S_ISREG(ctx->s.st_mode); return S_ISREG(ctx->s.st_mode);
#endif #endif
@ -2332,8 +2416,15 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
dirNameLen = (int)WSTRLEN(sendCtx->dirName); dirNameLen = (int)WSTRLEN(sendCtx->dirName);
#ifdef WOLFSSL_NUCLEUS #if defined(WOLFSSL_NUCLEUS)
dNameLen = (int)WSTRLEN(sendCtx->currentDir->dir.lfname); dNameLen = (int)WSTRLEN(sendCtx->currentDir->dir.lfname);
#elif defined(USE_WINDOWS_API)
{
char path[MAX_PATH];
GetFullPathNameA(fileName, MAX_PATH, path, NULL);
dNameLen = (int)WSTRLEN(path);
}
#else #else
dNameLen = (int)WSTRLEN(sendCtx->entry->d_name); dNameLen = (int)WSTRLEN(sendCtx->entry->d_name);
#endif #endif
@ -2354,6 +2445,11 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
if (wolfSSH_CleanPath(ssh, filePath) < 0) { if (wolfSSH_CleanPath(ssh, filePath) < 0) {
ret = WS_SCP_ABORT; ret = WS_SCP_ABORT;
} }
#elif defined(USE_WINDOWS_API)
WSTRNCAT(filePath, sendCtx->entry,
DEFAULT_SCP_FILE_NAME_SZ);
WSTRNCPY(fileName, sendCtx->entry,
DEFAULT_SCP_FILE_NAME_SZ);
#else #else
WSTRNCAT(filePath, sendCtx->entry->d_name, WSTRNCAT(filePath, sendCtx->entry->d_name,
DEFAULT_SCP_FILE_NAME_SZ); DEFAULT_SCP_FILE_NAME_SZ);
@ -2387,7 +2483,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = GetFileSize(sendCtx->fp, totalFileSz); ret = _GetFileSize(sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp); ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp);
@ -2538,7 +2634,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileSize(sendCtx->fp, totalFileSz); ret = _GetFileSize(sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileStats(sendCtx, peerRequest, mTime, aTime, fileMode); ret = GetFileStats(sendCtx, peerRequest, mTime, aTime, fileMode);

View File

@ -2500,16 +2500,15 @@ static void getDate(char* buf, int len, struct tm* t)
* return WS_SUCCESS on success */ * return WS_SUCCESS on success */
static int SFTP_CreateLongName(WS_SFTPNAME* name) static int SFTP_CreateLongName(WS_SFTPNAME* name)
{ {
#if defined(XGMTIME) && defined(XSNPRINTF)
char sizeStr[32]; char sizeStr[32];
char perm[11]; char perm[11];
int linkCount = 1; /* @TODO set to correct value */ int linkCount = 1; /* @TODO set to correct value */
#if defined(XGMTIME) && defined(XSNPRINTF)
char date[WS_DATE_SIZE + 1]; /* +1 for null terminator */ char date[WS_DATE_SIZE + 1]; /* +1 for null terminator */
struct tm* localTime = NULL; struct tm* localTime = NULL;
#endif
WS_SFTP_FILEATRB* atr;
int i; int i;
WS_SFTP_FILEATRB* atr;
#endif
int totalSz = 0; int totalSz = 0;
if (name == NULL) { if (name == NULL) {

View File

@ -582,6 +582,11 @@ static int wolfSSH_DoControlSeq(WOLFSSH* ssh, WOLFSSH_HANDLE handle, byte* buf,
i += 1; /* for 'h' or 'l' */ i += 1; /* for 'h' or 'l' */
break; break;
case 'X':
/* @TODO (ECH) Erase <n> number of characters on current line */
break;
default: default:
WLOG(WS_LOG_DEBUG, "Unknown control sequence char:%c", c); WLOG(WS_LOG_DEBUG, "Unknown control sequence char:%c", c);
i = *idx; i = *idx;

View File

@ -799,6 +799,12 @@ struct WOLFSSH {
#ifdef WOLFSSH_FWD #ifdef WOLFSSH_FWD
void* fwdCbCtx; void* fwdCbCtx;
#endif /* WOLFSSH_FWD */ #endif /* WOLFSSH_FWD */
#ifdef WOLFSSH_TERM
WS_CallbackTerminalSize termResizeCb;
void* termCtx;
word32 curX; /* current terminal width */
word32 curY; /* current terminal height */
#endif
}; };
@ -922,6 +928,8 @@ WOLFSSH_LOCAL int SendChannelExit(WOLFSSH*, word32, int);
WOLFSSH_LOCAL int SendChannelData(WOLFSSH*, word32, byte*, word32); WOLFSSH_LOCAL int SendChannelData(WOLFSSH*, word32, byte*, word32);
WOLFSSH_LOCAL int SendChannelWindowAdjust(WOLFSSH*, word32, word32); WOLFSSH_LOCAL int SendChannelWindowAdjust(WOLFSSH*, word32, word32);
WOLFSSH_LOCAL int SendChannelRequest(WOLFSSH*, byte*, word32); WOLFSSH_LOCAL int SendChannelRequest(WOLFSSH*, byte*, word32);
WOLFSSH_LOCAL int SendChannelTerminalResize(WOLFSSH*, word32, word32, word32,
word32);
WOLFSSH_LOCAL int SendChannelTerminalRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int SendChannelTerminalRequest(WOLFSSH* ssh);
WOLFSSH_LOCAL int SendChannelAgentRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int SendChannelAgentRequest(WOLFSSH* ssh);
WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH*, word32, int); WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH*, word32, int);

View File

@ -48,10 +48,16 @@ extern "C" {
#else #else
#define WISSPACE isspace #define WISSPACE isspace
#endif #endif
#ifdef USE_WINDOWS_API
#define WUID_T int
#define WGID_T int
#define WPASSWD struct passwd
#else
#define WUID_T uid_t #define WUID_T uid_t
#define WGID_T gid_t #define WGID_T gid_t
#define WPASSWD struct passwd #define WPASSWD struct passwd
#endif #endif
#endif
/* setup memory handling */ /* setup memory handling */
#ifndef WMALLOC_USER #ifndef WMALLOC_USER
@ -366,6 +372,8 @@ extern "C" {
#define WBADFILE NULL #define WBADFILE NULL
#ifdef WOLFSSL_VXWORKS #ifdef WOLFSSL_VXWORKS
#define WUTIMES(f,t) (WS_SUCCESS) #define WUTIMES(f,t) (WS_SUCCESS)
#elif defined(USE_WINDOWS_API)
#include <sys/utime.h>
#else #else
#define WUTIMES(f,t) utimes((f),(t)) #define WUTIMES(f,t) utimes((f),(t))
#endif #endif
@ -451,7 +459,7 @@ extern "C" {
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
#define WSTRNCPY(s1,s2,n) strncpy_s((s1),(n),(s2),(n)) #define WSTRNCPY(s1,s2,n) strncpy_s((s1),(n),(s2),(n))
#define WSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) #define WSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#define WSNPRINTF(s,n,f,...) _snprintf_s((s),(n),(n),(f),##__VA_ARGS__) #define WSNPRINTF(s,n,f,...) _snprintf_s((s),(n),_TRUNCATE,(f),##__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) _vsnprintf_s((s),(n),(n),(f),##__VA_ARGS__) #define WVSNPRINTF(s,n,f,...) _vsnprintf_s((s),(n),(n),(f),##__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_s((s1),(s2),(s3)) #define WSTRTOK(s1,s2,s3) strtok_s((s1),(s2),(s3))
#elif defined(MICROCHIP_MPLAB_HARMONY) || defined(MICROCHIP_PIC32) #elif defined(MICROCHIP_MPLAB_HARMONY) || defined(MICROCHIP_PIC32)

View File

@ -283,6 +283,12 @@ typedef enum {
WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*); WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*);
WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH*); WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH*);
WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH*, byte, byte*, word32); WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH*, byte, byte*, word32);
WOLFSSH_API int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32, word32,
word32, word32);
typedef int (*WS_CallbackTerminalSize)(WOLFSSH*, word32, word32, word32,
word32, void*);
void wolfSSH_SetTerminalResizeCb(WOLFSSH*, WS_CallbackTerminalSize);
void wolfSSH_SetTerminalResizeCtx(WOLFSSH*, void*);
enum WS_HighwaterSide { enum WS_HighwaterSide {

View File

@ -76,13 +76,16 @@ enum WS_ScpFileStates {
#include <errno.h> #include <errno.h>
typedef struct ScpSendCtx { typedef struct ScpSendCtx {
#ifndef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
struct dirent* entry; /* file entry, from readdir() */
struct stat s; /* stat info from file */
#else
int fd; /* file descriptor, in the case of Nucleus fp points to fd */ int fd; /* file descriptor, in the case of Nucleus fp points to fd */
DSTAT s; DSTAT s;
int nextError; int nextError;
#elif defined(USE_WINDOWS_API)
char* entry;
WIN32_FILE_ATTRIBUTE_DATA s;
#else
struct dirent* entry; /* file entry, from readdir() */
struct stat s; /* stat info from file */
#endif #endif
WFILE* fp; /* file pointer */ WFILE* fp; /* file pointer */
struct ScpDir* currentDir; /* dir being copied, stack */ struct ScpDir* currentDir; /* dir being copied, stack */