Merge branch 'master' into pull-reqs/cca01a4_WOLFSSH_FTP_FSETSTAT

pull/551/head
JacobBarthelmeh 2023-09-15 15:33:59 -06:00 committed by GitHub
commit d84e3b3f4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 3083 additions and 821 deletions

2
.gitignore vendored
View File

@ -74,8 +74,10 @@ client.plist
*.sdf *.sdf
*.v11.suo *.v11.suo
*.vcxproj.filters *.vcxproj.filters
*.vcxproj.user
*.opensdf *.opensdf
*.pdb *.pdb
.vs
Debug Debug
Release Release
DLL Debug DLL Debug

View File

@ -22,6 +22,12 @@
#include <config.h> #include <config.h>
#endif #endif
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.h>
#endif
#ifdef WOLFSSH_SSHD #ifdef WOLFSSH_SSHD
#ifdef __linux__ #ifdef __linux__
@ -30,7 +36,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 +78,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 +155,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 +342,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,35 +426,16 @@ 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 };
void SetAuthKeysPattern(const char* pattern) void SetAuthKeysPattern(const char* pattern)
{ {
@ -451,6 +445,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;
@ -481,7 +476,7 @@ static int ResolveAuthKeysPath(const char* homeDir, char* resolved)
if (homeDirSz + 1 + WSTRLEN(suffix) >= MAX_PATH_SZ) { if (homeDirSz + 1 + WSTRLEN(suffix) >= MAX_PATH_SZ) {
wolfSSH_Log(WS_LOG_ERROR, wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Path for key file larger than max allowed"); "[SSHD] Path for key file larger than max allowed");
ret = WS_FATAL_ERROR; ret = WS_FATAL_ERROR;
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
@ -496,23 +491,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(NULL, &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 = WFGETS(lineBuf, MAX_LINE_SZ, f)) != NULL) {
currentSz = (word32)WSTRLEN(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 != WBADFILE) {
WFCLOSE(NULL, 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 +667,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 +1090,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,22 +1188,40 @@ 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;
}
else {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error getting users token.");
ret = WOLFSSH_USERAUTH_FAILURE;
}
#else
ret = WOLFSSH_USERAUTH_SUCCESS; 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;
} }
else if (rc == WSSHD_AUTH_FAILURE) { else if (rc == WSSHD_AUTH_FAILURE) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key not authorized."); wolfSSH_Log(WS_LOG_INFO,
"[SSHD] Public key not authorized.");
ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY; ret = WOLFSSH_USERAUTH_INVALID_PUBLICKEY;
} }
else { else {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error checking public key."); wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error checking public key.");
ret = WOLFSSH_USERAUTH_FAILURE; ret = WOLFSSH_USERAUTH_FAILURE;
} }
} }
@ -939,7 +1313,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 +1331,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 +1352,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 +1363,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 +1401,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;
@ -1004,7 +1409,8 @@ WOLFSSHD_AUTH* wolfSSHD_AuthCreateUser(void* heap, const WOLFSSHD_CONFIG* conf)
/* set the default user checking based on build */ /* set the default user checking based on build */
ret = SetDefaultUserCheck(auth); ret = SetDefaultUserCheck(auth);
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error setting default user check."); wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error setting default user check.");
} }
/* set the default password checking based on build */ /* set the default password checking based on build */
@ -1026,21 +1432,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 +1467,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 +1482,7 @@ int wolfSSHD_AuthRaisePermissions(WOLFSSHD_AUTH* auth)
else { else {
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
} }
#endif
return ret; return ret;
} }
@ -1092,6 +1492,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 +1502,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 +1515,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 +1533,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 +1589,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 +1617,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 +1639,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,12 @@
#include <config.h> #include <config.h>
#endif #endif
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.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 +53,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;
@ -64,6 +73,7 @@ struct WOLFSSHD_CONFIG {
char* listenAddress; char* listenAddress;
char* authKeysFile; char* authKeysFile;
char* forceCmd; char* forceCmd;
char* pidFile;
WOLFSSHD_CONFIG* next; /* next config in list */ WOLFSSHD_CONFIG* next; /* next config in list */
long loginTimer; long loginTimer;
word16 port; word16 port;
@ -76,6 +86,7 @@ struct WOLFSSHD_CONFIG {
}; };
int CountWhitespace(const char* in, int inSz, byte inv); int CountWhitespace(const char* in, int inSz, byte inv);
int SetFileString(char** dst, const char* src, void* heap);
/* convert a string into seconds, handles if 'm' for minutes follows the string /* convert a string into seconds, handles if 'm' for minutes follows the string
* number, i.e. 2m * number, i.e. 2m
@ -294,6 +305,7 @@ void wolfSSHD_ConfigFree(WOLFSSHD_CONFIG* conf)
FreeString(&current->authKeysFile, heap); FreeString(&current->authKeysFile, heap);
FreeString(&current->hostKeyFile, heap); FreeString(&current->hostKeyFile, heap);
FreeString(&current->hostCertFile, heap); FreeString(&current->hostCertFile, heap);
FreeString(&current->pidFile, heap);
WFREE(current, heap, DYNTYPE_SSHD); WFREE(current, heap, DYNTYPE_SSHD);
current = next; current = next;
@ -330,9 +342,10 @@ enum {
OPT_FORCE_CMD = 19, OPT_FORCE_CMD = 19,
OPT_HOST_CERT = 20, OPT_HOST_CERT = 20,
OPT_TRUSTED_USER_CA_KEYS = 21, OPT_TRUSTED_USER_CA_KEYS = 21,
OPT_PIDFILE = 22,
}; };
enum { enum {
NUM_OPTIONS = 22 NUM_OPTIONS = 23
}; };
static const CONFIG_OPTION options[NUM_OPTIONS] = { static const CONFIG_OPTION options[NUM_OPTIONS] = {
@ -358,6 +371,7 @@ static const CONFIG_OPTION options[NUM_OPTIONS] = {
{OPT_FORCE_CMD, "ForceCommand"}, {OPT_FORCE_CMD, "ForceCommand"},
{OPT_HOST_CERT, "HostCertificate"}, {OPT_HOST_CERT, "HostCertificate"},
{OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"}, {OPT_TRUSTED_USER_CA_KEYS, "TrustedUserCAKeys"},
{OPT_PIDFILE, "PidFile"},
}; };
/* returns WS_SUCCESS on success */ /* returns WS_SUCCESS on success */
@ -658,7 +672,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
char** fileNames = NULL; char** fileNames = NULL;
/* Count up the number of files */ /* Count up the number of files */
while ((dir = WREADDIR(&d)) != NULL) { while ((dir = WREADDIR(NULL, &d)) != NULL) {
/* Skip sub-directories */ /* Skip sub-directories */
#if defined(__QNX__) || defined(__QNXNTO__) #if defined(__QNX__) || defined(__QNXNTO__)
struct stat s; struct stat s;
@ -672,7 +686,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
fileCount++; fileCount++;
} }
} }
WREWINDDIR(&d); WREWINDDIR(NULL, &d);
if (fileCount > 0) { if (fileCount > 0) {
fileNames = (char**)WMALLOC(fileCount * sizeof(char*), fileNames = (char**)WMALLOC(fileCount * sizeof(char*),
@ -684,7 +698,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
i = 0; i = 0;
while (i < fileCount && (dir = WREADDIR(&d)) != NULL) { while (i < fileCount && (dir = WREADDIR(NULL, &d)) != NULL) {
/* Skip sub-directories */ /* Skip sub-directories */
#if defined(__QNX__) || defined(__QNXNTO__) #if defined(__QNX__) || defined(__QNXNTO__)
struct stat s; struct stat s;
@ -752,7 +766,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
WFREE(fileNames, conf->heap, DYNTYPE_PATH); WFREE(fileNames, conf->heap, DYNTYPE_PATH);
} }
} }
WCLOSEDIR(&d); WCLOSEDIR(NULL, &d);
} }
else { else {
/* Bad directory */ /* Bad directory */
@ -849,7 +863,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) {
@ -999,6 +1013,9 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt,
/* TODO: Add logic to check if file exists? */ /* TODO: Add logic to check if file exists? */
ret = wolfSSHD_ConfigSetUserCAKeysFile(*conf, value); ret = wolfSSHD_ConfigSetUserCAKeysFile(*conf, value);
break; break;
case OPT_PIDFILE:
ret = SetFileString(&(*conf)->pidFile, value, (*conf)->heap);
break;
default: default:
break; break;
} }
@ -1070,8 +1087,13 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
} }
} }
else { else {
#ifdef WOLFSSH_IGNORE_UNKNOWN_CONFIG
wolfSSH_Log(WS_LOG_DEBUG, "[SSHD] ignoring config line %s.", l);
ret = WS_SUCCESS;
#else
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error parsing config line."); wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error parsing config line.");
ret = WS_FATAL_ERROR; ret = WS_FATAL_ERROR;
#endif
} }
return ret; return ret;
@ -1083,7 +1105,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];
@ -1092,8 +1114,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(NULL, &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;
@ -1111,7 +1132,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 */
} }
@ -1125,7 +1146,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
break; break;
} }
} }
XFCLOSE(f); WFCLOSE(NULL, f);
SetAuthKeysPattern(conf->authKeysFile); SetAuthKeysPattern(conf->authKeysFile);
@ -1288,7 +1309,7 @@ char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf)
return ret; return ret;
} }
static int SetFileString(char** dst, const char* src, void* heap) int SetFileString(char** dst, const char* src, void* heap)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
@ -1420,4 +1441,20 @@ long wolfSSHD_ConfigGetGraceTime(const WOLFSSHD_CONFIG* conf)
return ret; return ret;
} }
/* Used to save out the PID of SSHD to a file */
void wolfSSHD_ConfigSavePID(const WOLFSSHD_CONFIG* conf)
{
FILE* f;
char buf[12]; /* large enough to hold 'int' type with null terminator */
WMEMSET(buf, 0, sizeof(buf));
if (WFOPEN(NULL, &f, conf->pidFile, "wb") == 0) {
WSNPRINTF(buf, sizeof(buf), "%d", getpid());
WFWRITE(NULL, buf, 1, WSTRLEN(buf), f);
WFCLOSE(NULL, f);
}
}
#endif /* WOLFSSH_SSHD */ #endif /* WOLFSSH_SSHD */

View File

@ -56,6 +56,7 @@ WOLFSSHD_CONFIG* wolfSSHD_GetUserConf(const WOLFSSHD_CONFIG* conf,
const char* usr, const char* grp, const char* host, const char* usr, const char* grp, 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);
void wolfSSHD_ConfigSavePID(const WOLFSSHD_CONFIG* conf);
#ifdef WOLFSSHD_UNIT_TEST #ifdef WOLFSSHD_UNIT_TEST
int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, int lSz); int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, int lSz);

View File

@ -33,7 +33,7 @@ static void CleanupWildcardTest(void)
char filepath[MAX_PATH*2]; /* d_name is max_path long */ char filepath[MAX_PATH*2]; /* d_name is max_path long */
if (!WOPENDIR(NULL, NULL, &dir, "./sshd_config.d/")) { if (!WOPENDIR(NULL, NULL, &dir, "./sshd_config.d/")) {
while ((d = WREADDIR(&dir)) != NULL) { while ((d = WREADDIR(NULL, &dir)) != NULL) {
#if defined(__QNX__) || defined(__QNXNTO__) #if defined(__QNX__) || defined(__QNXNTO__)
struct stat s; struct stat s;
@ -48,7 +48,7 @@ static void CleanupWildcardTest(void)
WREMOVE(0, filepath); WREMOVE(0, filepath);
} }
} }
WCLOSEDIR(&dir); WCLOSEDIR(NULL, &dir);
WRMDIR(0, "./sshd_config.d/"); WRMDIR(0, "./sshd_config.d/");
} }
} }
@ -75,15 +75,15 @@ static int SetupWildcardTest(void)
"./sshd_config.d/"); "./sshd_config.d/");
} }
WFOPEN(&f, filepath, "w"); WFOPEN(NULL, &f, filepath, "w");
if (f) { if (f) {
word32 sz, wr; word32 sz, wr;
char contents[20]; char contents[20];
WSNPRINTF(contents, sizeof contents, "LoginGraceTime %02u", WSNPRINTF(contents, sizeof contents, "LoginGraceTime %02u",
fileIds[i]); fileIds[i]);
sz = (word32)WSTRLEN(contents); sz = (word32)WSTRLEN(contents);
wr = (word32)WFWRITE(contents, sizeof(char), sz, f); wr = (word32)WFWRITE(NULL, contents, sizeof(char), sz, f);
WFCLOSE(f); WFCLOSE(NULL, f);
if (sz != wr) { if (sz != wr) {
Log("Couldn't write the contents of file %s\n", filepath); Log("Couldn't write the contents of file %s\n", filepath);
ret = WS_FATAL_ERROR; ret = WS_FATAL_ERROR;

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,20 @@
#!/bin/sh #!/bin/sh
# #
# Create configure and makefile stuff... # Create configure and makefile stuff...
#
set -e
# if get an error about libtool not setup
# " error: Libtool library used but 'LIBTOOL' is undefined
# The usual way to define 'LIBTOOL' is to add 'LT_INIT' "
# manually call libtoolize or glibtoolize before running this again
# (g)libtoolize
# if you get an error about config.rpath missing, some buggy automake versions
# then touch the missing file (may need to make config/ first).
# touch config/config.rpath
# touch config.rpath
if test ! -d build-aux; then
echo "Making missing build-aux directory."
mkdir -p build-aux
fi
if test ! -f build-aux/config.rpath; then
echo "Touching missing build-aux/config.rpath file."
touch build-aux/config.rpath
fi
# Git hooks should come before autoreconf. # Git hooks should come before autoreconf.
if test -d .git; then if test -d .git
if ! test -d .git/hooks; then then
mkdir .git/hooks mkdir -p .git/hooks && ln -sf ../../scripts/pre-commit.sh .git/hooks/pre-commit
fi
ln -s -f ../../scripts/pre-commit.sh .git/hooks/pre-commit
fi fi
# If this is a source checkout then call autoreconf with error as well # If this is a source checkout then call autoreconf with error as well
if test -e .git; then if test -e .git
then
WARNINGS="all,error" WARNINGS="all,error"
else else
WARNINGS="all" WARNINGS="all"
fi fi
export WARNINGS
autoreconf --install --force --verbose autoreconf -ivf

View File

@ -148,10 +148,17 @@ static int NonBlockSSH_connect(WOLFSSH* ssh)
printf("... client would write block\n"); printf("... client would write block\n");
select_ret = tcp_select(sockfd, 1); select_ret = tcp_select(sockfd, 1);
if (select_ret == WS_SELECT_RECV_READY ||
/* Continue in want write cases even if did not select on socket
* because there could be pending data to be written. Added continue
* on want write for test cases where a forced want read was introduced
* and the socket will not be receiving more data. */
if (error == WS_WANT_WRITE || error == WS_WANT_READ ||
select_ret == WS_SELECT_RECV_READY ||
select_ret == WS_SELECT_ERROR_READY) select_ret == WS_SELECT_ERROR_READY)
{ {
ret = wolfSSH_connect(ssh); ret = wolfSSH_connect(ssh);
error = wolfSSH_get_error(ssh);
} }
else if (select_ret == WS_SELECT_TIMEOUT) else if (select_ret == WS_SELECT_TIMEOUT)
error = WS_WANT_READ; error = WS_WANT_READ;
@ -168,6 +175,7 @@ typedef struct thread_args {
WOLFSSH* ssh; WOLFSSH* ssh;
wolfSSL_Mutex lock; wolfSSL_Mutex lock;
byte rawMode; byte rawMode;
byte quit;
} thread_args; } thread_args;
#ifdef _POSIX_THREADS #ifdef _POSIX_THREADS
@ -181,6 +189,112 @@ typedef struct thread_args {
#define THREAD_RET_SUCCESS 0 #define THREAD_RET_SUCCESS 0
#endif #endif
static int sendCurrentWindowSize(thread_args* args)
{
int ret;
word32 col = 80, row = 24, xpix = 0, ypix = 0;
wc_LockMutex(&args->lock);
#if defined(_MSC_VER)
{
CONSOLE_SCREEN_BUFFER_INFO cs;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cs) != 0) {
col = cs.srWindow.Right - cs.srWindow.Left + 1;
row = cs.srWindow.Bottom - cs.srWindow.Top + 1;
}
}
#else
{
struct winsize windowSize = { 0,0,0,0 };
ioctl(STDOUT_FILENO, TIOCGWINSZ, &windowSize);
col = windowSize.ws_col;
row = windowSize.ws_row;
xpix = windowSize.ws_xpixel;
ypix = windowSize.ws_ypixel;
}
#endif
ret = wolfSSH_ChangeTerminalSize(args->ssh, col, row, xpix, ypix);
wc_UnLockMutex(&args->lock);
return ret;
}
#ifndef _MSC_VER
#if (defined(__OSX__) || defined(__APPLE__))
#include <dispatch/dispatch.h>
dispatch_semaphore_t windowSem;
#else
#include <semaphore.h>
static sem_t windowSem;
#endif
/* capture window change signales */
static void WindowChangeSignal(int sig)
{
#if (defined(__OSX__) || defined(__APPLE__))
dispatch_semaphore_signal(windowSem);
#else
sem_post(&windowSem);
#endif
(void)sig;
}
/* thread for handling window size adjustments */
static THREAD_RET windowMonitor(void* in)
{
thread_args* args;
int ret;
args = (thread_args*)in;
do {
#if (defined(__OSX__) || defined(__APPLE__))
dispatch_semaphore_wait(windowSem, DISPATCH_TIME_FOREVER);
#else
sem_wait(&windowSem);
#endif
if (args->quit) {
break;
}
ret = sendCurrentWindowSize(args);
(void)ret;
} while (1);
return THREAD_RET_SUCCESS;
}
#else
/* no SIGWINCH on Windows, poll current terminal size */
static word32 prevCol, prevRow;
static int windowMonitor(thread_args* args)
{
word32 row, col;
int ret = WS_SUCCESS;
CONSOLE_SCREEN_BUFFER_INFO cs;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cs) != 0) {
col = cs.srWindow.Right - cs.srWindow.Left + 1;
row = cs.srWindow.Bottom - cs.srWindow.Top + 1;
if (prevCol != col || prevRow != row) {
prevCol = col;
prevRow = row;
wc_LockMutex(&args->lock);
ret = wolfSSH_ChangeTerminalSize(args->ssh, col, row, 0, 0);
wc_UnLockMutex(&args->lock);
}
}
return ret;
}
#endif
static THREAD_RET readInput(void* in) static THREAD_RET readInput(void* in)
{ {
byte buf[256]; byte buf[256];
@ -198,6 +312,7 @@ static THREAD_RET readInput(void* in)
/* Using A version to avoid potential 2 byte chars */ /* Using A version to avoid potential 2 byte chars */
ret = ReadConsoleA(stdinHandle, (void*)buf, bufSz - 1, (DWORD*)&sz, ret = ReadConsoleA(stdinHandle, (void*)buf, bufSz - 1, (DWORD*)&sz,
NULL); NULL);
(void)windowMonitor(args);
#else #else
ret = (int)read(STDIN_FILENO, buf, bufSz -1); ret = (int)read(STDIN_FILENO, buf, bufSz -1);
sz = (word32)ret; sz = (word32)ret;
@ -233,11 +348,11 @@ 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;
int fd = wolfSSH_get_fd(args->ssh); int fd = (int)wolfSSH_get_fd(args->ssh);
word32 bytes; word32 bytes;
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
@ -250,7 +365,18 @@ 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) {
#ifdef USE_WINDOWS_API
(void)windowMonitor(args);
#endif
bytes = select(fd + 1, &readSet, NULL, &errSet, NULL); bytes = select(fd + 1, &readSet, NULL, &errSet, NULL);
wc_LockMutex(&args->lock); wc_LockMutex(&args->lock);
while (bytes > 0 && (FD_ISSET(fd, &readSet) || FD_ISSET(fd, &errSet))) { while (bytes > 0 && (FD_ISSET(fd, &readSet) || FD_ISSET(fd, &errSet))) {
@ -264,14 +390,24 @@ 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) {
#ifdef WOLFSSH_AGENT
if (ret == WS_FATAL_ERROR) { if (ret == WS_FATAL_ERROR) {
ret = wolfSSH_get_error(args->ssh); ret = wolfSSH_get_error(args->ssh);
if (ret == WS_CHAN_RXD) { if (ret == WS_WANT_READ) {
/* If WANT_READ, not an error. */
ret = WS_SUCCESS;
}
#ifdef WOLFSSH_AGENT
else if (ret == WS_CHAN_RXD) {
byte agentBuf[512]; byte agentBuf[512];
int rxd, txd; int rxd, txd;
word32 channel = 0; word32 channel = 0;
@ -302,9 +438,9 @@ static THREAD_RET readPeer(void* in)
WMEMSET(agentBuf, 0, sizeof(agentBuf)); WMEMSET(agentBuf, 0, sizeof(agentBuf));
continue; continue;
} }
#endif /* WOLFSSH_AGENT */
} }
#endif else if (ret != WS_EOF) {
if (ret != WS_EOF) {
err_sys("Stream read failed."); err_sys("Stream read failed.");
} }
} }
@ -327,7 +463,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
} }
@ -629,7 +767,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) {
@ -728,14 +866,47 @@ 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;
arg.quit = 0;
wc_InitMutex(&arg.lock); wc_InitMutex(&arg.lock);
pthread_create(&thread[0], NULL, readInput, (void*)&arg); #if (defined(__OSX__) || defined(__APPLE__))
pthread_create(&thread[1], NULL, readPeer, (void*)&arg); windowSem = dispatch_semaphore_create(0);
pthread_join(thread[1], NULL); #else
pthread_cancel(thread[0]); sem_init(&windowSem, 0, 0);
#endif
if (cmd) {
int err;
/* exec command does not contain initial terminal size, unlike pty-req.
* Send an inital terminal size for recieving the results of the command */
err = sendCurrentWindowSize(&arg);
if (err != WS_SUCCESS) {
fprintf(stderr, "Issue sending exec initial terminal size\n\r");
}
}
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);
/* Wake the windowMonitor thread so it can exit. */
arg.quit = 1;
#if (defined(__OSX__) || defined(__APPLE__))
dispatch_semaphore_signal(windowSem);
#else
sem_post(&windowSem);
#endif
pthread_join(thread[0], NULL);
pthread_cancel(thread[1]);
#if (defined(__OSX__) || defined(__APPLE__))
dispatch_release(windowSem);
#else
sem_destroy(&windowSem);
#endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
thread_args arg; thread_args arg;
HANDLE thread[2]; HANDLE thread[2];
@ -743,6 +914,18 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
arg.ssh = ssh; arg.ssh = ssh;
arg.rawMode = rawMode; arg.rawMode = rawMode;
wc_InitMutex(&arg.lock); wc_InitMutex(&arg.lock);
if (cmd) {
int err;
/* exec command does not contain initial terminal size, unlike pty-req.
* Send an inital terminal size for recieving the results of the command */
err = sendCurrentWindowSize(&arg);
if (err != WS_SUCCESS) {
fprintf(stderr, "Issue sending exec initial terminal size\n\r");
}
}
thread[0] = CreateThread(NULL, 0, readInput, (void*)&arg, 0, 0); thread[0] = CreateThread(NULL, 0, readInput, (void*)&arg, 0, 0);
thread[1] = CreateThread(NULL, 0, readPeer, (void*)&arg, 0, 0); thread[1] = CreateThread(NULL, 0, readPeer, (void*)&arg, 0, 0);
WaitForSingleObject(thread[1], INFINITE); WaitForSingleObject(thread[1], INFINITE);
@ -785,18 +968,21 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
#endif #endif
} }
ret = wolfSSH_shutdown(ssh); ret = wolfSSH_shutdown(ssh);
if (ret != WS_SUCCESS) { /* do not continue on with shutdown process if peer already disconnected */
err_sys("Sending the shutdown messages failed."); if (ret != WS_SOCKET_ERROR_E && wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
} if (ret != WS_SUCCESS) {
ret = wolfSSH_worker(ssh, NULL); err_sys("Sending the shutdown messages failed.");
if (ret != WS_SUCCESS) { }
err_sys("Failed to listen for close messages from the peer."); ret = wolfSSH_worker(ssh, NULL);
if (ret != WS_SUCCESS) {
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

@ -248,29 +248,29 @@ static int load_der_file(const char* filename, byte** out, word32* outSz)
if (filename == NULL || out == NULL || outSz == NULL) if (filename == NULL || out == NULL || outSz == NULL)
return -1; return -1;
ret = WFOPEN(&file, filename, "rb"); ret = WFOPEN(NULL, &file, filename, "rb");
if (ret != 0 || file == WBADFILE) if (ret != 0 || file == WBADFILE)
return -1; return -1;
if (WFSEEK(file, 0, WSEEK_END) != 0) { if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) {
WFCLOSE(file); WFCLOSE(NULL, file);
return -1; return -1;
} }
inSz = (word32)WFTELL(file); inSz = (word32)WFTELL(NULL, file);
WREWIND(file); WREWIND(NULL, file);
if (inSz == 0) { if (inSz == 0) {
WFCLOSE(file); WFCLOSE(NULL, file);
return -1; return -1;
} }
in = (byte*)WMALLOC(inSz, NULL, 0); in = (byte*)WMALLOC(inSz, NULL, 0);
if (in == NULL) { if (in == NULL) {
WFCLOSE(file); WFCLOSE(NULL, file);
return -1; return -1;
} }
ret = (int)WFREAD(in, 1, inSz, file); ret = (int)WFREAD(NULL, in, 1, inSz, file);
if (ret <= 0 || (word32)ret != inSz) { if (ret <= 0 || (word32)ret != inSz) {
ret = -1; ret = -1;
WFREE(in, NULL, 0); WFREE(in, NULL, 0);
@ -283,7 +283,7 @@ static int load_der_file(const char* filename, byte** out, word32* outSz)
*out = in; *out = in;
*outSz = inSz; *outSz = inSz;
WFCLOSE(file); WFCLOSE(NULL, file);
return ret; return ret;
} }
@ -382,25 +382,26 @@ int ClientPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
if (ParseRFC6187(pubKey, pubKeySz, &der, &derSz) == WS_SUCCESS) { if (ParseRFC6187(pubKey, pubKeySz, &der, &derSz) == WS_SUCCESS) {
wc_InitDecodedCert(&dCert, der, derSz, NULL); wc_InitDecodedCert(&dCert, der, derSz, NULL);
if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { if (wc_ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
printf("public key not a cert\n"); WLOG(WS_LOG_DEBUG, "public key not a cert");
} }
else { else {
int ipMatch = 0; int ipMatch = 0;
DNS_entry* current = dCert.altNames; DNS_entry* current = dCert.altNames;
if (ctx == NULL) { if (ctx == NULL) {
fprintf(stderr, "No host IP set to check against!\n"); WLOG(WS_LOG_ERROR, "No host IP set to check against!");
ret = -1; ret = -1;
} }
if (ret == 0) { if (ret == 0) {
while (current != NULL) { while (current != NULL) {
if (current->type == ASN_IP_TYPE) { if (current->type == ASN_IP_TYPE) {
printf("host cert alt. name IP : %s\n", WLOG(WS_LOG_DEBUG, "host cert alt. name IP : %s",
current->ipString); current->ipString);
printf("\texpecting host IP : %s\n", (char*)ctx); WLOG(WS_LOG_DEBUG,
"\texpecting host IP : %s", (char*)ctx);
if (XSTRCMP(ctx, current->ipString) == 0) { if (XSTRCMP(ctx, current->ipString) == 0) {
printf("\tmatched!\n"); WLOG(WS_LOG_DEBUG, "\tmatched!");
ipMatch = 1; ipMatch = 1;
} }
} }
@ -424,8 +425,8 @@ int ClientPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx)
} }
} }
#else #else
printf("wolfSSL not built with OPENSSL_ALL or WOLFSSL_IP_ALT_NAME\n"); WLOG(WS_LOG_DEBUG, "wolfSSL not built with OPENSSL_ALL or WOLFSSL_IP_ALT_NAME");
printf("\tnot checking IP address from peer's cert\n"); WLOG(WS_LOG_DEBUG, "\tnot checking IP address from peer's cert");
#endif #endif
#endif #endif

View File

@ -1411,7 +1411,7 @@ static int load_file(const char* fileName, byte* buf, word32* bufSz)
if (fileName == NULL) return 0; if (fileName == NULL) return 0;
if (WFOPEN(&file, fileName, "rb") != 0) if (WFOPEN(NULL, &file, fileName, "rb") != 0)
return 0; return 0;
fseek(file, 0, XSEEK_END); fseek(file, 0, XSEEK_END);
fileSz = (word32)ftell(file); fileSz = (word32)ftell(file);
@ -2511,10 +2511,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
WFILE* f = NULL; WFILE* f = NULL;
int ret; int ret;
ret = WFOPEN(&f, readyFile, "w"); ret = WFOPEN(NULL, &f, readyFile, "w");
if (f != NULL && ret == 0) { if (f != NULL && ret == 0) {
fprintf(f, "%d\n", (int)port); fprintf(f, "%d\n", (int)port);
WFCLOSE(f); WFCLOSE(NULL, f);
} }
#endif #endif
} }

View File

@ -310,17 +310,20 @@ 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);
if (ret != WS_SUCCESS) { /* do not continue on with shutdown process if peer already disconnected */
err_sys("Sending the shutdown messages failed."); if (ret != WS_SOCKET_ERROR_E && wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
} if (ret != WS_SUCCESS) {
ret = wolfSSH_worker(ssh, NULL); err_sys("Sending the shutdown messages failed.");
if (ret != WS_SUCCESS && ret != WS_CHANNEL_CLOSED) { }
err_sys("Failed to listen for close messages from the peer."); ret = wolfSSH_worker(ssh, NULL);
if (ret != WS_SUCCESS && ret != WS_CHANNEL_CLOSED) {
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

@ -282,7 +282,7 @@ static int load_file(const char* fileName, byte* buf, word32 bufSz)
if (fileName == NULL) return 0; if (fileName == NULL) return 0;
if (WFOPEN(&file, fileName, "rb") != 0) if (WFOPEN(NULL, &file, fileName, "rb") != 0)
return 0; return 0;
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
fileSz = (word32)ftell(file); fileSz = (word32)ftell(file);

View File

@ -24,6 +24,12 @@
#define WOLFSSH_TEST_CLIENT #define WOLFSSH_TEST_CLIENT
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.h>
#endif
#include <wolfssh/ssh.h> #include <wolfssh/ssh.h>
#include <wolfssh/internal.h> #include <wolfssh/internal.h>
#include <wolfssh/wolfsftp.h> #include <wolfssh/wolfsftp.h>
@ -1032,8 +1038,9 @@ static int doAutopilot(int cmd, char* local, char* remote)
} }
if (remoteAbsPath) { if (remoteAbsPath) {
WMEMSET(fullpath, 0, sizeof(fullpath)); /* use remote absolute path if provided */
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1); WMEMSET(fullpath, 0, sizeof(fullpath));
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1);
} }
else { else {
do { do {
@ -1244,7 +1251,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
else else
wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth); wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth);
#ifndef WS_NO_SIGNAL #if !defined(WS_NO_SIGNAL) && !defined(USE_WINDOWS_API)
/* handle interrupt with get and put */ /* handle interrupt with get and put */
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
#endif #endif
@ -1332,7 +1339,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 service
`sc.exe create wolfSSHd binpath="D:\work\wolfssh\ide\winvs\Debug\x64\wolfsshd.exe -f <sshd_config fils> -h <optionally load host key> -p <optional port number>"`
Starting wolfSSHd service run the following command in an adminstrator power shell session:
`sc.exe start wolfSSHd`
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

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

View File

@ -7,14 +7,9 @@ EXTRA_DIST+= ide/winvs/wolfssh.sln
EXTRA_DIST+= ide/winvs/wolfssh.props EXTRA_DIST+= ide/winvs/wolfssh.props
EXTRA_DIST+= ide/winvs/wolfssh/wolfssh.vcxproj EXTRA_DIST+= ide/winvs/wolfssh/wolfssh.vcxproj
EXTRA_DIST+= ide/winvs/api-test/api-test.vcxproj EXTRA_DIST+= ide/winvs/api-test/api-test.vcxproj
EXTRA_DIST+= ide/winvs/api-test/api-test.vcxproj.user
EXTRA_DIST+= ide/winvs/unit-test/unit-test.vcxproj EXTRA_DIST+= ide/winvs/unit-test/unit-test.vcxproj
EXTRA_DIST+= ide/winvs/unit-test/unit-test.vcxproj.user
EXTRA_DIST+= ide/winvs/client/client.vcxproj EXTRA_DIST+= ide/winvs/client/client.vcxproj
EXTRA_DIST+= ide/winvs/client/client.vcxproj.user
EXTRA_DIST+= ide/winvs/echoserver/echoserver.vcxproj EXTRA_DIST+= ide/winvs/echoserver/echoserver.vcxproj
EXTRA_DIST+= ide/winvs/echoserver/echoserver.vcxproj.user
EXTRA_DIST+= ide/winvs/testsuite/testsuite.vcxproj EXTRA_DIST+= ide/winvs/testsuite/testsuite.vcxproj
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/wolfsshd/wolfsshd.vcxproj

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

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

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllDebug64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease32);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerEnvironment>PATH=$(wolfCryptDllRelease64);%PATH%</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

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
@ -135,12 +140,28 @@ Global
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Debug|x64.Build.0 = Debug|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Debug|x64.Build.0 = Debug|x64
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|Win32.Build.0 = DLL Release|Win32 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|Win32.Build.0 = DLL Release|Win32
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|x64.ActiveCfg = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|x64.ActiveCfg = DLL Release|x64
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|x64.Build.0 = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.DLL Release|x64.Build.0 = DLL Release|x64
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.ActiveCfg = Release|Win32 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.ActiveCfg = Release|Win32
{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 = DLL Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|x64.Build.0 = DLL 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,202 @@
<?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="DLL Release|Win32">
<Configuration>DLL Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="DLL Release|x64">
<Configuration>DLL Release</Configuration>
<Platform>x64</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>
<ItemGroup>
<ProjectReference Include="..\wolfssh\wolfssh.vcxproj">
<Project>{7c2ccf0d-a155-4914-bd1c-9a47c0530e65}</Project>
</ProjectReference>
</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>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<PlatformToolset>v100</PlatformToolset>
</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" />
<Import Project="..\wolfssh.props" />
</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" />
<Import Project="..\wolfssh.props" />
</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" />
<Import Project="..\wolfssh.props" />
</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" />
<Import Project="..\wolfssh.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<Import Project="..\wolfssh.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
<Import Project="..\wolfssh.props" />
</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>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</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>..;..\..\..;$(wolfCryptDir);..\..\..\apps\wolfsshd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Debug\x64;..\Debug\x64</AdditionalLibraryDirectories>
<AdditionalDependencies>wolfssl.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>..;..\..\..;$(wolfCryptDir);..\..\..\apps\wolfsshd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>wolfssl.lib;ws2_32.lib;secur32.lib;userenv.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Release\x64;..\Release\x64</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WOLFSSL_USER_SETTINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..;..\..\..;$(wolfCryptDir);..\..\..\apps\wolfsshd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ConformanceMode>true</ConformanceMode>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalDependencies>wolfssl.lib;ws2_32.lib;secur32.lib;userenv.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(wolfCryptDLLRelease64)</AdditionalLibraryDirectories>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -151,6 +151,9 @@ const char* GetErrorString(int err)
return "No wolfSSH strings available"; return "No wolfSSH strings available";
#else #else
switch (err) { switch (err) {
case WS_SUCCESS:
return "no error";
case WS_ERROR: case WS_ERROR:
return "general function failure"; return "general function failure";
@ -576,6 +579,7 @@ WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap)
#endif /* WOLFSSH_CERTS */ #endif /* WOLFSSH_CERTS */
ctx->windowSz = DEFAULT_WINDOW_SZ; ctx->windowSz = DEFAULT_WINDOW_SZ;
ctx->maxPacketSz = DEFAULT_MAX_PACKET_SZ; ctx->maxPacketSz = DEFAULT_MAX_PACKET_SZ;
ctx->sshProtoIdStr = sshProtoIdStr;
count = (word32)(sizeof(ctx->privateKey) count = (word32)(sizeof(ctx->privateKey)
/ sizeof(ctx->privateKey[0])); / sizeof(ctx->privateKey[0]));
@ -626,6 +630,35 @@ void CtxResourceFree(WOLFSSH_CTX* ctx)
} }
#ifdef WOLFSSH_TERM
/* default terminal resize handling callbacks */
#if defined(USE_WINDOWS_API) && defined(WOLFSSH_SSHD)
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)
@ -718,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) && defined(WOLFSSH_SSHD)
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) {
@ -2260,8 +2299,14 @@ static int GetInputData(WOLFSSH* ssh, word32 size)
/* Take into account the data already in the buffer. Update size /* Take into account the data already in the buffer. Update size
* for what is missing in the request. */ * for what is missing in the request. */
word32 haveDataSz = ssh->inputBuffer.length - ssh->inputBuffer.idx; word32 haveDataSz;
/* reset want read state before attempting to read */
if (ssh->error == WS_WANT_READ) {
ssh->error = 0;
}
haveDataSz = ssh->inputBuffer.length - ssh->inputBuffer.idx;
if (haveDataSz >= size) { if (haveDataSz >= size) {
WLOG(WS_LOG_INFO, "GID: have enough already, return early"); WLOG(WS_LOG_INFO, "GID: have enough already, return early");
return WS_SUCCESS; return WS_SUCCESS;
@ -3230,13 +3275,13 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
byte SSH_PROTO_EOL_SZ = 2; byte SSH_PROTO_EOL_SZ = 2;
strSz = (word32)WSTRLEN(sshProtoIdStr) - SSH_PROTO_EOL_SZ; strSz = (word32)WSTRLEN(ssh->ctx->sshProtoIdStr) - SSH_PROTO_EOL_SZ;
c32toa(strSz, scratchLen); c32toa(strSz, scratchLen);
ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ); ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ);
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = HashUpdate(hash, hashId, (const byte*)sshProtoIdStr, strSz); ret = HashUpdate(hash, hashId, (const byte*)ssh->ctx->sshProtoIdStr, strSz);
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
@ -4187,7 +4232,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
/* Replace the concatenated shared secrets with the hash. That /* Replace the concatenated shared secrets with the hash. That
* will become the new shared secret. */ * will become the new shared secret. */
if (ret == 0) { if (ret == 0) {
sharedSecretHashSz = wc_HashGetDigestSize(enmhashId); sharedSecretHashSz = wc_HashGetDigestSize(hashId);
sharedSecretHash = (byte *)WMALLOC(sharedSecretHashSz, sharedSecretHash = (byte *)WMALLOC(sharedSecretHashSz,
ssh->ctx->heap, ssh->ctx->heap,
DYNTYPE_PRIVKEY); DYNTYPE_PRIVKEY);
@ -4197,7 +4242,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
} }
if (ret == 0) { if (ret == 0) {
ret = wc_Hash(enmhashId, ssh->k, ssh->kSz, sharedSecretHash, ret = wc_Hash(hashId, ssh->k, ssh->kSz, sharedSecretHash,
sharedSecretHashSz); sharedSecretHashSz);
} }
@ -4973,6 +5018,8 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData,
word32 begin; word32 begin;
WS_UserAuthData_Password* pw = NULL; WS_UserAuthData_Password* pw = NULL;
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
int authFailure = 0;
byte partialSuccess = 0;
WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPassword()"); WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestPassword()");
@ -5015,36 +5062,43 @@ static int DoUserAuthRequestPassword(WOLFSSH* ssh, WS_UserAuthData* authData,
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD, ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PASSWORD,
authData, ssh->userAuthCtx); authData, ssh->userAuthCtx);
if (ret == WOLFSSH_USERAUTH_SUCCESS) { if (ret == WOLFSSH_USERAUTH_SUCCESS) {
WLOG(WS_LOG_DEBUG, "DUARPW: password check successful"); WLOG(WS_LOG_DEBUG, "DUARPW: password check success");
ssh->clientState = CLIENT_USERAUTH_DONE; ret = WS_SUCCESS;
}
else if (ret == WOLFSSH_USERAUTH_PARTIAL_SUCCESS) {
WLOG(WS_LOG_DEBUG, "DUARPW: password check partial success");
partialSuccess = 1;
ret = WS_SUCCESS; ret = WS_SUCCESS;
} }
else if (ret == WOLFSSH_USERAUTH_REJECTED) { else if (ret == WOLFSSH_USERAUTH_REJECTED) {
WLOG(WS_LOG_DEBUG, "DUARPW: password rejected"); WLOG(WS_LOG_DEBUG, "DUARPW: password rejected");
#ifndef NO_FAILURE_ON_REJECTED #ifndef NO_FAILURE_ON_REJECTED
ret = SendUserAuthFailure(ssh, 0); authFailure = 1;
if (ret == WS_SUCCESS)
ret = WS_USER_AUTH_E;
#else
ret = WS_USER_AUTH_E;
#endif #endif
ret = WS_USER_AUTH_E;
} }
else { else {
WLOG(WS_LOG_DEBUG, "DUARPW: password check failed, retry"); WLOG(WS_LOG_DEBUG, "DUARPW: password check failed, retry");
ret = SendUserAuthFailure(ssh, 0); authFailure = 1;
ret = WS_SUCCESS;
} }
} }
else { else {
WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback"); WLOG(WS_LOG_DEBUG, "DUARPW: No user auth callback");
ret = SendUserAuthFailure(ssh, 0); authFailure = 1;
if (ret == WS_SUCCESS)
ret = WS_FATAL_ERROR;
} }
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
*idx = begin; *idx = begin;
if (authFailure || partialSuccess) {
ret = SendUserAuthFailure(ssh, partialSuccess);
}
else {
ssh->clientState = CLIENT_USERAUTH_DONE;
}
WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPassword(), ret = %d", ret); WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPassword(), ret = %d", ret);
return ret; return ret;
} }
@ -5728,6 +5782,7 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
word32 begin; word32 begin;
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
int authFailure = 0; int authFailure = 0;
int partialSuccess = 0;
byte hasSig = 0; byte hasSig = 0;
byte pkTypeId = ID_NONE; byte pkTypeId = ID_NONE;
@ -5834,17 +5889,49 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY, ret = ssh->ctx->userAuthCb(WOLFSSH_USERAUTH_PUBLICKEY,
authData, ssh->userAuthCtx); authData, ssh->userAuthCtx);
WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret); WLOG(WS_LOG_DEBUG, "DUARPK: callback result = %d", ret);
if (ret == WOLFSSH_USERAUTH_SUCCESS) { #ifdef DEBUG_WOLFSSH
ret = WS_SUCCESS; switch (ret) {
case WOLFSSH_USERAUTH_SUCCESS:
WLOG(WS_LOG_DEBUG, "DUARPK: user auth success");
break;
case WOLFSSH_USERAUTH_INVALID_PUBLICKEY:
WLOG(WS_LOG_DEBUG, "DUARPK: client key invalid");
break;
case WOLFSSH_USERAUTH_INVALID_USER:
WLOG(WS_LOG_DEBUG, "DUARPK: public key user rejected");
break;
case WOLFSSH_USERAUTH_FAILURE:
WLOG(WS_LOG_DEBUG, "DUARPK: public key general failure");
break;
case WOLFSSH_USERAUTH_INVALID_AUTHTYPE:
WLOG(WS_LOG_DEBUG, "DUARPK: public key invalid auth type");
break;
case WOLFSSH_USERAUTH_REJECTED:
WLOG(WS_LOG_DEBUG, "DUARPK: public key rejected");
break;
case WOLFSSH_USERAUTH_PARTIAL_SUCCESS:
WLOG(WS_LOG_DEBUG, "DUARPK: user auth partial success");
break;
default:
WLOG(WS_LOG_DEBUG,
"Unexpected return value from Auth callback");
} }
else if (ret == WOLFSSH_USERAUTH_INVALID_PUBLICKEY) { #endif
WLOG(WS_LOG_DEBUG, "DUARPK: client key rejected");
authFailure = 1; if (ret == WOLFSSH_USERAUTH_PARTIAL_SUCCESS) {
ret = WS_SUCCESS; partialSuccess = 1;
} }
else { else if (ret != WOLFSSH_USERAUTH_SUCCESS) {
authFailure = 1; authFailure = 1;
} }
ret = WS_SUCCESS;
} }
else { else {
WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set"); WLOG(WS_LOG_DEBUG, "DUARPK: no userauth callback set");
@ -5982,8 +6069,13 @@ static int DoUserAuthRequestPublicKey(WOLFSSH* ssh, WS_UserAuthData* authData,
} }
} }
if (ret == WS_SUCCESS && authFailure) { if (ret == WS_SUCCESS) {
ret = SendUserAuthFailure(ssh, 0); if (authFailure) {
ret = SendUserAuthFailure(ssh, 0);
}
else if (partialSuccess && hasSig) {
ret = SendUserAuthFailure(ssh, 1);
}
} }
WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPublicKey(), ret = %d", ret); WLOG(WS_LOG_DEBUG, "Leaving DoUserAuthRequestPublicKey(), ret = %d", ret);
@ -6358,6 +6450,7 @@ static int DoChannelOpen(WOLFSSH* ssh,
#endif /* WOLFSSH_FWD */ #endif /* WOLFSSH_FWD */
WOLFSSH_CHANNEL* newChannel = NULL; WOLFSSH_CHANNEL* newChannel = NULL;
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
word32 fail_reason = OPEN_OK;
WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()"); WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()");
@ -6388,6 +6481,10 @@ static int DoChannelOpen(WOLFSSH* ssh,
typeId = NameToId(type, typeSz); typeId = NameToId(type, typeSz);
switch (typeId) { switch (typeId) {
case ID_CHANTYPE_SESSION: case ID_CHANTYPE_SESSION:
if (ssh->channelListSz >= 1) {
ret = WS_INVALID_CHANID;
fail_reason = OPEN_ADMINISTRATIVELY_PROHIBITED;
}
break; break;
#ifdef WOLFSSH_FWD #ifdef WOLFSSH_FWD
case ID_CHANTYPE_TCPIP_DIRECT: case ID_CHANTYPE_TCPIP_DIRECT:
@ -6410,6 +6507,7 @@ static int DoChannelOpen(WOLFSSH* ssh,
#endif #endif
default: default:
ret = WS_INVALID_CHANTYPE; ret = WS_INVALID_CHANTYPE;
fail_reason = OPEN_UNKNOWN_CHANNEL_TYPE;
} }
} }
@ -6418,8 +6516,10 @@ static int DoChannelOpen(WOLFSSH* ssh,
newChannel = ChannelNew(ssh, typeId, newChannel = ChannelNew(ssh, typeId,
ssh->ctx->windowSz, ssh->ctx->maxPacketSz); ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
if (newChannel == NULL) if (newChannel == NULL) {
ret = WS_RESOURCE_E; ret = WS_RESOURCE_E;
fail_reason = OPEN_RESOURCE_SHORTAGE;
}
else { else {
ChannelUpdatePeer(newChannel, peerChannelId, ChannelUpdatePeer(newChannel, peerChannelId,
peerInitialWindowSz, peerMaxPacketSz); peerInitialWindowSz, peerMaxPacketSz);
@ -6446,8 +6546,24 @@ static int DoChannelOpen(WOLFSSH* ssh,
} }
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS) {
ret = SendChannelOpenConf(ssh, newChannel); ret = SendChannelOpenConf(ssh, newChannel);
}
else {
const char *description = NULL;
if (fail_reason == OPEN_ADMINISTRATIVELY_PROHIBITED)
description = "Each session cannot have more than one channel open.";
else if (fail_reason == OPEN_UNKNOWN_CHANNEL_TYPE)
description = "Channel type not supported.";
else if (fail_reason == OPEN_RESOURCE_SHORTAGE)
description = "Not enough resources.";
if (description != NULL)
ret = SendChannelOpenFail(ssh, peerChannelId, fail_reason, description, "en");
else
ret = SendRequestSuccess(ssh, 0);
}
#ifdef WOLFSSH_FWD #ifdef WOLFSSH_FWD
/* ChannelUpdateForward makes new host and origin buffer */ /* ChannelUpdateForward makes new host and origin buffer */
@ -6675,7 +6791,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);
@ -6687,8 +6803,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); /* iterate over op codes */
if (ret == WS_SUCCESS && begin < len) {
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);
@ -6696,7 +6818,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
@ -6746,6 +6875,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)
@ -7632,7 +7789,7 @@ int DoReceive(WOLFSSH* ssh)
+ peerBlockSz, + peerBlockSz,
ssh->inputBuffer.buffer + ssh->inputBuffer.idx ssh->inputBuffer.buffer + ssh->inputBuffer.idx
+ peerBlockSz, + peerBlockSz,
ssh->curSz - peerBlockSz); UINT32_SZ + ssh->curSz - peerBlockSz);
} }
else { else {
/* Entire packet fit in one block, don't need /* Entire packet fit in one block, don't need
@ -7728,7 +7885,7 @@ int DoProtoId(WOLFSSH* ssh)
} }
if (WSTRNCASECMP((char*)ssh->inputBuffer.buffer, if (WSTRNCASECMP((char*)ssh->inputBuffer.buffer,
sshProtoIdStr, SSH_PROTO_SZ) == 0) { ssh->ctx->sshProtoIdStr, SSH_PROTO_SZ) == 0) {
if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER)
ssh->clientState = CLIENT_VERSION_DONE; ssh->clientState = CLIENT_VERSION_DONE;
@ -7779,14 +7936,14 @@ int SendProtoId(WOLFSSH* ssh)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "%s", sshProtoIdStr); WLOG(WS_LOG_DEBUG, "%s", ssh->ctx->sshProtoIdStr);
sshProtoIdStrSz = (word32)WSTRLEN(sshProtoIdStr); sshProtoIdStrSz = (word32)WSTRLEN(ssh->ctx->sshProtoIdStr);
ret = GrowBuffer(&ssh->outputBuffer, sshProtoIdStrSz); ret = GrowBuffer(&ssh->outputBuffer, sshProtoIdStrSz);
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
WMEMCPY(ssh->outputBuffer.buffer + ssh->outputBuffer.length, WMEMCPY(ssh->outputBuffer.buffer + ssh->outputBuffer.length,
sshProtoIdStr, sshProtoIdStrSz); ssh->ctx->sshProtoIdStr, sshProtoIdStrSz);
ssh->outputBuffer.length += sshProtoIdStrSz; ssh->outputBuffer.length += sshProtoIdStrSz;
ret = wolfSSH_SendPacket(ssh); ret = wolfSSH_SendPacket(ssh);
} }
@ -8338,10 +8495,10 @@ struct wolfSSH_sigKeyBlockFull {
#ifndef WOLFSSH_NO_RSA #ifndef WOLFSSH_NO_RSA
struct { struct {
RsaKey key; RsaKey key;
byte e[257]; byte e[1025];
word32 eSz; word32 eSz;
byte ePad; byte ePad;
byte n[257]; byte n[1025];
word32 nSz; word32 nSz;
byte nPad; byte nPad;
} rsa; } rsa;
@ -8474,6 +8631,46 @@ static int BuildRFC6187Info(WOLFSSH* ssh, int pubKeyID,
#endif /* WOLFSSH_CERTS */ #endif /* WOLFSSH_CERTS */
#ifndef WOLFSSH_NO_DH
static int GetDHPrimeGroup(int kexId, const byte** primeGroup,
word32* primeGroupSz, const byte** generator, word32* generatorSz)
{
int ret = WS_SUCCESS;
switch (kexId) {
#ifndef WOLFSSH_NO_DH_GROUP1_SHA1
case ID_DH_GROUP1_SHA1:
*primeGroup = dhPrimeGroup1;
*primeGroupSz = dhPrimeGroup1Sz;
*generator = dhGenerator;
*generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GROUP14_SHA1
case ID_DH_GROUP14_SHA1:
*primeGroup = dhPrimeGroup14;
*primeGroupSz = dhPrimeGroup14Sz;
*generator = dhGenerator;
*generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256:
*primeGroup = dhPrimeGroup14;
*primeGroupSz = dhPrimeGroup14Sz;
*generator = dhGenerator;
*generatorSz = dhGeneratorSz;
break;
#endif
default:
ret = WS_INVALID_ALGO_ID;
}
return ret;
}
#endif /* !WOLFSSH_NO_DH */
/* Sets the signing key and hashes in the public key /* Sets the signing key and hashes in the public key
* returns WS_SUCCESS on success */ * returns WS_SUCCESS on success */
static int SendKexGetSigningKey(WOLFSSH* ssh, static int SendKexGetSigningKey(WOLFSSH* ssh,
@ -8717,6 +8914,11 @@ static int SendKexGetSigningKey(WOLFSSH* ssh,
if (ssh->handshake->kexId == ID_DH_GEX_SHA256) { if (ssh->handshake->kexId == ID_DH_GEX_SHA256) {
byte primeGroupPad = 0, generatorPad = 0; byte primeGroupPad = 0, generatorPad = 0;
if (GetDHPrimeGroup(ssh->handshake->kexId, &primeGroup,
&primeGroupSz, &generator, &generatorSz) != WS_SUCCESS) {
ret = WS_BAD_ARGUMENT;
}
/* Hash in the client's requested minimum key size. */ /* Hash in the client's requested minimum key size. */
if (ret == 0) { if (ret == 0) {
c32toa(ssh->handshake->dhGexMinSz, scratchLen); c32toa(ssh->handshake->dhGexMinSz, scratchLen);
@ -8991,35 +9193,13 @@ int SendKexDhReply(WOLFSSH* ssh)
y_ptr = y_s; y_ptr = y_s;
#endif #endif
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
switch (ssh->handshake->kexId) { ret = GetDHPrimeGroup(ssh->handshake->kexId, &primeGroup,
#ifndef WOLFSSH_NO_DH_GROUP1_SHA1 &primeGroupSz, &generator, &generatorSz);
case ID_DH_GROUP1_SHA1: #ifndef WOLFSSH_NO_DH_GEX_SHA256
primeGroup = dhPrimeGroup1; if (ssh->handshake->kexId == ID_DH_GEX_SHA256)
primeGroupSz = dhPrimeGroup1Sz; msgId = MSGID_KEXDH_GEX_REPLY;
generator = dhGenerator; #endif
generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GROUP14_SHA1
case ID_DH_GROUP14_SHA1:
primeGroup = dhPrimeGroup14;
primeGroupSz = dhPrimeGroup14Sz;
generator = dhGenerator;
generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256:
primeGroup = dhPrimeGroup14;
primeGroupSz = dhPrimeGroup14Sz;
generator = dhGenerator;
generatorSz = dhGeneratorSz;
msgId = MSGID_KEXDH_GEX_REPLY;
break;
#endif
default:
ret = WS_INVALID_ALGO_ID;
}
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = wc_InitDhKey(privKey); ret = wc_InitDhKey(privKey);
} }
@ -9206,7 +9386,7 @@ int SendKexDhReply(WOLFSSH* ssh)
ret = wc_ecc_shared_secret(privKey, pubKey, ret = wc_ecc_shared_secret(privKey, pubKey,
ssh->k + kem->length_shared_secret, &tmp_kSz); ssh->k + kem->length_shared_secret, &tmp_kSz);
PRIVATE_KEY_LOCK(); PRIVATE_KEY_LOCK();
ssh->kSz = kem->length_shared_secret + tmp_kSz; ssh->kSz = (word32)kem->length_shared_secret + tmp_kSz;
} }
wc_ecc_free(privKey); wc_ecc_free(privKey);
wc_ecc_free(pubKey); wc_ecc_free(pubKey);
@ -12163,6 +12343,58 @@ int SendChannelOpenConf(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
return ret; return ret;
} }
int SendChannelOpenFail(WOLFSSH* ssh, word32 channel, word32 reason, const char *description, const char *language)
{
byte* output;
word32 idx;
word32 descriptionSz = (word32)WSTRLEN(description);
word32 languageSz = (word32)WSTRLEN(language);
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenFail()");
if (ssh == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
WLOG(WS_LOG_INFO, " channelId = %u", channel);
WLOG(WS_LOG_INFO, " reason = %u", reason);
WLOG(WS_LOG_INFO, " description = %s", description);
WLOG(WS_LOG_INFO, " language = %s", language);
}
if (ret == WS_SUCCESS)
ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + UINT32_SZ + LENGTH_SZ + descriptionSz + LENGTH_SZ + languageSz);
if (ret == WS_SUCCESS) {
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_OPEN_FAIL;
c32toa(channel, output + idx);
idx += UINT32_SZ;
c32toa(reason, output + idx);
idx += UINT32_SZ;
c32toa(descriptionSz, output + idx);
idx += UINT32_SZ;
WMEMCPY(output + idx, description, descriptionSz);
idx += descriptionSz;
c32toa(languageSz, output + idx);
idx += UINT32_SZ;
WMEMCPY(output + idx, language, languageSz);
idx += languageSz;
ssh->outputBuffer.length = idx;
ret = BundlePacket(ssh);
}
if (ret == WS_SUCCESS)
ret = wolfSSH_SendPacket(ssh);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenFail(), ret = %d", ret);
return ret;
}
int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId) int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)
{ {
@ -12775,6 +13007,97 @@ 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)WSTRLEN(cType);
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;
}
#ifdef __linux__
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#endif
static void GetTerminalSize(word32* width, word32* height)
{
#ifdef __linux__
struct winsize windowSize = { 0,0,0,0 };
ioctl(STDOUT_FILENO, TIOCGWINSZ, &windowSize);
*width = (word32)windowSize.ws_col;
*height = (word32)windowSize.ws_row;
#elif defined(_MSC_VER)
CONSOLE_SCREEN_BUFFER_INFO cs;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cs) != 0) {
*width = cs.srWindow.Right - cs.srWindow.Left + 1;
*height = cs.srWindow.Bottom - cs.srWindow.Top + 1;
}
#else
/* sane defaults for terminal size if not yet supported */
*width = 80;
*height = 24;
#endif
}
/* 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)
@ -12787,7 +13110,7 @@ int SendChannelTerminalRequest(WOLFSSH* ssh)
const char envVar[] = "xterm"; const char envVar[] = "xterm";
byte mode[4096]; byte mode[4096];
word32 envSz, typeSz, modeSz; word32 envSz, typeSz, modeSz;
word32 w = 80, h = 24; word32 w, h;
word32 pxW = 0, pxH = 0; word32 pxW = 0, pxH = 0;
WLOG(WS_LOG_DEBUG, "Entering SendChannelTerminalRequest()"); WLOG(WS_LOG_DEBUG, "Entering SendChannelTerminalRequest()");
@ -12795,6 +13118,7 @@ int SendChannelTerminalRequest(WOLFSSH* ssh)
if (ssh == NULL) if (ssh == NULL)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
GetTerminalSize(&w, &h);
envSz = (word32)WSTRLEN(envVar); envSz = (word32)WSTRLEN(envVar);
typeSz = (word32)WSTRLEN(cType); typeSz = (word32)WSTRLEN(cType);
modeSz = CreateMode(ssh, mode); modeSz = CreateMode(ssh, mode);
@ -13216,9 +13540,13 @@ int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz)
/* addend1 += addend2 */ /* addend1 += addend2 */
void AddAssign64(word32* addend1, word32 addend2) void AddAssign64(word32* addend1, word32 addend2)
{ {
word32 tmp = addend1[0]; if (addend1[0] > (WOLFSSL_MAX_32BIT - addend2)) {
if ((addend1[0] += addend2) < tmp)
addend1[1]++; addend1[1]++;
addend1[0] = addend2 - (WOLFSSL_MAX_32BIT- addend1[0]);
}
else {
addend1[0] += addend2;
}
} }
#endif /* WOLFSSH_SFTP */ #endif /* WOLFSSH_SFTP */

View File

@ -66,13 +66,13 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
} }
if (filename != NULL && f != NULL) { if (filename != NULL && f != NULL) {
if ((**f = WOPEN(filename, m, 0)) < 0) { if ((**f = WOPEN(ssh->fs, filename, m, 0)) < 0) {
return **f; return **f;
} }
/* fopen defaults to normal */ /* fopen defaults to normal */
if (NU_Set_Attributes(filename, 0) != NU_SUCCESS) { if (NU_Set_Attributes(filename, 0) != NU_SUCCESS) {
WCLOSE(**f); WCLOSE(ssh->fs, **f);
return 1; return 1;
} }
return 0; return 0;

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.
* *
@ -1534,7 +1569,7 @@ int wolfSSH_ReadKey_buffer(const byte* in, word32 inSz, int format,
} }
#ifndef NO_FILESYSTEM #if !defined(NO_FILESYSTEM) && !defined(WOLFSSH_USER_FILESYSTEM)
/* Reads a key from the file name into a buffer. If the key starts with the /* Reads a key from the file name into a buffer. If the key starts with the
string "ssh-rsa" or "ecdsa-sha2-nistp256", it is considered an SSH format string "ssh-rsa" or "ecdsa-sha2-nistp256", it is considered an SSH format
@ -1557,27 +1592,27 @@ int wolfSSH_ReadKey_file(const char* name,
isPrivate == NULL) isPrivate == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
ret = WFOPEN(&file, name, "rb"); ret = WFOPEN(NULL, &file, name, "rb");
if (ret != 0 || file == WBADFILE) return WS_BAD_FILE_E; if (ret != 0 || file == WBADFILE) return WS_BAD_FILE_E;
if (WFSEEK(file, 0, WSEEK_END) != 0) { if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) {
WFCLOSE(file); WFCLOSE(NULL, file);
return WS_BAD_FILE_E; return WS_BAD_FILE_E;
} }
inSz = (word32)WFTELL(file); inSz = (word32)WFTELL(NULL, file);
WREWIND(file); WREWIND(NULL, file);
if (inSz > WOLFSSH_MAX_FILE_SIZE || inSz == 0) { if (inSz > WOLFSSH_MAX_FILE_SIZE || inSz == 0) {
WFCLOSE(file); WFCLOSE(NULL, file);
return WS_BAD_FILE_E; return WS_BAD_FILE_E;
} }
in = (byte*)WMALLOC(inSz + 1, heap, DYNTYPE_FILE); in = (byte*)WMALLOC(inSz + 1, heap, DYNTYPE_FILE);
if (in == NULL) { if (in == NULL) {
WFCLOSE(file); WFCLOSE(NULL, file);
return WS_MEMORY_E; return WS_MEMORY_E;
} }
ret = (int)WFREAD(in, 1, inSz, file); ret = (int)WFREAD(NULL, in, 1, inSz, file);
if (ret <= 0 || (word32)ret != inSz) { if (ret <= 0 || (word32)ret != inSz) {
ret = WS_BAD_FILE_E; ret = WS_BAD_FILE_E;
} }
@ -1599,7 +1634,7 @@ int wolfSSH_ReadKey_file(const char* name,
out, outSz, outType, outTypeSz, heap); out, outSz, outType, outTypeSz, heap);
} }
WFCLOSE(file); WFCLOSE(ssh->fs, file);
WFREE(in, heap, DYNTYPE_FILE); WFREE(in, heap, DYNTYPE_FILE);
return ret; return ret;
@ -1628,6 +1663,16 @@ int wolfSSH_CTX_SetBanner(WOLFSSH_CTX* ctx,
return WS_SUCCESS; return WS_SUCCESS;
} }
int wolfSSH_CTX_SetSshProtoIdStr(WOLFSSH_CTX* ctx,
const char* protoIdStr)
{
if (!ctx || !protoIdStr) {
return WS_BAD_ARGUMENT;
}
ctx->sshProtoIdStr = protoIdStr;
return WS_SUCCESS;
}
int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX* ctx, int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX* ctx,
const byte* in, word32 inSz, int format) const byte* in, word32 inSz, int format)

View File

@ -53,8 +53,8 @@
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
static int ScpFileIsDir(ScpSendCtx* ctx); static int ScpFileIsDir(ScpSendCtx* ctx);
static int ScpPushDir(ScpSendCtx* ctx, const char* path, void* heap); static int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap);
static int ScpPopDir(ScpSendCtx* ctx, void* heap); static int ScpPopDir(void *fs, ScpSendCtx* ctx, void* heap);
#endif #endif
const char scpError[] = "scp error: %s, %d"; const char scpError[] = "scp error: %s, %d";
@ -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,18 +1158,20 @@ 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(ssh->fs, &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(ssh->fs, &ctx, ssh->ctx->heap);
if (ret == WS_SCP_DIR_STACK_EMPTY_E) { if (ret == WS_SCP_DIR_STACK_EMPTY_E) {
ret = WS_SUCCESS; /* is ok to empty the directory stack here */ ret = WS_SUCCESS; /* is ok to empty the directory stack here */
} }
@ -1261,7 +1263,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 +1769,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.
@ -1910,7 +1926,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
} }
} }
#else #else
if (WCHDIR(basePath) != 0) { if (WCHDIR(ssh->fs, basePath) != 0) {
WLOG(WS_LOG_ERROR, WLOG(WS_LOG_ERROR,
"scp: invalid destination directory, abort"); "scp: invalid destination directory, abort");
wolfSSH_SetScpErrorMsg(ssh, "invalid destination directory"); wolfSSH_SetScpErrorMsg(ssh, "invalid destination directory");
@ -1928,9 +1944,9 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
WSTRNCAT(abslut, "/", WOLFSSH_MAX_FILENAME); WSTRNCAT(abslut, "/", WOLFSSH_MAX_FILENAME);
WSTRNCAT(abslut, fileName, WOLFSSH_MAX_FILENAME); WSTRNCAT(abslut, fileName, WOLFSSH_MAX_FILENAME);
wolfSSH_CleanPath(ssh, abslut); wolfSSH_CleanPath(ssh, abslut);
if (WFOPEN(&fp, abslut, "wb") != 0) { if (WFOPEN(ssh->fs, &fp, abslut, "wb") != 0) {
#else #else
if (WFOPEN(&fp, fileName, "wb") != 0) { if (WFOPEN(ssh->fs, &fp, fileName, "wb") != 0) {
#endif #endif
WLOG(WS_LOG_ERROR, WLOG(WS_LOG_ERROR,
"scp: unable to open file for writing, abort"); "scp: unable to open file for writing, abort");
@ -1954,11 +1970,11 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
break; break;
} }
/* read file, or file part */ /* read file, or file part */
bytes = (word32)WFWRITE(buf, 1, bufSz, fp); bytes = (word32)WFWRITE(ssh->fs, buf, 1, bufSz, fp);
if (bytes != bufSz) { if (bytes != bufSz) {
WLOG(WS_LOG_ERROR, scpError, "scp receive callback unable " WLOG(WS_LOG_ERROR, scpError, "scp receive callback unable "
"to write requested size to file", bytes); "to write requested size to file", bytes);
WFCLOSE(fp); WFCLOSE(ssh->fs, fp);
ret = WS_SCP_ABORT; ret = WS_SCP_ABORT;
} else { } else {
#ifdef WOLFSCP_FLUSH #ifdef WOLFSCP_FLUSH
@ -1984,7 +2000,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
(void)fsync(fileno(fp)); (void)fsync(fileno(fp));
flush_bytes = 0; flush_bytes = 0;
#endif #endif
WFCLOSE(fp); WFCLOSE(ssh->fs, fp);
} }
/* set timestamp info */ /* set timestamp info */
@ -2041,7 +2057,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
WSTRNCAT((char*)basePath, fileName, WOLFSSH_MAX_FILENAME); WSTRNCAT((char*)basePath, fileName, WOLFSSH_MAX_FILENAME);
wolfSSH_CleanPath(ssh, (char*)basePath); wolfSSH_CleanPath(ssh, (char*)basePath);
#else #else
if (WCHDIR(fileName) != 0) { if (WCHDIR(ssh->fs, fileName) != 0) {
WLOG(WS_LOG_ERROR, WLOG(WS_LOG_ERROR,
"scp: unable to cd into direcotry, abort"); "scp: unable to cd into direcotry, abort");
wolfSSH_SetScpErrorMsg(ssh, "unable to cd into directory"); wolfSSH_SetScpErrorMsg(ssh, "unable to cd into directory");
@ -2058,7 +2074,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
WSTRNCAT((char*)basePath, "/..", WOLFSSH_MAX_FILENAME - 1); WSTRNCAT((char*)basePath, "/..", WOLFSSH_MAX_FILENAME - 1);
wolfSSH_CleanPath(ssh, (char*)basePath); wolfSSH_CleanPath(ssh, (char*)basePath);
#else #else
if (WCHDIR("..") != 0) { if (WCHDIR(ssh->fs, "..") != 0) {
WLOG(WS_LOG_ERROR, WLOG(WS_LOG_ERROR,
"scp: unable to cd out of direcotry, abort"); "scp: unable to cd out of direcotry, abort");
wolfSSH_SetScpErrorMsg(ssh, "unable to cd out of directory"); wolfSSH_SetScpErrorMsg(ssh, "unable to cd out of directory");
@ -2079,31 +2095,51 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
return ret; return ret;
} }
static int GetFileSize(WFILE* fp, word32* fileSz) static int _GetFileSize(void* fs, WFILE* fp, word32* fileSz)
{ {
WOLFSSH_UNUSED(fs);
if (fp == NULL || fileSz == NULL) if (fp == NULL || fileSz == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
/* get file size */ /* get file size */
WFSEEK(fp, 0, WSEEK_END); WFSEEK(fs, fp, 0, WSEEK_END);
*fileSz = (word32)WFTELL(fp); *fileSz = (word32)WFTELL(fs, fp);
WREWIND(fp); WREWIND(fs, fp);
return WS_SUCCESS; return WS_SUCCESS;
} }
static int GetFileStats(ScpSendCtx* ctx, const char* fileName, static int GetFileStats(void *fs, ScpSendCtx* ctx, const char* fileName,
word64* mTime, word64* aTime, int* fileMode) word64* mTime, word64* aTime, int* fileMode)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
WOLFSSH_UNUSED(fs);
if (ctx == NULL || fileName == NULL || mTime == NULL || if (ctx == NULL || fileName == NULL || mTime == NULL ||
aTime == NULL || fileMode == NULL) { aTime == NULL || fileMode == NULL) {
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
} }
/* get file stats for times and mode */ /* get file stats for times and mode */
if (WSTAT(fileName, &ctx->s) < 0) { #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(fs, fileName, &ctx->s) < 0) {
ret = WS_BAD_FILE_E; ret = WS_BAD_FILE_E;
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
if (WSTRLEN(fileName) < 4 && WSTRLEN(fileName) > 2 && if (WSTRLEN(fileName) < 4 && WSTRLEN(fileName) > 2 &&
@ -2112,7 +2148,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,14 +2169,17 @@ 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;
} }
/* Create new ScpDir struct for pushing on directory stack. /* Create new ScpDir struct for pushing on directory stack.
* Return valid pointer on success, NULL on failure */ * Return valid pointer on success, NULL on failure */
static ScpDir* ScpNewDir(const char* path, void* heap) static ScpDir* ScpNewDir(void *fs, const char* path, void* heap)
{ {
WOLFSSH_UNUSED(fs);
ScpDir* entry = NULL; ScpDir* entry = NULL;
if (path == NULL) { if (path == NULL) {
@ -2155,7 +2195,25 @@ static ScpDir* ScpNewDir(const char* path, void* heap)
} }
entry->next = NULL; entry->next = NULL;
if (WOPENDIR(NULL, heap, &entry->dir, path) != 0 #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(fs, heap, &entry->dir, path) != 0
#ifndef WOLFSSL_NUCLEUS #ifndef WOLFSSL_NUCLEUS
|| entry->dir == NULL || entry->dir == NULL
#endif #endif
@ -2165,19 +2223,19 @@ 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;
} }
/* Create and push new ScpDir on stack, append directory to ctx->dirName */ /* Create and push new ScpDir on stack, append directory to ctx->dirName */
int ScpPushDir(ScpSendCtx* ctx, const char* path, void* heap) int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap)
{ {
ScpDir* entry; ScpDir* entry;
if (ctx == NULL || path == NULL) if (ctx == NULL || path == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
entry = ScpNewDir(path, heap); entry = ScpNewDir(fs, path, heap);
if (entry == NULL) { if (entry == NULL) {
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
@ -2198,8 +2256,10 @@ int ScpPushDir(ScpSendCtx* ctx, const char* path, void* heap)
} }
/* Remove top ScpDir from directory stack, remove dir from ctx->dirName */ /* Remove top ScpDir from directory stack, remove dir from ctx->dirName */
int ScpPopDir(ScpSendCtx* ctx, void* heap) int ScpPopDir(void *fs, ScpSendCtx* ctx, void* heap)
{ {
WOLFSSH_UNUSED(fs);
ScpDir* entry = NULL; ScpDir* entry = NULL;
int idx = 0, separator = 0; int idx = 0, separator = 0;
@ -2209,7 +2269,11 @@ int ScpPopDir(ScpSendCtx* ctx, void* heap)
} }
if (entry != NULL) { if (entry != NULL) {
WCLOSEDIR(&entry->dir); #ifdef USE_WINDOWS_API
FindClose(entry->dir);
#else
WCLOSEDIR(fs, &entry->dir);
#endif
WFREE(entry, heap, DYNTYPE_SCPDIR); WFREE(entry, heap, DYNTYPE_SCPDIR);
} }
@ -2235,8 +2299,10 @@ int ScpPopDir(ScpSendCtx* ctx, void* heap)
/* Get next entry in directory, either file or directory, skips self (.) /* Get next entry in directory, either file or directory, skips self (.)
* and parent (..) directories, stores in ctx->entry. * and parent (..) directories, stores in ctx->entry.
* Return WS_SUCCESS on success or negative upon error */ * Return WS_SUCCESS on success or negative upon error */
static int FindNextDirEntry(ScpSendCtx* ctx) static int FindNextDirEntry(void *fs, ScpSendCtx* ctx)
{ {
WOLFSSH_UNUSED(fs);
if (ctx == NULL) if (ctx == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
@ -2259,7 +2325,7 @@ static int FindNextDirEntry(ScpSendCtx* ctx)
if (ctx->nextError == 1) { if (ctx->nextError == 1) {
WDIR* dr; WDIR* dr;
do { do {
dr = WREADDIR(&ctx->currentDir->dir); dr = WREADDIR(fs, &ctx->currentDir->dir);
} while (dr != NULL && } while (dr != NULL &&
(WSTRNCMP(ctx->currentDir->dir.lfname, ".", 1) == 0 || (WSTRNCMP(ctx->currentDir->dir.lfname, ".", 1) == 0 ||
WSTRNCMP(ctx->currentDir->dir.lfname ,"..", 2) == 0)); WSTRNCMP(ctx->currentDir->dir.lfname ,"..", 2) == 0));
@ -2268,12 +2334,42 @@ 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) &&
(((WSTRLEN(ctx->entry) == 1) && WSTRNCMP(ctx->entry, ".", 1) == 0) ||
((WSTRLEN(ctx->entry) == 2) && WSTRNCMP(ctx->entry, "..", 2) == 0)));
#else #else
do { do {
ctx->entry = WREADDIR(&ctx->currentDir->dir); ctx->entry = WREADDIR(fs, &ctx->currentDir->dir);
} while ((ctx->entry != NULL) && } while ((ctx->entry != NULL) &&
(WSTRNCMP(ctx->entry->d_name, ".", 1) == 0 || (
WSTRNCMP(ctx->entry->d_name ,"..", 2) == 0)); ((WSTRLEN(ctx->entry->d_name) == 1) &&
(WSTRNCMP(ctx->entry->d_name, ".", 1) == 0))
||
((WSTRLEN(ctx->entry->d_name) == 2) &&
(WSTRNCMP(ctx->entry->d_name ,"..", 2) == 0))
));
#endif #endif
return WS_SUCCESS; return WS_SUCCESS;
@ -2293,6 +2389,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 +2400,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 +2432,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 +2461,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);
@ -2361,7 +2473,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
DEFAULT_SCP_FILE_NAME_SZ); DEFAULT_SCP_FILE_NAME_SZ);
#endif #endif
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = GetFileStats(sendCtx, filePath, mTime, aTime, fileMode); ret = GetFileStats(ssh->fs, sendCtx, filePath, mTime, aTime, fileMode);
} }
} }
} }
@ -2370,7 +2482,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
if (ScpFileIsDir(sendCtx)) { if (ScpFileIsDir(sendCtx)) {
ret = ScpPushDir(sendCtx, filePath, ssh->ctx->heap); ret = ScpPushDir(ssh->fs, sendCtx, filePath, ssh->ctx->heap);
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = WS_SCP_ENTER_DIR; ret = WS_SCP_ENTER_DIR;
} else { } else {
@ -2379,7 +2491,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
} }
} else if (ScpFileIsFile(sendCtx)) { } else if (ScpFileIsFile(sendCtx)) {
if (WFOPEN(&(sendCtx->fp), filePath, "rb") != 0) { if (WFOPEN(ssh->fs, &(sendCtx->fp), filePath, "rb") != 0) {
WLOG(WS_LOG_ERROR, "scp: Error with oepning file, abort"); WLOG(WS_LOG_ERROR, "scp: Error with oepning file, abort");
wolfSSH_SetScpErrorMsg(ssh, "unable to open file " wolfSSH_SetScpErrorMsg(ssh, "unable to open file "
"for reading"); "for reading");
@ -2387,16 +2499,16 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = GetFileSize(sendCtx->fp, totalFileSz); ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp); ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp);
} }
/* keep fp open if no errors and transfer will continue */ /* keep fp open if no errors and transfer will continue */
if ((sendCtx->fp != NULL) && if ((sendCtx->fp != NULL) &&
((ret < 0) || (*totalFileSz == (word32)ret))) { ((ret < 0) || (*totalFileSz == (word32)ret))) {
WFCLOSE(sendCtx->fp); WFCLOSE(ssh->fs, sendCtx->fp);
} }
} }
@ -2519,7 +2631,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
break; break;
case WOLFSSH_SCP_SINGLE_FILE_REQUEST: case WOLFSSH_SCP_SINGLE_FILE_REQUEST:
if ((sendCtx == NULL) || WFOPEN(&(sendCtx->fp), peerRequest, if ((sendCtx == NULL) || WFOPEN(ssh->fs, &(sendCtx->fp), peerRequest,
"rb") != 0) { "rb") != 0) {
WLOG(WS_LOG_ERROR, "scp: unable to open file, abort"); WLOG(WS_LOG_ERROR, "scp: unable to open file, abort");
@ -2538,10 +2650,10 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileSize(sendCtx->fp, totalFileSz); ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileStats(sendCtx, peerRequest, mTime, aTime, fileMode); ret = GetFileStats(ssh->fs, sendCtx, peerRequest, mTime, aTime, fileMode);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = ExtractFileName(peerRequest, fileName, fileNameSz); ret = ExtractFileName(peerRequest, fileName, fileNameSz);
@ -2549,7 +2661,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
if (ret == WS_SUCCESS && sendCtx != NULL && sendCtx->fp != NULL) { if (ret == WS_SUCCESS && sendCtx != NULL && sendCtx->fp != NULL) {
/* If it is an empty file, do not read. */ /* If it is an empty file, do not read. */
if (*totalFileSz != 0) { if (*totalFileSz != 0) {
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp); ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp);
if (ret == 0) { /* handle unexpected case */ if (ret == 0) { /* handle unexpected case */
ret = WS_EOF; ret = WS_EOF;
} }
@ -2562,7 +2674,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
/* keep fp open if no errors and transfer will continue */ /* keep fp open if no errors and transfer will continue */
if ((sendCtx != NULL) && (sendCtx->fp != NULL) && if ((sendCtx != NULL) && (sendCtx->fp != NULL) &&
((ret < 0) || (*totalFileSz == (word32)ret))) { ((ret < 0) || (*totalFileSz == (word32)ret))) {
WFCLOSE(sendCtx->fp); WFCLOSE(ssh->fs, sendCtx->fp);
} }
break; break;
@ -2572,7 +2684,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
if (ScpDirStackIsEmpty(sendCtx)) { if (ScpDirStackIsEmpty(sendCtx)) {
/* first request, keep track of request directory */ /* first request, keep track of request directory */
ret = ScpPushDir(sendCtx, peerRequest, ssh->ctx->heap); ret = ScpPushDir(ssh->fs, sendCtx, peerRequest, ssh->ctx->heap);
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
/* get file name from request */ /* get file name from request */
@ -2580,7 +2692,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = GetFileStats(sendCtx, peerRequest, mTime, aTime, ret = GetFileStats(ssh->fs, sendCtx, peerRequest, mTime, aTime,
fileMode); fileMode);
} }
@ -2595,7 +2707,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
/* send directory msg or abort */ /* send directory msg or abort */
break; break;
} }
ret = FindNextDirEntry(sendCtx); ret = FindNextDirEntry(ssh->fs, sendCtx);
/* help out static analysis tool */ /* help out static analysis tool */
if (ret != WS_BAD_ARGUMENT && sendCtx == NULL) if (ret != WS_BAD_ARGUMENT && sendCtx == NULL)
@ -2609,7 +2721,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
/* reached end of directory */ /* reached end of directory */
if (sendCtx->entry == NULL) { if (sendCtx->entry == NULL) {
#endif #endif
ret = ScpPopDir(sendCtx, ssh->ctx->heap); ret = ScpPopDir(ssh->fs, sendCtx, ssh->ctx->heap);
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = WS_SCP_EXIT_DIR; ret = WS_SCP_EXIT_DIR;
@ -2645,13 +2757,13 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
break; break;
} }
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp); ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp);
if (ret == 0) { /* handle case of EOF */ if (ret == 0) { /* handle case of EOF */
ret = WS_EOF; ret = WS_EOF;
} }
if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) { if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) {
WFCLOSE(sendCtx->fp); WFCLOSE(ssh->fs, sendCtx->fp);
} }
break; break;

View File

@ -63,6 +63,7 @@ enum WS_SFTP_STATE_ID {
STATE_ID_RECV = 0x10000, STATE_ID_RECV = 0x10000,
STATE_ID_CHMOD = 0x20000, STATE_ID_CHMOD = 0x20000,
STATE_ID_SETATR = 0x40000, STATE_ID_SETATR = 0x40000,
STATE_ID_RECV_INIT = 0x80000,
}; };
enum WS_SFTP_CHMOD_STATE_ID { enum WS_SFTP_CHMOD_STATE_ID {
@ -239,6 +240,11 @@ typedef struct WS_SFTP_LS_STATE {
} WS_SFTP_LS_STATE; } WS_SFTP_LS_STATE;
typedef struct WS_SFTP_RECV_INIT_STATE {
WS_SFTP_BUFFER buffer;
word32 extSz;
} WS_SFTP_RECV_INIT_STATE;
enum WS_SFTP_GET_STATE_ID { enum WS_SFTP_GET_STATE_ID {
STATE_GET_INIT, STATE_GET_INIT,
STATE_GET_LSTAT, STATE_GET_LSTAT,
@ -762,6 +768,14 @@ static void wolfSSH_SFTP_ClearState(WOLFSSH* ssh, enum WS_SFTP_STATE_ID state)
ssh->setatrState = NULL; ssh->setatrState = NULL;
} }
} }
if (state & STATE_ID_RECV_INIT) {
if (ssh->recvInitState) {
wolfSSH_SFTP_buffer_free(ssh, &ssh->recvInitState->buffer);
WFREE(ssh->recvInitState, ssh->ctx->heap, DYNTYPE_SFTP_STATE);
ssh->recvInitState = NULL;
}
}
} }
} }
@ -987,49 +1001,85 @@ static int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
* returns WS_SUCCESS on success * returns WS_SUCCESS on success
*/ */
static int SFTP_ServerRecvInit(WOLFSSH* ssh) { static int SFTP_ServerRecvInit(WOLFSSH* ssh) {
int len; enum {
RECV_INIT_SIZE = LENGTH_SZ + MSG_ID_SZ + UINT32_SZ
};
int ret;
byte id; byte id;
word32 sz = 0; word32 sz = 0;
word32 version = 0; word32 version = 0;
byte buf[LENGTH_SZ + MSG_ID_SZ + UINT32_SZ]; WS_SFTP_RECV_INIT_STATE *state;
if ((len = wolfSSH_stream_read(ssh, buf, sizeof(buf))) != sizeof(buf)) { state = ssh->recvInitState;
return len; if (state == NULL) {
state = (WS_SFTP_RECV_INIT_STATE*)WMALLOC(sizeof(WS_SFTP_RECV_INIT_STATE),
ssh->ctx->heap, DYNTYPE_SFTP_STATE);
if (state == NULL) {
ssh->error = WS_MEMORY_E;
return WS_FATAL_ERROR;
}
WMEMSET(state, 0, sizeof(WS_SFTP_RECV_INIT_STATE));
ssh->recvInitState = state;
} }
if (SFTP_GetSz(buf, &sz, switch (ssh->sftpState) {
MSG_ID_SZ + UINT32_SZ, WOLFSSH_MAX_SFTP_RECV) != WS_SUCCESS) { case SFTP_BEGIN:
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL); ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer, RECV_INIT_SIZE);
return WS_BUFFER_E; if (ret < 0) {
} return WS_FATAL_ERROR;
}
/* compare versions supported */ if (ret < WOLFSSH_SFTP_HEADER) {
id = buf[LENGTH_SZ]; WLOG(WS_LOG_SFTP, "Unable to read SFTP INIT message");
if (id != WOLFSSH_FTP_INIT) { return WS_FATAL_ERROR;
WLOG(WS_LOG_SFTP, "Unexpected SFTP type received"); }
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return WS_BUFFER_E;
}
ato32(buf + LENGTH_SZ + MSG_ID_SZ, &version); if (SFTP_GetSz(state->buffer.data, &sz,
/* versions greater than WOLFSSH_SFTP_VERSION should fall back to ours MSG_ID_SZ + UINT32_SZ, WOLFSSH_MAX_SFTP_RECV) != WS_SUCCESS) {
* versions less than WOLFSSH_SFTP_VERSION we should bail out on or wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
* implement a fall back */ return WS_BUFFER_E;
if (version < WOLFSSH_SFTP_VERSION) { }
WLOG(WS_LOG_SFTP, "Unsupported SFTP version, sending version 3");
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return WS_VERSION_E;
}
/* silently ignore extensions if not supported */ /* compare versions supported */
sz = sz - MSG_ID_SZ - UINT32_SZ; id = state->buffer.data[LENGTH_SZ];
if (sz > 0) { if (id != WOLFSSH_FTP_INIT) {
byte* data = (byte*)WMALLOC(sz, NULL, DYNTYPE_BUFFER); WLOG(WS_LOG_SFTP, "Unexpected SFTP type received");
if (data == NULL) return WS_MEMORY_E; wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
len = wolfSSH_stream_read(ssh, data, sz); return WS_BUFFER_E;
WFREE(data, NULL, DYNTYPE_BUFFER); }
if (len != (int)sz)
return len; ato32(state->buffer.data + LENGTH_SZ + MSG_ID_SZ, &version);
/* versions greater than WOLFSSH_SFTP_VERSION should fall back to ours
* versions less than WOLFSSH_SFTP_VERSION we should bail out on or
* implement a fall back */
if (version < WOLFSSH_SFTP_VERSION) {
WLOG(WS_LOG_SFTP, "Unsupported SFTP version, sending version 3");
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return WS_VERSION_E;
}
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
state->extSz = sz - MSG_ID_SZ - UINT32_SZ;
ssh->sftpState = SFTP_EXT;
NO_BREAK;
case SFTP_EXT:
/* silently ignore extensions if not supported */
if (state->extSz > 0) {
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer, (int)state->extSz);
if (ret < 0) {
return WS_FATAL_ERROR;
}
if (ret < (int)state->extSz) {
WLOG(WS_LOG_SFTP, "Unable to read SFTP INIT extensions");
return WS_FATAL_ERROR;
}
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
}
} }
ssh->reqId++; ssh->reqId++;
@ -1063,7 +1113,7 @@ static int SFTP_ServerSendInit(WOLFSSH* ssh) {
*/ */
int wolfSSH_SFTP_accept(WOLFSSH* ssh) int wolfSSH_SFTP_accept(WOLFSSH* ssh)
{ {
int ret = WS_SFTP_COMPLETE; int ret = WS_FATAL_ERROR;
if (ssh == NULL) { if (ssh == NULL) {
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
@ -1090,18 +1140,25 @@ int wolfSSH_SFTP_accept(WOLFSSH* ssh)
switch (ssh->sftpState) { switch (ssh->sftpState) {
case SFTP_BEGIN: case SFTP_BEGIN:
if (SFTP_ServerRecvInit(ssh) != WS_SUCCESS) { case SFTP_EXT:
return WS_FATAL_ERROR; ret = SFTP_ServerRecvInit(ssh);
if (ret != WS_SUCCESS) {
if (ssh->error != WS_WANT_READ && ssh->error != WS_WANT_WRITE)
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return ret;
} }
ssh->sftpState = SFTP_RECV; ssh->sftpState = SFTP_RECV;
NO_BREAK; NO_BREAK;
case SFTP_RECV: case SFTP_RECV:
if (SFTP_ServerSendInit(ssh) != WS_SUCCESS) { ret = SFTP_ServerSendInit(ssh);
return WS_FATAL_ERROR; if (ret != WS_SUCCESS) {
return ret;
} }
ssh->sftpState = SFTP_DONE; ssh->sftpState = SFTP_DONE;
WLOG(WS_LOG_SFTP, "SFTP connection established"); WLOG(WS_LOG_SFTP, "SFTP connection established");
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RECV_INIT);
ret = WS_SFTP_COMPLETE;
break; break;
default: default:
@ -1645,6 +1702,11 @@ int wolfSSH_SFTP_RecvRMDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_RMDIR"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_RMDIR");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -1720,6 +1782,11 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_MKDIR"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_MKDIR");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -1919,6 +1986,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -1966,7 +2038,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
atr.per = 0644; atr.per = 0644;
} }
fd = WOPEN(dir, m, atr.per); fd = WOPEN(ssh->fs, dir, m, atr.per);
if (fd < 0) { if (fd < 0) {
WLOG(WS_LOG_SFTP, "Error opening file %s", dir); WLOG(WS_LOG_SFTP, "Error opening file %s", dir);
res = oer; res = oer;
@ -2047,6 +2119,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -2147,16 +2224,13 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
#ifndef NO_WOLFSSH_DIR #ifndef NO_WOLFSSH_DIR
/* hold pointers to directory handles */ /* hold pointers to directory handles */
typedef struct DIR_HANDLE { struct WS_DIR_LIST {
WDIR dir; WDIR dir;
char* dirName; /* base name of directory */ char* dirName; /* base name of directory */
byte isEof; /* flag for if read everything */ byte isEof; /* flag for if read everything */
word32 id[2]; /* handle ID */ word32 id[2]; /* handle ID */
struct DIR_HANDLE* next; struct WS_DIR_LIST* next;
} DIR_HANDLE; };
static DIR_HANDLE* dirList = NULL;
static word32 idCount[2] = {0, 0};
/* @TODO add locking for thread safety */
/* Handles packet to open a directory /* Handles packet to open a directory
@ -2188,6 +2262,11 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get directory name */ /* get directory name */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
@ -2211,23 +2290,22 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WOLFSSH_UNUSED(reqId); WOLFSSH_UNUSED(reqId);
/* add to directory list @TODO locking for thread safety */
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
DIR_HANDLE* cur = NULL; WS_DIR_LIST* cur = NULL;
char* dirName = NULL; char* dirName = NULL;
word32 dirNameSz; word32 dirNameSz;
cur = (DIR_HANDLE*)WMALLOC(sizeof(DIR_HANDLE), cur = (WS_DIR_LIST*)WMALLOC(sizeof(WS_DIR_LIST),
ssh->ctx->heap, DYNTYPE_SFTP); ssh->ctx->heap, DYNTYPE_SFTP);
if (cur == NULL) { if (cur == NULL) {
WCLOSEDIR(&ctx); WCLOSEDIR(ssh->fs, &ctx);
return WS_MEMORY_E; return WS_MEMORY_E;
} }
dirNameSz = (word32)WSTRLEN(dir) + 1; dirNameSz = (word32)WSTRLEN(dir) + 1;
dirName = (char*)WMALLOC(dirNameSz, dirName = (char*)WMALLOC(dirNameSz,
ssh->ctx->heap, DYNTYPE_PATH); ssh->ctx->heap, DYNTYPE_PATH);
if (dirName == NULL) { if (dirName == NULL) {
WCLOSEDIR(&ctx); WCLOSEDIR(ssh->fs, &ctx);
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP); WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
return WS_MEMORY_E; return WS_MEMORY_E;
} }
@ -2237,15 +2315,15 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
#else #else
cur->dir = ctx; cur->dir = ctx;
#endif #endif
cur->id[0] = id[0] = idCount[0]; cur->id[0] = id[0] = ssh->dirIdCount[0];
cur->id[1] = id[1] = idCount[1]; cur->id[1] = id[1] = ssh->dirIdCount[1];
c32toa(id[0], idFlat); c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ); c32toa(id[1], idFlat + UINT32_SZ);
AddAssign64(idCount, 1); AddAssign64(ssh->dirIdCount, 1);
cur->isEof = 0; cur->isEof = 0;
cur->next = dirList; cur->next = ssh->dirList;
dirList = cur; ssh->dirList = cur;
dirList->dirName = dirName; /* take over ownership of buffer */ ssh->dirList->dirName = dirName; /* take over ownership of buffer */
} }
out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER);
@ -2298,6 +2376,11 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get directory name */ /* get directory name */
ato32(data + idx, &sz); ato32(data + idx, &sz);
idx += UINT32_SZ; idx += UINT32_SZ;
@ -2364,24 +2447,23 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WOLFSSH_UNUSED(reqId); WOLFSSH_UNUSED(reqId);
/* add to directory list @TODO locking for thread safety */
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
DIR_HANDLE* cur = (DIR_HANDLE*)WMALLOC(sizeof(DIR_HANDLE), WS_DIR_LIST* cur = (WS_DIR_LIST*)WMALLOC(sizeof(WS_DIR_LIST),
ssh->ctx->heap, DYNTYPE_SFTP); ssh->ctx->heap, DYNTYPE_SFTP);
if (cur == NULL) { if (cur == NULL) {
WFREE(dirName, ssh->ctx->heap, DYNTYPE_BUFFER); WFREE(dirName, ssh->ctx->heap, DYNTYPE_BUFFER);
return WS_MEMORY_E; return WS_MEMORY_E;
} }
cur->dir = INVALID_HANDLE_VALUE; cur->dir = INVALID_HANDLE_VALUE;
cur->id[0] = id[0] = idCount[0]; cur->id[0] = id[0] = ssh->dirIdCount[0];
cur->id[1] = id[1] = idCount[1]; cur->id[1] = id[1] = ssh->dirIdCount[1];
c32toa(id[0], idFlat); c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ); c32toa(id[1], idFlat + UINT32_SZ);
AddAssign64(idCount, 1); AddAssign64(ssh->dirIdCount, 1);
cur->isEof = 0; cur->isEof = 0;
cur->dirName = dirName; /* take over ownership of buffer */ cur->dirName = dirName; /* take over ownership of buffer */
cur->next = dirList; cur->next = ssh->dirList;
dirList = cur; ssh->dirList = cur;
} }
@ -2453,15 +2535,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 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) {
@ -2506,7 +2588,9 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name)
totalSz += name->fSz; /* size of file name */ totalSz += name->fSz; /* size of file name */
totalSz += 7; /* for all ' ' spaces */ totalSz += 7; /* for all ' ' spaces */
totalSz += 3 + 8 + 8 + 8; /* linkCount + uid + gid + size */ totalSz += 3 + 8 + 8; /* linkCount + uid + gid */
WSNPRINTF(sizeStr, sizeof(sizeStr) - 1, "%8lld", ((long long int)atr->sz[1] << 32) + (long long int)(atr->sz[0]));
totalSz += WSTRLEN(sizeStr);
#else #else
totalSz = name->fSz; totalSz = name->fSz;
#endif #endif
@ -2520,8 +2604,8 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name)
name->lName[totalSz] = '\0'; name->lName[totalSz] = '\0';
#if defined(XGMTIME) && defined(XSNPRINTF) #if defined(XGMTIME) && defined(XSNPRINTF)
WSNPRINTF(name->lName, totalSz, "%s %3d %8d %8d %8d %s %s", WSNPRINTF(name->lName, totalSz, "%s %3d %8d %8d %s %s %s",
perm, linkCount, atr->uid, atr->gid, atr->sz[0], date, name->fName); perm, linkCount, atr->uid, atr->gid, sizeStr, date, name->fName);
#else #else
WMEMCPY(name->lName, name->fName, totalSz); WMEMCPY(name->lName, name->fName, totalSz);
#endif #endif
@ -2618,7 +2702,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
} }
} }
if (!special && (WREADDIR(dir)) == NULL) { if (!special && (WREADDIR(ssh->fs, dir)) == NULL) {
ret = WS_NEXT_ERROR; ret = WS_NEXT_ERROR;
} }
@ -2892,7 +2976,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
} }
dp = WREADDIR(dir); dp = WREADDIR(ssh->fs, dir);
if (dp == NULL) { if (dp == NULL) {
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
@ -3033,7 +3117,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WS_SFTPNAME* name = NULL; WS_SFTPNAME* name = NULL;
WS_SFTPNAME* list = NULL; WS_SFTPNAME* list = NULL;
word32 outSz = 0; word32 outSz = 0;
DIR_HANDLE* cur = dirList; WS_DIR_LIST* cur;
char* dirName = NULL; char* dirName = NULL;
byte* out; byte* out;
@ -3043,10 +3127,16 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READDIR"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READDIR");
cur = ssh->dirList;
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
dir = INVALID_HANDLE_VALUE; dir = INVALID_HANDLE_VALUE;
#endif #endif
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get directory handle */ /* get directory handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3143,7 +3233,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
*/ */
int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz) int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
{ {
DIR_HANDLE* cur = dirList; WS_DIR_LIST* cur;
word32 h[2] = {0,0}; word32 h[2] = {0,0};
if (ssh == NULL || handle == NULL || handleSz != (sizeof(word32)*2)) { if (ssh == NULL || handle == NULL || handleSz != (sizeof(word32)*2)) {
@ -3153,6 +3243,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE Directory"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE Directory");
/* find DIR given handle */ /* find DIR given handle */
cur = ssh->dirList;
ato32(handle, &h[0]); ato32(handle, &h[0]);
ato32(handle + UINT32_SZ, &h[1]); ato32(handle + UINT32_SZ, &h[1]);
while (cur != NULL) { while (cur != NULL) {
@ -3169,18 +3260,18 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
FindClose(cur->dir); FindClose(cur->dir);
#else #else
WCLOSEDIR(&cur->dir); WCLOSEDIR(ssh->fs, &cur->dir);
#endif #endif
/* remove directory from list */ /* remove directory from list */
if (cur != NULL) { if (cur != NULL) {
DIR_HANDLE* pre = dirList; WS_DIR_LIST* pre = ssh->dirList;
WLOG(WS_LOG_SFTP, "Free'ing and closing handle %d%d pointer of [%p]", WLOG(WS_LOG_SFTP, "Free'ing and closing handle %d%d pointer of [%p]",
cur->id[1], cur->id[0], cur); cur->id[1], cur->id[0], cur);
/* case where node is at head of list */ /* case where node is at head of list */
if (pre == cur) { if (pre == cur) {
dirList = cur->next; ssh->dirList = cur->next;
WFREE(cur->dirName, ssh->ctx->heap, DYNTYPE_SFTP); WFREE(cur->dirName, ssh->ctx->heap, DYNTYPE_SFTP);
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP); WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
} }
@ -3229,6 +3320,11 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_WRITE"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_WRITE");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3252,7 +3348,7 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_BUFFER_E; return WS_BUFFER_E;
} }
ret = WPWRITE(fd, data + idx, sz, ofst); ret = WPWRITE(ssh->fs, fd, data + idx, sz, ofst);
if (ret < 0) { if (ret < 0) {
#if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH) #if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH)
if (ret == NUF_NOSPC) { if (ret == NUF_NOSPC) {
@ -3313,6 +3409,11 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_WRITE"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_WRITE");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); ato32(data + idx, &sz);
idx += UINT32_SZ; idx += UINT32_SZ;
@ -3404,6 +3505,11 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READ"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READ");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3429,7 +3535,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_MEMORY_E; return WS_MEMORY_E;
} }
ret = WPREAD(fd, out + UINT32_SZ + WOLFSSH_SFTP_HEADER, sz, ofst); ret = WPREAD(ssh->fs, fd, out + UINT32_SZ + WOLFSSH_SFTP_HEADER, sz, ofst);
if (ret < 0 || (word32)ret > sz) { if (ret < 0 || (word32)ret > sz) {
WLOG(WS_LOG_SFTP, "Error reading from file"); WLOG(WS_LOG_SFTP, "Error reading from file");
res = err; res = err;
@ -3499,6 +3605,11 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READ"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READ");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx || sz > WOLFSSH_MAX_HANDLE) { if (sz > maxSz - idx || sz > WOLFSSH_MAX_HANDLE) {
@ -3616,6 +3727,11 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3632,7 +3748,7 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
if (sz == sizeof(WFD)) { if (sz == sizeof(WFD)) {
WMEMSET((byte*)&fd, 0, sizeof(WFD)); WMEMSET((byte*)&fd, 0, sizeof(WFD));
WMEMCPY((byte*)&fd, data + idx, sz); WMEMCPY((byte*)&fd, data + idx, sz);
ret = WCLOSE(fd); ret = WCLOSE(ssh->fs, fd);
#ifdef WOLFSSH_STOREHANDLE #ifdef WOLFSSH_STOREHANDLE
if (SFTP_RemoveHandleNode(ssh, data + idx, sz) != WS_SUCCESS) { if (SFTP_RemoveHandleNode(ssh, data + idx, sz) != WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Unable to remove handle from list"); WLOG(WS_LOG_SFTP, "Unable to remove handle from list");
@ -3697,6 +3813,11 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file handle */ /* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3787,6 +3908,11 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_REMOVE"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_REMOVE");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get file name */ /* get file name */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
@ -3873,6 +3999,11 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_RENAME"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_RENAME");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
/* get old file name */ /* get old file name */
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
@ -4090,10 +4221,10 @@ int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr,
WOLFSSH_UNUSED(fs); WOLFSSH_UNUSED(fs);
if (noFollow) { if (noFollow) {
ret = WLSTAT(fileName, &stats); ret = WLSTAT(ssh->fs, fileName, &stats);
} }
else { else {
ret = WSTAT(fileName, &stats); ret = WSTAT(ssh->fs, fileName, &stats);
} }
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB)); WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
@ -4172,7 +4303,7 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
return WS_BAD_FILE_E; return WS_BAD_FILE_E;
} }
if (WSTAT(cur->name, &stats) != NU_SUCCESS) { if (WSTAT(ssh->fs, cur->name, &stats) != NU_SUCCESS) {
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
@ -4512,12 +4643,12 @@ int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr,
if (noFollow) { if (noFollow) {
/* Note, for windows, we treat WSTAT and WLSTAT the same. */ /* Note, for windows, we treat WSTAT and WLSTAT the same. */
if (WLSTAT(fileName, &stats) != 0) { if (WLSTAT(ssh->fs, fileName, &stats) != 0) {
return WS_BAD_FILE_E; return WS_BAD_FILE_E;
} }
} }
else { else {
if (WSTAT(fileName, &stats) != 0) { if (WSTAT(ssh->fs, fileName, &stats) != 0) {
return WS_BAD_FILE_E; return WS_BAD_FILE_E;
} }
} }
@ -4615,6 +4746,11 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_FSTAT"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_FSTAT");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &handleSz); idx += UINT32_SZ; ato32(data + idx, &handleSz); idx += UINT32_SZ;
if (handleSz + idx > maxSz) { if (handleSz + idx > maxSz) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -4683,6 +4819,11 @@ int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_STAT"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_STAT");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -4762,6 +4903,11 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_LSTAT"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_LSTAT");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -4946,6 +5092,11 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_SETSTAT"); WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_SETSTAT");
if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}
ato32(data + idx, &sz); idx += UINT32_SZ; ato32(data + idx, &sz); idx += UINT32_SZ;
if (sz > maxSz - idx) { if (sz > maxSz - idx) {
return WS_BUFFER_E; return WS_BUFFER_E;
@ -8221,9 +8372,9 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
WLOG(WS_LOG_SFTP, "SFTP GET STATE: OPEN LOCAL"); WLOG(WS_LOG_SFTP, "SFTP GET STATE: OPEN LOCAL");
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
if (state->gOfst[0] > 0 || state->gOfst[1] > 0) if (state->gOfst[0] > 0 || state->gOfst[1] > 0)
ret = WFOPEN(&state->fl, to, "ab"); ret = WFOPEN(ssh->fs, &state->fl, to, "ab");
else else
ret = WFOPEN(&state->fl, to, "wb"); ret = WFOPEN(ssh->fs, &state->fl, to, "wb");
#else /* USE_WINDOWS_API */ #else /* USE_WINDOWS_API */
{ {
DWORD desiredAccess = GENERIC_WRITE; DWORD desiredAccess = GENERIC_WRITE;
@ -8268,7 +8419,7 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
} }
else { else {
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
if ((long)WFWRITE(state->r, 1, if ((long)WFWRITE(ssh->fs, state->r, 1,
sz, state->fl) != sz) { sz, state->fl) != sz) {
WLOG(WS_LOG_SFTP, "Error writing to file"); WLOG(WS_LOG_SFTP, "Error writing to file");
ssh->error = WS_BAD_FILE_E; ssh->error = WS_BAD_FILE_E;
@ -8330,7 +8481,7 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
case STATE_GET_CLOSE_LOCAL: case STATE_GET_CLOSE_LOCAL:
WLOG(WS_LOG_SFTP, "SFTP GET STATE: CLOSE LOCAL"); WLOG(WS_LOG_SFTP, "SFTP GET STATE: CLOSE LOCAL");
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
WFCLOSE(state->fl); WFCLOSE(ssh->fs, state->fl);
#else /* USE_WINDOWS_API */ #else /* USE_WINDOWS_API */
if (CloseHandle(state->fileHandle) == 0) { if (CloseHandle(state->fileHandle) == 0) {
WLOG(WS_LOG_SFTP, "Error closing file."); WLOG(WS_LOG_SFTP, "Error closing file.");
@ -8419,7 +8570,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
case STATE_PUT_OPEN_LOCAL: case STATE_PUT_OPEN_LOCAL:
WLOG(WS_LOG_SFTP, "SFTP PUT STATE: OPEN LOCAL"); WLOG(WS_LOG_SFTP, "SFTP PUT STATE: OPEN LOCAL");
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
ret = WFOPEN(&state->fl, from, "rb"); ret = WFOPEN(ssh->fs, &state->fl, from, "rb");
if (ret != 0) { if (ret != 0) {
WLOG(WS_LOG_SFTP, "Unable to open input file"); WLOG(WS_LOG_SFTP, "Unable to open input file");
ssh->error = WS_SFTP_FILE_DNE; ssh->error = WS_SFTP_FILE_DNE;
@ -8433,7 +8584,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
#if SIZEOF_OFF_T == 8 #if SIZEOF_OFF_T == 8
offset = (((word64)state->pOfst[1]) << 32) | offset; offset = (((word64)state->pOfst[1]) << 32) | offset;
#endif #endif
WFSEEK(state->fl, offset, 0); WFSEEK(ssh->fs, state->fl, offset, 0);
} }
#else /* USE_WINDOWS_API */ #else /* USE_WINDOWS_API */
state->fileHandle = WS_CreateFileA(from, GENERIC_READ, state->fileHandle = WS_CreateFileA(from, GENERIC_READ,
@ -8447,7 +8598,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
} }
if (resume) { if (resume) {
WMEMSET(&state->offset, 0, sizeof(OVERLAPPED)); WMEMSET(&state->offset, 0, sizeof(OVERLAPPED));
state->offset.OffsetHigh = 0; state->offset.OffsetHigh = state->pOfst[1];
state->offset.Offset = state->pOfst[0]; state->offset.Offset = state->pOfst[0];
} }
#endif /* USE_WINDOWS_API */ #endif /* USE_WINDOWS_API */
@ -8478,7 +8629,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
do { do {
if (state->rSz == 0) { if (state->rSz == 0) {
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
state->rSz = (int)WFREAD(state->r, state->rSz = (int)WFREAD(ssh->fs, state->r,
1, WOLFSSH_MAX_SFTP_RW, state->fl); 1, WOLFSSH_MAX_SFTP_RW, state->fl);
if (state->rSz <= 0) { if (state->rSz <= 0) {
break; /* either at end of file or error */ break; /* either at end of file or error */
@ -8503,7 +8654,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
else { else {
AddAssign64(state->pOfst, sz); AddAssign64(state->pOfst, sz);
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
state->offset.OffsetHigh = 0; state->offset.OffsetHigh = state->pOfst[1];
state->offset.Offset = state->pOfst[0]; state->offset.Offset = state->pOfst[0];
#endif /* USE_WINDOWS_API */ #endif /* USE_WINDOWS_API */
state->rSz -= sz; state->rSz -= sz;
@ -8522,7 +8673,7 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
case STATE_PUT_CLOSE_LOCAL: case STATE_PUT_CLOSE_LOCAL:
WLOG(WS_LOG_SFTP, "SFTP PUT STATE: CLOSE LOCAL"); WLOG(WS_LOG_SFTP, "SFTP PUT STATE: CLOSE LOCAL");
#ifndef USE_WINDOWS_API #ifndef USE_WINDOWS_API
WFCLOSE(state->fl); WFCLOSE(ssh->fs, state->fl);
#else /* USE_WINDOWS_API */ #else /* USE_WINDOWS_API */
CloseHandle(state->fileHandle); CloseHandle(state->fileHandle);
#endif /* USE_WINDOWS_API */ #endif /* USE_WINDOWS_API */
@ -8573,7 +8724,7 @@ int wolfSSH_SFTP_free(WOLFSSH* ssh)
/* go through and free handles and make sure files are closed */ /* go through and free handles and make sure files are closed */
while (cur != NULL) { while (cur != NULL) {
WCLOSE(*((WFD*)cur->handle)); WCLOSE(ssh->fs, *((WFD*)cur->handle));
if (SFTP_RemoveHandleNode(ssh, cur->handle, cur->handleSz) if (SFTP_RemoveHandleNode(ssh, cur->handle, cur->handleSz)
!= WS_SUCCESS) { != WS_SUCCESS) {
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
@ -8586,23 +8737,23 @@ int wolfSSH_SFTP_free(WOLFSSH* ssh)
#ifndef NO_WOLFSSH_DIR #ifndef NO_WOLFSSH_DIR
{ {
/* free all dirs if hung up on */ /* free all dirs if hung up on */
DIR_HANDLE* cur = dirList; WS_DIR_LIST* cur = ssh->dirList;
/* find DIR given handle */ /* find DIR given handle */
while (cur != NULL) { while (cur != NULL) {
DIR_HANDLE* toFree = cur; WS_DIR_LIST* toFree = cur;
cur = cur->next; cur = cur->next;
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
FindClose(toFree->dir); FindClose(toFree->dir);
#else #else
WCLOSEDIR(&toFree->dir); WCLOSEDIR(ssh->fs, &toFree->dir);
#endif #endif
if (toFree->dirName != NULL) if (toFree->dirName != NULL)
WFREE(toFree->dirName, ssh->ctx->heap, DYNTYPE_SFTP); WFREE(toFree->dirName, ssh->ctx->heap, DYNTYPE_SFTP);
WFREE(toFree, ssh->ctx->heap, DYNTYPE_SFTP); WFREE(toFree, ssh->ctx->heap, DYNTYPE_SFTP);
} }
dirList = NULL; ssh->dirList = NULL;
} }
#endif /* NO_WOLFSSH_DIR */ #endif /* NO_WOLFSSH_DIR */

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

@ -493,6 +493,7 @@ struct WOLFSSH_CTX {
word32 publicKeyAlgoCount; word32 publicKeyAlgoCount;
word32 highwaterMark; word32 highwaterMark;
const char* banner; const char* banner;
const char* sshProtoIdStr;
word32 bannerSz; word32 bannerSz;
word32 windowSz; word32 windowSz;
word32 maxPacketSz; word32 maxPacketSz;
@ -571,6 +572,9 @@ typedef struct HandshakeInfo {
#ifdef WOLFSSH_SFTP #ifdef WOLFSSH_SFTP
#define WOLFSSH_MAX_SFTPOFST 3 #define WOLFSSH_MAX_SFTPOFST 3
#ifndef NO_WOLFSSH_DIR
typedef struct WS_DIR_LIST WS_DIR_LIST;
#endif
typedef struct WS_HANDLE_LIST WS_HANDLE_LIST; typedef struct WS_HANDLE_LIST WS_HANDLE_LIST;
typedef struct SFTP_OFST { typedef struct SFTP_OFST {
word32 offset[2]; word32 offset[2];
@ -578,6 +582,7 @@ typedef struct SFTP_OFST {
char to[WOLFSSH_MAX_FILENAME]; char to[WOLFSSH_MAX_FILENAME];
} SFTP_OFST; } SFTP_OFST;
struct WS_SFTP_RECV_INIT_STATE;
struct WS_SFTP_GET_STATE; struct WS_SFTP_GET_STATE;
struct WS_SFTP_PUT_STATE; struct WS_SFTP_PUT_STATE;
struct WS_SFTP_LSTAT_STATE; struct WS_SFTP_LSTAT_STATE;
@ -751,9 +756,14 @@ struct WOLFSSH {
word32 sftpExtSz; /* size of extension buffer (buffer not currently used) */ word32 sftpExtSz; /* size of extension buffer (buffer not currently used) */
SFTP_OFST sftpOfst[WOLFSSH_MAX_SFTPOFST]; SFTP_OFST sftpOfst[WOLFSSH_MAX_SFTPOFST];
char* sftpDefaultPath; char* sftpDefaultPath;
#ifndef NO_WOLFSSH_DIR
WS_DIR_LIST* dirList;
word32 dirIdCount[2];
#endif
#ifdef WOLFSSH_STOREHANDLE #ifdef WOLFSSH_STOREHANDLE
WS_HANDLE_LIST* handleList; WS_HANDLE_LIST* handleList;
#endif #endif
struct WS_SFTP_RECV_INIT_STATE* recvInitState;
struct WS_SFTP_RECV_STATE* recvState; struct WS_SFTP_RECV_STATE* recvState;
struct WS_SFTP_RMDIR_STATE* rmdirState; struct WS_SFTP_RMDIR_STATE* rmdirState;
struct WS_SFTP_MKDIR_STATE* mkdirState; struct WS_SFTP_MKDIR_STATE* mkdirState;
@ -789,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
}; };
@ -867,6 +883,13 @@ WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH*, void*, word32, void*);
#endif /* WOLFSSH_USER_IO */ #endif /* WOLFSSH_USER_IO */
enum ChannelOpenFailReasons {
OPEN_OK = 0,
OPEN_ADMINISTRATIVELY_PROHIBITED,
OPEN_CONNECT_FAILED,
OPEN_UNKNOWN_CHANNEL_TYPE,
OPEN_RESOURCE_SHORTAGE
};
WOLFSSH_LOCAL int DoReceive(WOLFSSH*); WOLFSSH_LOCAL int DoReceive(WOLFSSH*);
WOLFSSH_LOCAL int DoProtoId(WOLFSSH*); WOLFSSH_LOCAL int DoProtoId(WOLFSSH*);
@ -897,6 +920,7 @@ WOLFSSH_LOCAL int SendRequestSuccess(WOLFSSH*, int);
WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH*, WOLFSSH_CHANNEL*); WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_LOCAL int SendChannelOpenForward(WOLFSSH*, WOLFSSH_CHANNEL*); WOLFSSH_LOCAL int SendChannelOpenForward(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_LOCAL int SendChannelOpenConf(WOLFSSH*, WOLFSSH_CHANNEL*); WOLFSSH_LOCAL int SendChannelOpenConf(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_LOCAL int SendChannelOpenFail(WOLFSSH*, word32, word32, const char*, const char*);
WOLFSSH_LOCAL int SendChannelEof(WOLFSSH*, word32); WOLFSSH_LOCAL int SendChannelEof(WOLFSSH*, word32);
WOLFSSH_LOCAL int SendChannelEow(WOLFSSH*, word32); WOLFSSH_LOCAL int SendChannelEow(WOLFSSH*, word32);
WOLFSSH_LOCAL int SendChannelClose(WOLFSSH*, word32); WOLFSSH_LOCAL int SendChannelClose(WOLFSSH*, word32);
@ -904,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
@ -99,14 +105,14 @@ extern "C" {
#define WFILE int #define WFILE int
WOLFSSH_API int wfopen(WFILE**, const char*, const char*); WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m)) #define WFOPEN(fs, f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) NU_Close(*(f)) #define WFCLOSE(fs,f) NU_Close(*(f))
#define WFWRITE(b,x,s,f) ((s) != 0)? NU_Write(*(f),(const CHAR*)(b),(s)): 0 #define WFWRITE(fs,b,x,s,f) ((s) != 0)? NU_Write(*(f),(const CHAR*)(b),(s)): 0
#define WFREAD(b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s)) #define WFREAD(fs,b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s))
#define WFSEEK(s,o,w) NU_Seek(*(s),(o),(w)) #define WFSEEK(fs,s,o,w) NU_Seek(*(s),(o),(w))
#define WFTELL(s) NU_Seek(*(s), 0, PSEEK_CUR) #define WFTELL(fs,s) NU_Seek(*(s), 0, PSEEK_CUR)
#define WREWIND(s) NU_Seek(*(s), 0, PSEEK_SET) #define WREWIND(fs,s) NU_Seek(*(s), 0, PSEEK_SET)
#define WSEEK_END PSEEK_END #define WSEEK_END PSEEK_END
#define WS_DELIM '\\' #define WS_DELIM '\\'
#define WOLFSSH_O_RDWR PO_RDWR #define WOLFSSH_O_RDWR PO_RDWR
@ -124,10 +130,10 @@ extern "C" {
return NU_Open(f, PO_TEXT | flag, (PS_IWRITE | PS_IREAD)); return NU_Open(f, PO_TEXT | flag, (PS_IWRITE | PS_IREAD));
} }
#define WOPEN(f,m,p) wOpen((f),(m),(p)) #define WOPEN(fs,f,m,p) wOpen((f),(m),(p))
#endif #endif
#define WCLOSE(fd) NU_Close((fd)) #define WCLOSE(fs,fd) NU_Close((fd))
static inline int wChmod(const char* f, int mode) { static inline int wChmod(const char* f, int mode) {
unsigned char atr = 0; unsigned char atr = 0;
@ -176,13 +182,13 @@ extern "C" {
WOLFSSH_API int wfopen(WFILE**, const char*, const char*); WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m)) #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) fclose((f)) #define WFCLOSE(fs,f) fclose((f))
#define WFREAD(b,s,a,f) fread((b),(s),(a),(f)) #define WFREAD(fs,b,s,a,f) fread((b),(s),(a),(f))
#define WFWRITE(b,x,s,f) fwrite((b),(x),(s),(f)) #define WFWRITE(fs,b,x,s,f) fwrite((b),(x),(s),(f))
#define WFSEEK(s,o,w) fseek((s),(o),(w)) #define WFSEEK(fs,s,o,w) fseek((s),(o),(w))
#define WFTELL(s) ftell((s)) #define WFTELL(fs,s) ftell((s))
#define WREWIND(s) fseek((s), 0, IO_SEEK_SET) #define WREWIND(fs,s) fseek((s), 0, IO_SEEK_SET)
#define WSEEK_END IO_SEEK_END #define WSEEK_END IO_SEEK_END
#define WBADFILE NULL #define WBADFILE NULL
@ -275,7 +281,7 @@ extern "C" {
ret = f_open(*f, filename, m); ret = f_open(*f, filename, m);
return (int)ret; return (int)ret;
} }
#define WFOPEN(f, fn, m) ff_fopen((f),(fn),(m)) #define WFOPEN(fs, f, fn, m) ff_fopen((f),(fn),(m))
#ifdef WOLFSSH_XILFATFS #ifdef WOLFSSH_XILFATFS
static inline int ff_close(WFILE *f) static inline int ff_close(WFILE *f)
@ -287,7 +293,7 @@ extern "C" {
} }
#endif #endif
#define WFCLOSE(f) f_close(f) #define WFCLOSE(fs,f) f_close(f)
static inline int ff_read(void *ptr, size_t size, size_t nmemb, WFILE *f) static inline int ff_read(void *ptr, size_t size, size_t nmemb, WFILE *f)
{ {
@ -301,7 +307,7 @@ extern "C" {
} }
return (n_bytes / size); return (n_bytes / size);
} }
#define WFREAD(b,s,a,f) ff_read(b,s,a,f) #define WFREAD(fs,b,s,a,f) ff_read(b,s,a,f)
static inline int ff_write(const void *ptr, size_t size, size_t nmemb, WFILE *f) static inline int ff_write(const void *ptr, size_t size, size_t nmemb, WFILE *f)
{ {
FRESULT ret; FRESULT ret;
@ -314,9 +320,9 @@ extern "C" {
} }
return (n_bytes / size); return (n_bytes / size);
} }
#define WFWRITE(b,s,a,f) ff_write(b,s,a,f) #define WFWRITE(fs,b,s,a,f) ff_write(b,s,a,f)
#define WFTELL(s) f_tell((s)) #define WFTELL(fs,s) f_tell((s))
static inline int ff_seek(WFILE *fp, long off, int whence) static inline int ff_seek(WFILE *fp, long off, int whence)
{ {
switch(whence) { switch(whence) {
@ -333,17 +339,17 @@ extern "C" {
} }
return -1; return -1;
} }
#define WFSEEK(s,o,w) ff_seek((s),(o),(w)) #define WFSEEK(fs,s,o,w) ff_seek((s),(o),(w))
#ifdef WOLFSSH_XILFATFS #ifdef WOLFSSH_XILFATFS
#define WREWIND(s) ff_seek(s, WSEEK_SET, 0) #define WREWIND(fs,s) ff_seek(s, WSEEK_SET, 0)
#else #else
#define WREWIND(s) f_rewind(s) #define WREWIND(fs,s) f_rewind(s)
#endif #endif
#define WBADFILE (-1) #define WBADFILE (-1)
#ifndef NO_WOLFSSH_DIR #ifndef NO_WOLFSSH_DIR
#define WDIR DIR #define WDIR DIR
#define WOPENDIR(fs,h,c,d) f_opendir((c),(d)) #define WOPENDIR(fs,h,c,d) f_opendir((c),(d))
#define WCLOSEDIR(d) f_closedir(d) #define WCLOSEDIR(fs,d) f_closedir(d)
#endif #endif
#elif defined(WOLFSSH_USER_FILESYSTEM) #elif defined(WOLFSSH_USER_FILESYSTEM)
/* User-defined I/O support */ /* User-defined I/O support */
@ -355,20 +361,21 @@ extern "C" {
#define WFILE FILE #define WFILE FILE
WOLFSSH_API int wfopen(WFILE**, const char*, const char*); WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m)) #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) fclose(f) #define WFCLOSE(fs,f) fclose(f)
#define WFREAD(b,s,a,f) fread((b),(s),(a),(f)) #define WFREAD(fs,b,s,a,f) fread((b),(s),(a),(f))
#define WFWRITE(b,s,a,f) fwrite((b),(s),(a),(f)) #define WFWRITE(fs,b,s,a,f) fwrite((b),(s),(a),(f))
#define WFSEEK(s,o,w) fseek((s),(o),(w)) #define WFSEEK(fs,s,o,w) fseek((s),(o),(w))
#define WFTELL(s) ftell((s)) #define WFTELL(fs,s) ftell((s))
#define WREWIND(s) rewind((s)) #define WREWIND(fs,s) rewind((s))
#define WSEEK_END SEEK_END #define WSEEK_END SEEK_END
#define WBADFILE NULL #define WBADFILE NULL
#define WSETTIME(fs,f,a,m) (0) #define WSETTIME(fs,f,a,m) (0)
#define WFSETTIME(fs,fd,a,m) (0) #define WFSETTIME(fs,fd,a,m) (0)
#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
@ -408,13 +415,13 @@ extern "C" {
#ifndef _WIN32_WCE #ifndef _WIN32_WCE
#include <direct.h> #include <direct.h>
#define WCHDIR(p) _chdir((p)) #define WCHDIR(fs,p) _chdir((p))
#define WMKDIR(fs,p,m) _mkdir((p)) #define WMKDIR(fs,p,m) _mkdir((p))
#endif #endif
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#define WCHDIR(p) chdir((p)) #define WCHDIR(fs,p) chdir((p))
#ifdef WOLFSSL_VXWORKS #ifdef WOLFSSL_VXWORKS
#define WMKDIR(fs,p,m) mkdir((p)) #define WMKDIR(fs,p,m) mkdir((p))
#else #else
@ -456,7 +463,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)
@ -486,7 +493,7 @@ extern "C" {
#endif /* WSTRING_USER */ #endif /* WSTRING_USER */
/* get local time for debug print out */ /* get local time for debug print out */
#ifdef USE_WINDOWS_API #if defined(USE_WINDOWS_API) || defined(__MINGW32__)
#define WTIME time #define WTIME time
#define WLOCALTIME(c,r) (localtime_s((r),(c))==0) #define WLOCALTIME(c,r) (localtime_s((r),(c))==0)
#elif defined(MICROCHIP_MPLAB_HARMONY) #elif defined(MICROCHIP_MPLAB_HARMONY)
@ -534,8 +541,8 @@ extern "C" {
#define WSTAT_T struct stat #define WSTAT_T struct stat
#define WRMDIR(fs,d) (NU_Remove_Dir((d)) == NU_SUCCESS)?0:1 #define WRMDIR(fs,d) (NU_Remove_Dir((d)) == NU_SUCCESS)?0:1
#define WMKDIR(fs,d,m) (NU_Make_Dir((d)) == NU_SUCCESS)?0:1 #define WMKDIR(fs,d,m) (NU_Make_Dir((d)) == NU_SUCCESS)?0:1
#define WSTAT(p,b) NU_Get_First((b),(p)) #define WSTAT(fs,p,b) NU_Get_First((b),(p))
#define WLSTAT(p,b) NU_Get_First((b),(p)) #define WLSTAT(fs,p,b) NU_Get_First((b),(p))
#define WREMOVE(fs,d) NU_Delete((d)) #define WREMOVE(fs,d) NU_Delete((d))
#ifndef WS_MAX_RENAME_BUF #ifndef WS_MAX_RENAME_BUF
@ -558,39 +565,39 @@ extern "C" {
WFILE* fNew; WFILE* fNew;
unsigned char buf[WS_MAX_RENAME_BUF]; unsigned char buf[WS_MAX_RENAME_BUF];
if ((ret = WFOPEN(&fOld, o, "rb")) != 0) { if ((ret = WFOPEN(NULL, &fOld, o, "rb")) != 0) {
return ret; return ret;
} }
if ((ret = WFOPEN(&fNew, n, "rwb")) != 0) { if ((ret = WFOPEN(NULL, &fNew, n, "rwb")) != 0) {
WFCLOSE(fOld); WFCLOSE(NULL, fOld);
return ret; return ret;
} }
/* read from the file in chunks and write chunks to new file */ /* read from the file in chunks and write chunks to new file */
do { do {
ret = WFREAD(buf, 1, WS_MAX_RENAME_BUF, fOld); ret = WFREAD(NULL, buf, 1, WS_MAX_RENAME_BUF, fOld);
if (ret > 0) { if (ret > 0) {
if ((WFWRITE(buf, 1, ret, fNew)) != ret) { if ((WFWRITE(NULL, buf, 1, ret, fNew)) != ret) {
WFCLOSE(fOld); WFCLOSE(NULL, fOld);
WFCLOSE(fNew); WFCLOSE(NULL, fNew);
WREMOVE(NULL, n); WREMOVE(NULL, n);
return NUF_BADPARM; return NUF_BADPARM;
} }
} }
} while (ret > 0); } while (ret > 0);
if (WFTELL(fOld) == WFSEEK(fOld, 0, WSEEK_END)) { if (WFTELL(NULL, fOld) == WFSEEK(NULL, fOld, 0, WSEEK_END)) {
/* wrote everything from file */ /* wrote everything from file */
WFCLOSE(fOld); WFCLOSE(NULL, fOld);
WREMOVE(NULL, o); WREMOVE(NULL, o);
WFCLOSE(fNew); WFCLOSE(NULL, fNew);
} }
else { else {
/* unable to write everything to file */ /* unable to write everything to file */
WFCLOSE(fNew); WFCLOSE(NULL, fNew);
WREMOVE(NULL, n); WREMOVE(NULL, n);
WFCLOSE(fOld); WFCLOSE(NULL, fOld);
return NUF_BADPARM; return NUF_BADPARM;
} }
@ -639,7 +646,7 @@ extern "C" {
return NU_Write(fd, (const CHAR*)buf, sz); return NU_Write(fd, (const CHAR*)buf, sz);
} }
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
#endif #endif
#ifndef WPREAD #ifndef WPREAD
@ -653,7 +660,7 @@ extern "C" {
return NU_Read(fd, (CHAR*)buf, sz); return NU_Read(fd, (CHAR*)buf, sz);
} }
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
#endif #endif
static inline int wUtimes(const char* f, struct timeval t[2]) static inline int wUtimes(const char* f, struct timeval t[2])
@ -743,8 +750,8 @@ extern "C" {
#define WOPENDIR(fs,h,c,d) wOpenDir((c),(d)) #define WOPENDIR(fs,h,c,d) wOpenDir((c),(d))
#endif #endif
#define WCLOSEDIR(d) NU_Done((d)) #define WCLOSEDIR(fs,d) NU_Done((d))
#define WREADDIR(d) (NU_Get_Next((d)) == NU_SUCCESS)?(d):NULL #define WREADDIR(fs,d) (NU_Get_Next((d)) == NU_SUCCESS)?(d):NULL
#endif /* NO_WOLFSSH_DIR */ #endif /* NO_WOLFSSH_DIR */
#elif defined(FREESCALE_MQX) #elif defined(FREESCALE_MQX)
@ -806,7 +813,7 @@ extern "C" {
return fopen(f, mode); return fopen(f, mode);
} }
#define WOPEN(f,m,p) wOpen((f),(m),(p)) #define WOPEN(fs,f,m,p) wOpen((f),(m),(p))
#endif #endif
#ifndef WRMDIR #ifndef WRMDIR
@ -985,7 +992,7 @@ extern "C" {
#define WGETCWD(fs,r,rSz) wGetCwd((fs),(r),(rSz)) #define WGETCWD(fs,r,rSz) wGetCwd((fs),(r),(rSz))
#endif /* WGETCWD */ #endif /* WGETCWD */
#define WCLOSE fclose #define WCLOSE(fs,fd) fclose(fd)
#ifndef WPWRITE #ifndef WPWRITE
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz,
@ -1000,7 +1007,7 @@ extern "C" {
return fwrite(buf, sz, 1, fd); return fwrite(buf, sz, 1, fd);
} }
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
#endif #endif
#ifndef WPREAD #ifndef WPREAD
@ -1016,7 +1023,7 @@ extern "C" {
return fread(buf, 1, sz, fd); return fread(buf, 1, sz, fd);
} }
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
#endif #endif
#ifndef NO_WOLFSSH_DIR #ifndef NO_WOLFSSH_DIR
@ -1114,7 +1121,7 @@ extern "C" {
return 0; return 0;
} }
#define WCLOSEDIR(d) wCloseDir((d)) #define WCLOSEDIR(fs,d) wCloseDir((d))
#endif /* WCLOSEDIR */ #endif /* WCLOSEDIR */
#endif /* NO_WOLFSSH_DIR */ #endif /* NO_WOLFSSH_DIR */
@ -1122,10 +1129,10 @@ extern "C" {
#define WSTAT_T FILINFO #define WSTAT_T FILINFO
#define WRMDIR(fs, d) f_unlink((d)) #define WRMDIR(fs, d) f_unlink((d))
#define WSTAT(p,b) f_stat(p,b) #define WSTAT(fs,p,b) f_stat(p,b)
#define WLSTAT(p,b) f_stat(p,b) #define WLSTAT(fs,p,b) f_stat(p,b)
#define WREMOVE(fs,d) f_unlink((d)) #define WREMOVE(fs,d) f_unlink((d))
#define WRENAME(fd,o,n) f_rename((o),(n)) #define WRENAME(fs,fd,o,n) f_rename((o),(n))
#define WMKDIR(fs, p, m) f_mkdir(p) #define WMKDIR(fs, p, m) f_mkdir(p)
#define WFD int #define WFD int
@ -1133,10 +1140,10 @@ extern "C" {
int ff_close(int fd); int ff_close(int fd);
int ff_pwrite(int fd, const byte *buffer, int sz); int ff_pwrite(int fd, const byte *buffer, int sz);
int ff_pread(int fd, byte *buffer, int sz); int ff_pread(int fd, byte *buffer, int sz);
#define WOPEN(f,m,p) ff_open(f,m,p) #define WOPEN(fs,f,m,p) ff_open(f,m,p)
#define WPWRITE(fd,b,s,o) ff_pwrite(fd,b,s) #define WPWRITE(fs,fd,b,s,o) ff_pwrite(fd,b,s)
#define WPREAD(fd,b,s,o) ff_pread(fd,b,s) #define WPREAD(fs,fd,b,s,o) ff_pread(fd,b,s)
#define WCLOSE(fd) ff_close(fd) #define WCLOSE(fs,fd) ff_close(fd)
static inline int ff_chmod(const char *fname, int mode) static inline int ff_chmod(const char *fname, int mode)
{ {
@ -1187,19 +1194,19 @@ extern "C" {
#define WSTAT_T struct _stat #define WSTAT_T struct _stat
#define WRMDIR(fs,d) _rmdir((d)) #define WRMDIR(fs,d) _rmdir((d))
#define WSTAT(p,b) _stat((p),(b)) #define WSTAT(fs,p,b) _stat((p),(b))
#define WLSTAT(p,b) _stat((p),(b)) #define WLSTAT(fs,p,b) _stat((p),(b))
#define WREMOVE(fs,d) remove((d)) #define WREMOVE(fs,d) remove((d))
#define WRENAME(fs,o,n) rename((o),(n)) #define WRENAME(fs,o,n) rename((o),(n))
#define WGETCWD(fs,r,rSz) _getcwd((r),(rSz)) #define WGETCWD(fs,r,rSz) _getcwd((r),(rSz))
#define WOPEN(f,m,p) _open((f),(m),(p)) #define WOPEN(fs,f,m,p) _open((f),(m),(p))
#define WCLOSE(fd) _close((fd)) #define WCLOSE(fs,fd) _close((fd))
#define WFD int #define WFD int
int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*);
int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); int wPread(WFD, unsigned char*, unsigned int, const unsigned int*);
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
#define WS_DELIM '\\' #define WS_DELIM '\\'
#define WOLFSSH_O_RDWR _O_RDWR #define WOLFSSH_O_RDWR _O_RDWR
@ -1226,11 +1233,11 @@ extern "C" {
#define WSTAT_T struct stat #define WSTAT_T struct stat
#define WRMDIR(fs,d) rmdir((d)) #define WRMDIR(fs,d) rmdir((d))
#define WSTAT(p,b) stat((p),(b)) #define WSTAT(fs,p,b) stat((p),(b))
#ifndef USE_OSE_API #ifndef USE_OSE_API
#define WLSTAT(p,b) lstat((p),(b)) #define WLSTAT(fs,p,b) lstat((p),(b))
#else #else
#define WLSTAT(p,b) stat((p),(b)) #define WLSTAT(fs,p,b) stat((p),(b))
#endif #endif
#define WREMOVE(fs,d) remove((d)) #define WREMOVE(fs,d) remove((d))
#define WRENAME(fs,o,n) rename((o),(n)) #define WRENAME(fs,o,n) rename((o),(n))
@ -1247,12 +1254,12 @@ extern "C" {
#define WOLFSSH_O_TRUNC O_TRUNC #define WOLFSSH_O_TRUNC O_TRUNC
#define WOLFSSH_O_EXCL O_EXCL #define WOLFSSH_O_EXCL O_EXCL
#define WOPEN(f,m,p) open((f),(m),(p)) #define WOPEN(fs,f,m,p) open((f),(m),(p))
#define WCLOSE(fd) close((fd)) #define WCLOSE(fs,fd) close((fd))
int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*);
int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); int wPread(WFD, unsigned char*, unsigned int, const unsigned int*);
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
#ifndef NO_WOLFSSH_DIR #ifndef NO_WOLFSSH_DIR
#include <dirent.h> /* used for opendir, readdir, and closedir */ #include <dirent.h> /* used for opendir, readdir, and closedir */
@ -1260,9 +1267,9 @@ extern "C" {
/* returns 0 on success */ /* returns 0 on success */
#define WOPENDIR(fs,h,c,d) ((*(c) = opendir((d))) == NULL) #define WOPENDIR(fs,h,c,d) ((*(c) = opendir((d))) == NULL)
#define WCLOSEDIR(d) closedir(*(d)) #define WCLOSEDIR(fs,d) closedir(*(d))
#define WREADDIR(d) readdir(*(d)) #define WREADDIR(fs,d) readdir(*(d))
#define WREWINDDIR(d) rewinddir(*(d)) #define WREWINDDIR(fs,d) rewinddir(*(d))
#endif /* NO_WOLFSSH_DIR */ #endif /* NO_WOLFSSH_DIR */
#endif #endif
#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */ #endif /* WOLFSSH_SFTP or WOLFSSH_SCP */

View File

@ -236,6 +236,7 @@ WOLFSSH_API int wolfSSH_SetUsername(WOLFSSH*, const char*);
WOLFSSH_API char* wolfSSH_GetUsername(WOLFSSH*); WOLFSSH_API char* wolfSSH_GetUsername(WOLFSSH*);
WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX*, const char*); WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX*, const char*);
WOLFSSH_API int wolfSSH_CTX_SetSshProtoIdStr(WOLFSSH_CTX*, const char*);
WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*, WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*,
const byte*, word32, int); const byte*, word32, int);
#ifdef WOLFSSH_CERTS #ifdef WOLFSSH_CERTS
@ -282,6 +283,13 @@ 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*);
WOLFSSH_API void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh,
WS_CallbackTerminalSize cb);
WOLFSSH_API void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx);
enum WS_HighwaterSide { enum WS_HighwaterSide {
@ -317,7 +325,8 @@ enum WS_UserAuthResults
WOLFSSH_USERAUTH_INVALID_USER, WOLFSSH_USERAUTH_INVALID_USER,
WOLFSSH_USERAUTH_INVALID_PASSWORD, WOLFSSH_USERAUTH_INVALID_PASSWORD,
WOLFSSH_USERAUTH_REJECTED, WOLFSSH_USERAUTH_REJECTED,
WOLFSSH_USERAUTH_INVALID_PUBLICKEY WOLFSSH_USERAUTH_INVALID_PUBLICKEY,
WOLFSSH_USERAUTH_PARTIAL_SUCCESS
}; };
enum WS_DisconnectReasonCodes { enum WS_DisconnectReasonCodes {

View File

@ -719,8 +719,8 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
int depth, res; int depth, res;
WFILE* file; WFILE* file;
for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) {
if (WFOPEN(&file, serverKeyRsaPemFile, "rb") == 0) { if (WFOPEN(NULL, &file, serverKeyRsaPemFile, "rb") == 0) {
WFCLOSE(file); WFCLOSE(NULL, file);
return depth; return depth;
} }
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API

View File

@ -41,7 +41,7 @@ extern "C" {
*/ */
#if defined(BUILDING_WOLFSSH) #if defined(BUILDING_WOLFSSH)
#if defined(_MSC_VER) || defined(__CYGWIN__) #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
#ifdef WOLFSSH_DLL #ifdef WOLFSSH_DLL
#define WOLFSSH_API extern __declspec(dllexport) #define WOLFSSH_API extern __declspec(dllexport)
#else #else
@ -59,7 +59,7 @@ extern "C" {
#define WOLFSSH_LOCAL #define WOLFSSH_LOCAL
#endif /* HAVE_VISIBILITY */ #endif /* HAVE_VISIBILITY */
#else /* BUILDING_WOLFSSH */ #else /* BUILDING_WOLFSSH */
#if defined(_MSC_VER) || defined(__CYGWIN__) #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
#ifdef WOLFSSH_DLL #ifdef WOLFSSH_DLL
#define WOLFSSH_API extern __declspec(dllimport) #define WOLFSSH_API extern __declspec(dllimport)
#else #else

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 */