Merge branch 'master' into pull-reqs/f4021bb_All_the_filesystem-related_W_macros_accept_a_filesystem_context_pointer_as_first_parameter

pull/556/head
John Safranek 2023-09-01 09:08:34 -07:00 committed by GitHub
commit d4fa4ebd69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 2766 additions and 596 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,32 +426,13 @@ static int CheckPasswordUnix(const char* usr, const byte* pw, word32 pwSz)
WFREE(storedHashCpy, NULL, DYNTYPE_STRING); WFREE(storedHashCpy, NULL, DYNTYPE_STRING);
} }
WOLFSSH_UNUSED(authCtx);
return ret; return ret;
} }
#endif /* WOLFSSH_USE_PAM */ #endif /* WOLFSSH_USE_PAM */
#endif /* !_WIN32 */ #endif /* !_WIN32 */
#ifndef _WIN32
static int CheckUserUnix(const char* name) {
int ret = WSSHD_AUTH_FAILURE;
struct passwd* pwInfo;
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Unix check user");
errno = 0;
pwInfo = getpwnam(name);
if (pwInfo == NULL) {
if (errno != 0) {
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Error calling getpwnam for user "
"%s.", name);
ret = WS_FATAL_ERROR;
}
}
else {
ret = WSSHD_AUTH_SUCCESS;
}
return ret;
}
static const char authKeysDefault[] = ".ssh/authorized_keys"; static const char authKeysDefault[] = ".ssh/authorized_keys";
static char authKeysPattern[MAX_PATH_SZ] = { 0 }; static char authKeysPattern[MAX_PATH_SZ] = { 0 };
@ -451,6 +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;
@ -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(&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(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; ret = WOLFSSH_USERAUTH_SUCCESS;
} }
else {
wolfSSH_Log(WS_LOG_ERROR,
"[SSHD] Error getting users token.");
ret = WOLFSSH_USERAUTH_FAILURE;
}
#else
ret = WOLFSSH_USERAUTH_SUCCESS;
#endif
}
else { else {
/* if not a certificate then parse through authorized key file */ /* if not a certificate then parse through authorized key file */
rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey, rc = authCtx->checkPublicKeyCb(usr, &authData->sf.publicKey,
wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf)); wolfSSHD_ConfigGetUserCAKeysFile(authCtx->conf),
authCtx);
if (rc == WSSHD_AUTH_SUCCESS) { if (rc == WSSHD_AUTH_SUCCESS) {
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok."); wolfSSH_Log(WS_LOG_INFO, "[SSHD] Public key ok.");
ret = WOLFSSH_USERAUTH_SUCCESS; ret = WOLFSSH_USERAUTH_SUCCESS;
} }
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 */
@ -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(&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(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(&f, conf->pidFile, "wb") == 0) {
WSNPRINTF(buf, sizeof(buf), "%d", getpid());
WFWRITE(buf, 1, WSTRLEN(buf), f);
WFCLOSE(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);

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;
@ -181,6 +188,109 @@ 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
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 +308,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 +344,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 +361,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,7 +386,13 @@ static THREAD_RET readPeer(void* in)
if (ret < 0) if (ret < 0)
err_sys("Extended data read failed."); err_sys("Extended data read failed.");
buf[bufSz - 1] = '\0'; buf[bufSz - 1] = '\0';
#ifdef USE_WINDOWS_API
fprintf(stderr, "%s", buf); fprintf(stderr, "%s", buf);
#else
if (write(STDERR_FILENO, buf, ret) < 0) {
perror("Issue with stderr write ");
}
#endif
} while (ret > 0); } while (ret > 0);
} }
else if (ret <= 0) { else if (ret <= 0) {
@ -327,7 +455,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 +759,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 +858,39 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (cmd != NULL || keepOpen == 1) { if (cmd != NULL || keepOpen == 1) {
#if defined(_POSIX_THREADS) #if defined(_POSIX_THREADS)
thread_args arg; thread_args arg;
pthread_t thread[2]; pthread_t thread[3];
arg.ssh = ssh; arg.ssh = ssh;
wc_InitMutex(&arg.lock); wc_InitMutex(&arg.lock);
pthread_create(&thread[0], NULL, readInput, (void*)&arg); #if (defined(__OSX__) || defined(__APPLE__))
pthread_create(&thread[1], NULL, readPeer, (void*)&arg); windowSem = dispatch_semaphore_create(0);
pthread_join(thread[1], NULL); #else
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);
pthread_cancel(thread[0]); pthread_cancel(thread[0]);
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 +898,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,6 +952,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
#endif #endif
} }
ret = wolfSSH_shutdown(ssh); ret = wolfSSH_shutdown(ssh);
/* do not continue on with shutdown process if peer already disconnected */
if (ret != WS_SOCKET_ERROR_E && wolfSSH_get_error(ssh) != WS_SOCKET_ERROR_E) {
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
err_sys("Sending the shutdown messages failed."); err_sys("Sending the shutdown messages failed.");
} }
@ -792,11 +961,12 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
err_sys("Failed to listen for close messages from the peer."); err_sys("Failed to listen for close messages from the peer.");
} }
}
WCLOSESOCKET(sockFd); WCLOSESOCKET(sockFd);
wolfSSH_free(ssh); wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx); wolfSSH_CTX_free(ctx);
if (ret != WS_SUCCESS) if (ret != WS_SUCCESS && ret != WS_SOCKET_ERROR_E)
err_sys("Closing client stream failed. Connection could have been closed by peer"); err_sys("Closing client stream failed");
ClientFreeBuffers(pubKeyName, privKeyName); ClientFreeBuffers(pubKeyName, privKeyName);
#if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) #if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)

View File

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

View File

@ -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,6 +1038,7 @@ static int doAutopilot(int cmd, char* local, char* remote)
} }
if (remoteAbsPath) { if (remoteAbsPath) {
/* use remote absolute path if provided */
WMEMSET(fullpath, 0, sizeof(fullpath)); WMEMSET(fullpath, 0, sizeof(fullpath));
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1); WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1);
} }
@ -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
@ -141,6 +146,22 @@ Global
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.Build.0 = Release|Win32 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|Win32.Build.0 = Release|Win32
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.ActiveCfg = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.ActiveCfg = Release|x64
{8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.Build.0 = Release|x64 {8DD810D6-159B-4C40-B682-FCA11F9B3680}.Release|x64.Build.0 = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|Win32.ActiveCfg = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|Win32.Build.0 = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|x64.ActiveCfg = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Debug|x64.Build.0 = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|Win32.ActiveCfg = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|Win32.Build.0 = Debug|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|x64.ActiveCfg = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Debug|x64.Build.0 = Debug|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|Win32.ActiveCfg = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|Win32.Build.0 = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|x64.ActiveCfg = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.DLL Release|x64.Build.0 = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|Win32.ActiveCfg = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|Win32.Build.0 = Release|Win32
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|x64.ActiveCfg = Release|x64
{9A31DAB4-6292-4ECB-BE35-C60D925C571E}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

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

View File

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\apps\wolfsshd\auth.c" />
<ClCompile Include="..\..\..\apps\wolfsshd\configuration.c" />
<ClCompile Include="..\..\..\apps\wolfsshd\wolfsshd.c" />
</ItemGroup>
<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>
<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>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
<IntDir>$(Configuration)\$(Platform)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Debug\Win32;..\Debug\Win32</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\..\wolfssl\Release\Win32;..\Release\Win32</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WOLFSSL_USER_SETTINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..;..\..\..;$(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>
<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);
} }
@ -5834,17 +5879,39 @@ 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_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;
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_SUCCESS) {
ret = WS_SUCCESS;
}
else {
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");
@ -6358,6 +6425,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 +6456,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 +6482,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 +6491,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 +6521,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 +6766,7 @@ static int DoChannelRequest(WOLFSSH* ssh,
char term[32]; char term[32];
word32 termSz; word32 termSz;
word32 widthChar, heightRows, widthPixels, heightPixels; word32 widthChar, heightRows, widthPixels, heightPixels;
word32 modesSz; byte opCode = 0;
termSz = (word32)sizeof(term); termSz = (word32)sizeof(term);
ret = GetString(term, &termSz, buf, len, &begin); ret = GetString(term, &termSz, buf, len, &begin);
@ -6687,8 +6778,14 @@ static int DoChannelRequest(WOLFSSH* ssh,
ret = GetUint32(&widthPixels, buf, len, &begin); ret = GetUint32(&widthPixels, buf, len, &begin);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetUint32(&heightPixels, buf, len, &begin); ret = GetUint32(&heightPixels, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&modesSz, buf, len, &begin); /* itterate over op codes */
if (ret == WS_SUCCESS) {
do {
opCode = buf[begin];
begin++;
} while (opCode != 0 && begin < len);
}
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, " term = %s", term); WLOG(WS_LOG_DEBUG, " term = %s", term);
@ -6696,7 +6793,14 @@ static int DoChannelRequest(WOLFSSH* ssh,
WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows); WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows);
WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels); WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels);
WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels); WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels);
WLOG(WS_LOG_DEBUG, " modes = %u", (modesSz - 1) / 5); ssh->curX = widthChar;
ssh->curY = heightRows;
if (ssh->termResizeCb) {
if (ssh->termResizeCb(ssh, widthChar, heightRows, widthPixels,
heightPixels, ssh->termCtx) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
}
}
} }
} }
else else
@ -6746,6 +6850,34 @@ static int DoChannelRequest(WOLFSSH* ssh,
WLOG(WS_LOG_AGENT, "Agent callback not set, not using."); WLOG(WS_LOG_AGENT, "Agent callback not set, not using.");
} }
#endif /* WOLFSSH_AGENT */ #endif /* WOLFSSH_AGENT */
#ifdef WOLFSSH_SHELL
else if (WSTRNCMP(type, "window-change", typeSz) == 0) {
word32 widthChar, heightRows, widthPixels, heightPixels;
ret = GetUint32(&widthChar, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&heightRows, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&widthPixels, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&heightPixels, buf, len, &begin);
if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, " widthChar = %u", widthChar);
WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows);
WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels);
WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels);
ssh->curX = widthChar;
ssh->curY = heightRows;
if (ssh->termResizeCb) {
if (ssh->termResizeCb(ssh, widthChar, heightRows, widthPixels,
heightPixels, ssh->termCtx) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
}
}
}
}
#endif
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
@ -7632,7 +7764,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 +7860,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 +7911,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 +8470,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 +8606,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 +8889,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 +9168,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:
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 #ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256: if (ssh->handshake->kexId == ID_DH_GEX_SHA256)
primeGroup = dhPrimeGroup14;
primeGroupSz = dhPrimeGroup14Sz;
generator = dhGenerator;
generatorSz = dhGeneratorSz;
msgId = MSGID_KEXDH_GEX_REPLY; msgId = MSGID_KEXDH_GEX_REPLY;
break;
#endif #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 +9361,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 +12318,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 +12982,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)sizeof(cType) - 1;
ret = PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ +
typeSz + BOOLEAN_SZ + (4 * UINT32_SZ));
}
if (ret == WS_SUCCESS) {
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_REQUEST;
c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ;
c32toa(typeSz, output + idx);
idx += LENGTH_SZ;
WMEMCPY(output + idx, cType, typeSz);
idx += typeSz;
output[idx++] = 0;
c32toa(columns, output + idx);
idx += UINT32_SZ;
c32toa(rows, output + idx);
idx += UINT32_SZ;
c32toa(widthPixels, output + idx);
idx += UINT32_SZ;
c32toa(heightPixels, output + idx);
idx += UINT32_SZ;
ssh->outputBuffer.length = idx;
WLOG(WS_LOG_INFO, "Sending Channel Request: ");
WLOG(WS_LOG_INFO, " channelId = %u", channel->peerChannel);
WLOG(WS_LOG_INFO, " type = %s", cType);
WLOG(WS_LOG_INFO, " wantReply = %u", 0);
ret = BundlePacket(ssh);
}
if (ret == WS_SUCCESS)
ret = wolfSSH_SendPacket(ssh);
return ret;
}
#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 +13085,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 +13093,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 +13515,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

@ -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.
* *
@ -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

@ -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,16 +1158,17 @@ 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(ssh->fs, &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(ssh->fs, &ctx, ssh->ctx->heap); ret = ScpPopDir(ssh->fs, &ctx, ssh->ctx->heap);
@ -1262,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;
@ -1767,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.
@ -2080,7 +2095,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
return ret; return ret;
} }
static int GetFileSize(void *fs, WFILE* fp, word32* fileSz) static int _GetFileSize(WFILE* fp, word32* fileSz)
{ {
WOLFSSH_UNUSED(fs); WOLFSSH_UNUSED(fs);
@ -2108,6 +2123,22 @@ static int GetFileStats(void *fs, ScpSendCtx* ctx, const char* fileName,
} }
/* get file stats for times and mode */ /* get file stats for times and mode */
#if defined(USE_WINDOWS_API)
BOOL error;
error = !WS_GetFileAttributesExA(fileName, &ctx->s, NULL);
if (error)
return WS_BAD_FILE_E;
*aTime = ((word64)ctx->s.ftLastAccessTime.dwHighDateTime << 32) |
(word64)ctx->s.ftLastAccessTime.dwLowDateTime;
*mTime = ((word64)ctx->s.ftLastWriteTime.dwHighDateTime << 32) |
(word64)ctx->s.ftLastWriteTime.dwLowDateTime;
*fileMode = 0555 |
(ctx->s.dwFileAttributes | FILE_ATTRIBUTE_READONLY ? 0 : 0200);
*fileMode |= (ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0x4000 : 0;
#else
if (WSTAT(fs, fileName, &ctx->s) < 0) { if (WSTAT(fs, fileName, &ctx->s) < 0) {
ret = WS_BAD_FILE_E; ret = WS_BAD_FILE_E;
#ifdef WOLFSSL_NUCLEUS #ifdef WOLFSSL_NUCLEUS
@ -2117,7 +2148,8 @@ static int GetFileStats(void *fs, 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 */
@ -2137,6 +2169,7 @@ static int GetFileStats(void *fs, 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;
} }
@ -2162,6 +2195,24 @@ static ScpDir* ScpNewDir(void *fs, const char* path, void* heap)
} }
entry->next = NULL; entry->next = NULL;
#ifdef USE_WINDOWS_API
{
char sPath[MAX_PATH];
int isDir;
/* add wildcard to get full directory */
WSNPRINTF(sPath, MAX_PATH, "%s/*", path);
entry->dir = (HANDLE)WS_FindFirstFileA(sPath,
sPath, sizeof(sPath), &isDir, heap);
if (entry->dir == INVALID_HANDLE_VALUE) {
WFREE(entry, heap, DYNTYPE_SCPDIR);
WLOG(WS_LOG_ERROR, scpError, "opendir failed on directory",
WS_INVALID_PATH_E);
return NULL;
}
}
#else
if (WOPENDIR(fs, heap, &entry->dir, path) != 0 if (WOPENDIR(fs, heap, &entry->dir, path) != 0
#ifndef WOLFSSL_NUCLEUS #ifndef WOLFSSL_NUCLEUS
|| entry->dir == NULL || entry->dir == NULL
@ -2172,7 +2223,7 @@ static ScpDir* ScpNewDir(void *fs, const char* path, void* heap)
WS_INVALID_PATH_E); WS_INVALID_PATH_E);
return NULL; return NULL;
} }
#endif
return entry; return entry;
} }
@ -2218,7 +2269,11 @@ int ScpPopDir(void *fs, ScpSendCtx* ctx, void* heap)
} }
if (entry != NULL) { if (entry != NULL) {
#ifdef USE_WINDOWS_API
FindClose(entry->dir);
#else
WCLOSEDIR(fs, &entry->dir); WCLOSEDIR(fs, &entry->dir);
#endif
WFREE(entry, heap, DYNTYPE_SCPDIR); WFREE(entry, heap, DYNTYPE_SCPDIR);
} }
@ -2279,12 +2334,42 @@ static int FindNextDirEntry(void *fs, 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(fs, &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;
@ -2304,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
@ -2313,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
@ -2343,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
@ -2365,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);
@ -2398,7 +2499,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = GetFileSize(ssh->fs, sendCtx->fp, totalFileSz); ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp); ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp);
@ -2549,7 +2650,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
} }
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileSize(ssh->fs, sendCtx->fp, totalFileSz); ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetFileStats(ssh->fs, sendCtx, peerRequest, mTime, aTime, fileMode); ret = GetFileStats(ssh->fs, sendCtx, peerRequest, mTime, aTime, fileMode);

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,31 +1001,55 @@ 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) {
case SFTP_BEGIN:
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer, RECV_INIT_SIZE);
if (ret < 0) {
return WS_FATAL_ERROR;
}
if (ret < WOLFSSH_SFTP_HEADER) {
WLOG(WS_LOG_SFTP, "Unable to read SFTP INIT message");
return WS_FATAL_ERROR;
}
if (SFTP_GetSz(state->buffer.data, &sz,
MSG_ID_SZ + UINT32_SZ, WOLFSSH_MAX_SFTP_RECV) != WS_SUCCESS) { MSG_ID_SZ + UINT32_SZ, WOLFSSH_MAX_SFTP_RECV) != WS_SUCCESS) {
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL); wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return WS_BUFFER_E; return WS_BUFFER_E;
} }
/* compare versions supported */ /* compare versions supported */
id = buf[LENGTH_SZ]; id = state->buffer.data[LENGTH_SZ];
if (id != WOLFSSH_FTP_INIT) { if (id != WOLFSSH_FTP_INIT) {
WLOG(WS_LOG_SFTP, "Unexpected SFTP type received"); WLOG(WS_LOG_SFTP, "Unexpected SFTP type received");
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL); wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
return WS_BUFFER_E; return WS_BUFFER_E;
} }
ato32(buf + LENGTH_SZ + MSG_ID_SZ, &version); ato32(state->buffer.data + LENGTH_SZ + MSG_ID_SZ, &version);
/* versions greater than WOLFSSH_SFTP_VERSION should fall back to ours /* versions greater than WOLFSSH_SFTP_VERSION should fall back to ours
* versions less than WOLFSSH_SFTP_VERSION we should bail out on or * versions less than WOLFSSH_SFTP_VERSION we should bail out on or
* implement a fall back */ * implement a fall back */
@ -1021,15 +1059,27 @@ static int SFTP_ServerRecvInit(WOLFSSH* ssh) {
return WS_VERSION_E; 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 */ /* silently ignore extensions if not supported */
sz = sz - MSG_ID_SZ - UINT32_SZ; if (state->extSz > 0) {
if (sz > 0) { ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer, (int)state->extSz);
byte* data = (byte*)WMALLOC(sz, NULL, DYNTYPE_BUFFER); if (ret < 0) {
if (data == NULL) return WS_MEMORY_E; return WS_FATAL_ERROR;
len = wolfSSH_stream_read(ssh, data, sz); }
WFREE(data, NULL, DYNTYPE_BUFFER);
if (len != (int)sz) if (ret < (int)state->extSz) {
return len; 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:
@ -1640,6 +1697,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;
@ -1715,6 +1777,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;
@ -1914,6 +1981,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;
@ -2042,6 +2114,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;
@ -2142,16 +2219,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
@ -2183,6 +2257,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) {
@ -2206,13 +2285,12 @@ 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(ssh->fs, &ctx); WCLOSEDIR(ssh->fs, &ctx);
@ -2232,15 +2310,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);
@ -2293,6 +2371,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;
@ -2359,24 +2442,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;
} }
@ -2448,15 +2530,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) {
@ -2501,7 +2583,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
@ -2515,8 +2599,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
@ -3028,7 +3112,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;
@ -3038,10 +3122,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) {
@ -3138,7 +3228,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)) {
@ -3148,6 +3238,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,13 +3260,13 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
/* 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);
} }
@ -3224,6 +3315,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) {
@ -3308,6 +3404,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;
@ -3399,6 +3500,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) {
@ -3494,6 +3600,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) {
@ -3611,6 +3722,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) {
@ -3692,6 +3808,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) {
@ -3782,6 +3903,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) {
@ -3868,6 +3994,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) {
@ -4610,6 +4741,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;
@ -4678,6 +4814,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;
@ -4757,6 +4898,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;
@ -4898,6 +5044,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;
@ -8324,7 +8475,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 */
@ -8380,7 +8531,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;
@ -8463,11 +8614,11 @@ 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
@ -8479,7 +8630,7 @@ int wolfSSH_SFTP_free(WOLFSSH* ssh)
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
@ -366,6 +372,8 @@ extern "C" {
#define WBADFILE NULL #define WBADFILE NULL
#ifdef WOLFSSL_VXWORKS #ifdef WOLFSSL_VXWORKS
#define WUTIMES(f,t) (WS_SUCCESS) #define WUTIMES(f,t) (WS_SUCCESS)
#elif defined(USE_WINDOWS_API)
#include <sys/utime.h>
#else #else
#define WUTIMES(f,t) utimes((f),(t)) #define WUTIMES(f,t) utimes((f),(t))
#endif #endif
@ -451,7 +459,7 @@ extern "C" {
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
#define WSTRNCPY(s1,s2,n) strncpy_s((s1),(n),(s2),(n)) #define WSTRNCPY(s1,s2,n) strncpy_s((s1),(n),(s2),(n))
#define WSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) #define WSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#define WSNPRINTF(s,n,f,...) _snprintf_s((s),(n),(n),(f),##__VA_ARGS__) #define WSNPRINTF(s,n,f,...) _snprintf_s((s),(n),_TRUNCATE,(f),##__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) _vsnprintf_s((s),(n),(n),(f),##__VA_ARGS__) #define WVSNPRINTF(s,n,f,...) _vsnprintf_s((s),(n),(n),(f),##__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_s((s1),(s2),(s3)) #define WSTRTOK(s1,s2,s3) strtok_s((s1),(s2),(s3))
#elif defined(MICROCHIP_MPLAB_HARMONY) || defined(MICROCHIP_PIC32) #elif defined(MICROCHIP_MPLAB_HARMONY) || defined(MICROCHIP_PIC32)
@ -481,7 +489,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)

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,12 @@ typedef enum {
WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*); WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*);
WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH*); WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH*);
WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH*, byte, byte*, word32); WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH*, byte, byte*, word32);
WOLFSSH_API int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32, word32,
word32, word32);
typedef int (*WS_CallbackTerminalSize)(WOLFSSH*, word32, word32, word32,
word32, void*);
void wolfSSH_SetTerminalResizeCb(WOLFSSH*, WS_CallbackTerminalSize);
void wolfSSH_SetTerminalResizeCtx(WOLFSSH*, void*);
enum WS_HighwaterSide { enum WS_HighwaterSide {

View File

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