Skip to content

Commit c6c757a

Browse files
committed
Add storing credentials to connect quickly
1 parent 2e346f6 commit c6c757a

33 files changed

Lines changed: 3496 additions & 513 deletions

Common/SUString.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ static void __stdcall EmptyBufferX(PVOID pBufferX, size_t nSize, BYTE nSeed)
8888
n = nSize;
8989
while (n--)
9090
*(--pbx) = (char) (BYTE)((DWORD) (rand() * n / RAND_MAX) - nSeed + n);
91+
SecureZeroMemory(pBufferX, nSize);
9192
}
9293

9394
_SecureStringW::_SecureStringW(void)

EasySFTP/EasySFTP.rc

502 Bytes
Binary file not shown.

EasySFTP/Option.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,41 @@
55

66
COptionDialog::COptionDialog()
77
: CMyDialog(IDD_OPTION)
8+
, m_pRoot(nullptr)
89
{
910
}
1011

12+
COptionDialog::~COptionDialog()
13+
{
14+
if (m_pRoot)
15+
m_pRoot->Release();
16+
}
17+
1118
LRESULT COptionDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
1219
{
1320
HANDLE_COMMAND(IDOK, OnOK);
21+
HANDLE_COMMAND(IDC_CLEAR_ALL_CREDENTIALS, OnClearAllCredentials);
1422
HANDLE_COMMAND(IDC_REGISTER, OnRegister);
1523
HANDLE_COMMAND(IDC_REGISTER_SYSTEM, OnRegister);
1624
return CMyDialog::WindowProc(message, wParam, lParam);
1725
}
1826

1927
bool COptionDialog::OnInitDialog(HWND hWndFocus)
2028
{
29+
if (!m_pRoot)
30+
{
31+
if (FAILED(theApp.m_pEasySFTPRoot->QueryInterface(IID_IEasySFTPRoot2, reinterpret_cast<void**>(&m_pRoot))))
32+
m_pRoot = nullptr;
33+
}
34+
bool bAnyCredentials = false;
35+
if (m_pRoot)
36+
{
37+
VARIANT_BOOL b = VARIANT_FALSE;
38+
m_pRoot->HasCredentials(&b);
39+
bAnyCredentials = b != VARIANT_FALSE;
40+
}
41+
EnableDlgItem(m_hWnd, IDC_CLEAR_ALL_CREDENTIALS, bAnyCredentials);
42+
2143
CMyStringW strRegister;
2244
if (!theApp.m_bEmulatingRegistry)
2345
{
@@ -31,6 +53,24 @@ bool COptionDialog::OnInitDialog(HWND hWndFocus)
3153
return false;
3254
}
3355

56+
LRESULT COptionDialog::OnClearAllCredentials(WPARAM wParam, LPARAM lParam)
57+
{
58+
if (!m_pRoot)
59+
return 0;
60+
61+
if (::MyMessageBoxW(m_hWnd, MAKEINTRESOURCEW(IDS_CLEAR_CREDENTIALS_CONFIRM), NULL,
62+
MB_ICONEXCLAMATION | MB_YESNO) != IDYES)
63+
return 0;
64+
m_pRoot->ClearAllCredentials();
65+
::MyMessageBoxW(m_hWnd, MAKEINTRESOURCEW(IDS_CLEAR_CREDENTIALS_COMPLETE), NULL, MB_ICONINFORMATION);
66+
67+
VARIANT_BOOL b = VARIANT_FALSE;
68+
m_pRoot->HasCredentials(&b);
69+
EnableDlgItem(m_hWnd, IDC_CLEAR_ALL_CREDENTIALS, b);
70+
71+
return 0;
72+
}
73+
3474
LRESULT COptionDialog::OnRegister(WPARAM wParam, LPARAM lParam)
3575
{
3676
if (::MyMessageBoxW(m_hWnd, MAKEINTRESOURCEW(IDS_RESTART_APP), NULL,

EasySFTP/Option.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ class COptionDialog : public CMyDialog
55
{
66
public:
77
COptionDialog();
8+
virtual ~COptionDialog();
89

910
protected:
1011
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
1112
virtual bool OnInitDialog(HWND hWndFocus);
13+
LRESULT OnClearAllCredentials(WPARAM wParam, LPARAM lParam);
1214
LRESULT OnRegister(WPARAM wParam, LPARAM lParam);
1315
LRESULT OnOK(WPARAM wParam, LPARAM lParam);
16+
17+
private:
18+
IEasySFTPRoot2* m_pRoot;
1419
};

EasySFTP/resource.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#define IDS_LEFT_TO_RIGHT 127
3232
#define IDR_MAINFRAME 128
3333
#define IDS_RIGHT_TO_LEFT 128
34+
#define IDS_CLEAR_CREDENTIALS_CONFIRM 129
35+
#define IDS_CLEAR_CREDENTIALS_COMPLETE 130
3436
#define IDB_TOOLBAR 134
3537
#define IDD_OPTION 134
3638
#define IDR_POPUP 135
@@ -78,6 +80,7 @@
7880
#define IDC_LEFT_PATH 1060
7981
#define IDC_RIGHT_PATH 1061
8082
#define IDC_DIRECTION_LABEL 1062
83+
#define IDC_CLEAR_ALL_CREDENTIALS 1063
8184
#define IDS_UNKNOWN_HOST 10001
8285
#define IDS_FAILED_TO_CONNECT 10002
8386
#define IDS_DIRCHANGE_FAILED 11001
@@ -151,7 +154,7 @@
151154
#define _APS_NO_MFC 1
152155
#define _APS_NEXT_RESOURCE_VALUE 147
153156
#define _APS_NEXT_COMMAND_VALUE 32874
154-
#define _APS_NEXT_CONTROL_VALUE 1063
157+
#define _APS_NEXT_CONTROL_VALUE 1064
155158
#define _APS_NEXT_SYMED_VALUE 117
156159
#endif
157160
#endif

ShellDLL/Auth.cpp

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ CAuthSession::~CAuthSession()
2727
}
2828

2929
CAuthentication::CAuthentication()
30-
: CDispatchImplT(theApp.GetTypeInfo(IID_IEasySFTPAuthentication))
30+
: CDispatchImplT(theApp.GetTypeInfo(IID_IEasySFTPAuthentication2))
3131
, m_Mode(EasySFTPAuthenticationMode::None)
32-
, m_pSession(NULL)
32+
, m_pPrivateKeyData(nullptr)
33+
, m_nPrivateKeyData(0)
34+
, m_pSession(nullptr)
3335
{
3436
}
3537

3638
CAuthentication::~CAuthentication()
3739
{
40+
if (m_pPrivateKeyData != nullptr)
41+
{
42+
_SecureStringW::SecureEmptyBuffer(m_pPrivateKeyData, m_nPrivateKeyData);
43+
free(m_pPrivateKeyData);
44+
}
3845
if (m_pSession != NULL)
3946
{
4047
auto* p = static_cast<CAuthSession*>(m_pSession);
@@ -49,11 +56,12 @@ STDMETHODIMP CAuthentication::QueryInterface(REFIID riid, void** ppv)
4956
return E_POINTER;
5057
*ppv = NULL;
5158
if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IDispatch) &&
52-
!IsEqualIID(riid, IID_IEasySFTPAuthentication))
59+
!IsEqualIID(riid, IID_IEasySFTPAuthentication) &&
60+
!IsEqualIID(riid, IID_IEasySFTPAuthentication2))
5361
{
5462
return E_NOINTERFACE;
5563
}
56-
*ppv = static_cast<IEasySFTPAuthentication*>(this);
64+
*ppv = static_cast<IEasySFTPAuthentication2*>(this);
5765
AddRef();
5866
return S_OK;
5967
}
@@ -92,17 +100,17 @@ STDMETHODIMP CAuthentication::put_Password(BSTR p)
92100
return S_OK;
93101
}
94102

95-
STDMETHODIMP CAuthentication::get_PublicKeyFileName(BSTR* p)
103+
STDMETHODIMP CAuthentication::get_PrivateKeyFileName(BSTR* p)
96104
{
97105
if (!p)
98106
return E_POINTER;
99-
*p = MyStringToBSTR(m_strPublicKeyFileName);
107+
*p = MyStringToBSTR(m_strPrivateKeyFileName);
100108
return *p ? S_OK : E_OUTOFMEMORY;
101109
}
102110

103-
STDMETHODIMP CAuthentication::put_PublicKeyFileName(BSTR p)
111+
STDMETHODIMP CAuthentication::put_PrivateKeyFileName(BSTR p)
104112
{
105-
MyBSTRToString(p, m_strPublicKeyFileName);
113+
MyBSTRToString(p, m_strPrivateKeyFileName);
106114
return S_OK;
107115
}
108116

@@ -136,7 +144,39 @@ STDMETHODIMP CAuthentication::put_AuthSession(LONG_PTR session)
136144
return S_OK;
137145
}
138146

139-
AuthReturnType CAuthentication::SSHAuthenticate(IEasySFTPAuthentication* pAuth, LIBSSH2_SESSION* pSession, LPCSTR lpszService, char** ppAuthList)
147+
STDMETHODIMP CAuthentication::SetPrivateKeyBinary(const void* buffer, long length)
148+
{
149+
if (length < 0)
150+
return E_INVALIDARG;
151+
if (length != 0 && !buffer)
152+
return E_POINTER;
153+
if (m_pPrivateKeyData != nullptr)
154+
{
155+
_SecureStringW::SecureEmptyBuffer(m_pPrivateKeyData, m_nPrivateKeyData);
156+
free(m_pPrivateKeyData);
157+
m_pPrivateKeyData = nullptr;
158+
}
159+
m_nPrivateKeyData = length;
160+
if (length > 0)
161+
{
162+
m_pPrivateKeyData = malloc(static_cast<size_t>(length));
163+
if (!m_pPrivateKeyData)
164+
return E_OUTOFMEMORY;
165+
memcpy(m_pPrivateKeyData, buffer, static_cast<size_t>(length));
166+
}
167+
return S_OK;
168+
}
169+
170+
STDMETHODIMP CAuthentication::GetPrivateKeyBinary(const void** buffer, long* pLength)
171+
{
172+
if (!buffer || !pLength)
173+
return E_POINTER;
174+
*buffer = m_pPrivateKeyData;
175+
*pLength = m_nPrivateKeyData;
176+
return m_nPrivateKeyData > 0 ? S_OK : S_FALSE;
177+
}
178+
179+
AuthReturnType CAuthentication::SSHAuthenticate(IEasySFTPAuthentication2* pAuth, LIBSSH2_SESSION* pSession, LPCSTR lpszService, char** ppAuthList)
140180
{
141181
EasySFTPAuthenticationMode mode;
142182
if (FAILED(pAuth->get_Type(&mode)))
@@ -213,34 +253,66 @@ AuthReturnType CAuthentication::SSHAuthenticate(IEasySFTPAuthentication* pAuth,
213253
return AuthReturnType::Success;
214254
}
215255
break;
216-
case EasySFTPAuthenticationMode::PublicKey:
256+
case EasySFTPAuthenticationMode::PrivateKey:
217257
{
218-
if (FAILED(pAuth->get_PublicKeyFileName(&bstr)))
219-
return AuthReturnType::Error;
220-
CMyStringW strPublicKeyFileName;
221-
MyBSTRToString(bstr, strPublicKeyFileName);
222-
::SysFreeString(bstr);
223-
auto* lpszPKeyFileName = reinterpret_cast<LPCSTR>(strPublicKeyFileName.AllocUTF8String());
224-
if (FAILED(pAuth->get_Password(&bstr)))
225-
return AuthReturnType::Error;
226-
CMyStringW str;
227-
MyBSTRToString(bstr, str);
228-
_SecureStringW::SecureEmptyBStr(bstr);
229-
::SysFreeString(bstr);
230-
size_t nPasswordLen = 0;
231-
auto* lpszPassword = reinterpret_cast<LPSTR>(str.AllocUTF8StringC(&nPasswordLen));
232-
_SecureStringW::SecureEmptyString(str);
233-
if (!lpszPassword)
258+
const void* pKeyBuffer = nullptr;
259+
long nKeyLength = 0;
260+
auto hr = pAuth->GetPrivateKeyBinary(&pKeyBuffer, &nKeyLength);
261+
if (FAILED(hr))
234262
return AuthReturnType::Error;
263+
if (hr == S_OK && nKeyLength > 0 && pKeyBuffer != nullptr)
264+
{
265+
if (FAILED(pAuth->get_Password(&bstr)))
266+
return AuthReturnType::Error;
267+
CMyStringW str;
268+
MyBSTRToString(bstr, str);
269+
_SecureStringW::SecureEmptyBStr(bstr);
270+
::SysFreeString(bstr);
271+
size_t nPasswordLen = 0;
272+
auto* lpszPassword = reinterpret_cast<LPSTR>(str.AllocUTF8StringC(&nPasswordLen));
273+
_SecureStringW::SecureEmptyString(str);
274+
if (!lpszPassword)
275+
return AuthReturnType::Error;
276+
277+
auto ret = libssh2_userauth_publickey_frommemory(pSession, pUser, static_cast<UINT>(nUserLen), NULL, 0,
278+
static_cast<const char*>(pKeyBuffer), static_cast<size_t>(nKeyLength), lpszPassword);
279+
_SecureStringW::SecureEmptyBuffer(lpszPassword, sizeof(char) * nPasswordLen);
280+
free(lpszPassword);
281+
if (ret == LIBSSH2_ERROR_EAGAIN)
282+
return AuthReturnType::Again;
235283

236-
auto ret = libssh2_userauth_publickey_fromfile_ex(pSession, pUser, static_cast<UINT>(nUserLen), NULL, lpszPKeyFileName, lpszPassword);
237-
_SecureStringW::SecureEmptyBuffer(lpszPassword, sizeof(char) * nPasswordLen);
238-
free(lpszPassword);
239-
if (ret == LIBSSH2_ERROR_EAGAIN)
240-
return AuthReturnType::Again;
284+
if (ret != 0)
285+
return AuthReturnType::Error;
286+
}
287+
else
288+
{
289+
if (FAILED(pAuth->get_PrivateKeyFileName(&bstr)))
290+
return AuthReturnType::Error;
291+
CMyStringW strPrivateKeyFileName;
292+
MyBSTRToString(bstr, strPrivateKeyFileName);
293+
::SysFreeString(bstr);
294+
auto* lpszPKeyFileName = reinterpret_cast<LPCSTR>(strPrivateKeyFileName.AllocUTF8String());
295+
if (FAILED(pAuth->get_Password(&bstr)))
296+
return AuthReturnType::Error;
297+
CMyStringW str;
298+
MyBSTRToString(bstr, str);
299+
_SecureStringW::SecureEmptyBStr(bstr);
300+
::SysFreeString(bstr);
301+
size_t nPasswordLen = 0;
302+
auto* lpszPassword = reinterpret_cast<LPSTR>(str.AllocUTF8StringC(&nPasswordLen));
303+
_SecureStringW::SecureEmptyString(str);
304+
if (!lpszPassword)
305+
return AuthReturnType::Error;
306+
307+
auto ret = libssh2_userauth_publickey_fromfile_ex(pSession, pUser, static_cast<UINT>(nUserLen), NULL, lpszPKeyFileName, lpszPassword);
308+
_SecureStringW::SecureEmptyBuffer(lpszPassword, sizeof(char) * nPasswordLen);
309+
free(lpszPassword);
310+
if (ret == LIBSSH2_ERROR_EAGAIN)
311+
return AuthReturnType::Again;
241312

242-
if (ret != 0)
243-
return AuthReturnType::Error;
313+
if (ret != 0)
314+
return AuthReturnType::Error;
315+
}
244316
return AuthReturnType::Success;
245317
}
246318
break;

ShellDLL/Auth.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct CAuthSession
4141
~CAuthSession();
4242
};
4343

44-
class CAuthentication : public CDispatchImplT<IEasySFTPAuthentication>
44+
class CAuthentication : public CDispatchImplT<IEasySFTPAuthentication2>
4545
{
4646
public:
4747
CAuthentication();
@@ -55,14 +55,17 @@ class CAuthentication : public CDispatchImplT<IEasySFTPAuthentication>
5555
STDMETHOD(put_UserName)(BSTR Name) override;
5656
STDMETHOD(get_Password)(BSTR* pRet) override;
5757
STDMETHOD(put_Password)(BSTR Password) override;
58-
STDMETHOD(get_PublicKeyFileName)(BSTR* pRet) override;
59-
STDMETHOD(put_PublicKeyFileName)(BSTR FileName) override;
58+
STDMETHOD(get_PrivateKeyFileName)(BSTR* pRet) override;
59+
STDMETHOD(put_PrivateKeyFileName)(BSTR FileName) override;
6060
STDMETHOD(get_Type)(EasySFTPAuthenticationMode* pMode) override;
6161
STDMETHOD(put_Type)(EasySFTPAuthenticationMode mode) override;
6262
STDMETHOD(get_AuthSession)(LONG_PTR* pOut) override;
6363
STDMETHOD(put_AuthSession)(LONG_PTR session) override;
6464

65-
static AuthReturnType SSHAuthenticate(IEasySFTPAuthentication* pAuth, LIBSSH2_SESSION* pSession, LPCSTR lpszService, char** ppAuthList = NULL);
65+
STDMETHOD(SetPrivateKeyBinary)(const void* buffer, long length) override;
66+
STDMETHOD(GetPrivateKeyBinary)(const void** buffer, long* pLength) override;
67+
68+
static AuthReturnType SSHAuthenticate(IEasySFTPAuthentication2* pAuth, LIBSSH2_SESSION* pSession, LPCSTR lpszService, char** ppAuthList = NULL);
6669
static bool CanRetry(IEasySFTPAuthentication* pAuth);
6770

6871
private:
@@ -72,6 +75,8 @@ class CAuthentication : public CDispatchImplT<IEasySFTPAuthentication>
7275
EasySFTPAuthenticationMode m_Mode;
7376
CMyStringW m_strUserName;
7477
_SecureStringW m_strPassword;
75-
CMyStringW m_strPublicKeyFileName;
78+
CMyStringW m_strPrivateKeyFileName;
79+
void* m_pPrivateKeyData;
80+
long m_nPrivateKeyData;
7681
void* m_pSession;
7782
};

0 commit comments

Comments
 (0)