@@ -351,6 +351,10 @@ bool CAuthentication::CanRetry(IEasySFTPAuthentication* pAuth)
351351
352352 if (!pAuthSession->lpPageantKeyList )
353353 return false ;
354+
355+ if (AssignAgentFlags (pAuthSession))
356+ return true ;
357+
354358 pAuthSession->dwKeyIndex ++;
355359 if (pAuthSession->dwKeyIndex >= pAuthSession->dwKeyCount )
356360 {
@@ -363,6 +367,33 @@ bool CAuthentication::CanRetry(IEasySFTPAuthentication* pAuth)
363367 pAuthSession->lpCurrentKey += dw + 4 ;
364368 dw = ConvertEndian (*reinterpret_cast <DWORD*>(pAuthSession->lpCurrentKey ));
365369 pAuthSession->lpCurrentKey += dw + 4 ;
370+ pAuthSession->nPrevFlags = -1 ;
371+ return AssignAgentFlags (pAuthSession);
372+ }
373+
374+ bool CAuthentication::AssignAgentFlags (CAuthSession* pAuthSession)
375+ {
376+ if (pAuthSession->nPrevFlags == 0 )
377+ return false ;
378+ // get key type data (in the head of blob data)
379+ DWORD dwKeyTypeLen = ConvertEndian (*((DWORD*)(pAuthSession->lpCurrentKey + 4 )));
380+ LPCSTR lpszKeyType = (LPCSTR)(pAuthSession->lpCurrentKey + 8 );
381+
382+ if ((dwKeyTypeLen == 7 && memcmp (lpszKeyType, " ssh-rsa" , dwKeyTypeLen) == 0 ) ||
383+ (dwKeyTypeLen == 28 && memcmp (lpszKeyType, " ssh-rsa-cert-v01@openssh.com" , dwKeyTypeLen) == 0 ))
384+ {
385+ // both rsa-sha2-512 and rsa-sha2-256 are supported, so use rsa-sha2-512
386+ if (pAuthSession->nPrevFlags < 0 )
387+ pAuthSession->nPrevFlags = SSH_AGENT_RSA_SHA2_512;
388+ else if (pAuthSession->nPrevFlags == SSH_AGENT_RSA_SHA2_512)
389+ pAuthSession->nPrevFlags = SSH_AGENT_RSA_SHA2_256;
390+ else
391+ pAuthSession->nPrevFlags = 0 ;
392+ }
393+ else
394+ {
395+ pAuthSession->nPrevFlags = 0 ;
396+ }
366397 return true ;
367398}
368399
@@ -403,47 +434,49 @@ AuthReturnType CAuthentication::SSHAuthenticateWithAgent(IEasySFTPAuthentication
403434 pAuthSession->dwKeyCount = ConvertEndian (*((DWORD*)lpKeyList));
404435 pAuthSession->dwKeyIndex = 0 ;
405436 pAuthSession->lpCurrentKey = lpKeyList + 4 ;
437+ pAuthSession->nPrevFlags = -1 ;
406438 if (FAILED (pAuth->put_AuthSession (reinterpret_cast <__int3264>(pAuthSession))))
407439 {
408440 delete pAuthSession;
409441 return AuthReturnType::Error;
410442 }
443+ AssignAgentFlags (pAuthSession);
411444 }
412445 LPBYTE p = pAuthSession->lpCurrentKey ;
413446
414- LPCSTR lpszKeyType;
415447 LPCBYTE pBlob;
416448 size_t nBlobLen;
417449
418- // get key type data (in the head of blob data)
419- DWORD dwKeyTypeLen = ConvertEndian (*((DWORD*)(p + 4 )));
420- lpszKeyType = (LPCSTR)(p + 8 );
421-
422450 nBlobLen = (size_t )ConvertEndian (*((DWORD*)p));
423451 pBlob = (p + 4 );
424452 p += nBlobLen + 4 ;
425453
426- // get the comment of key
427454 {
455+ DWORD dwKeyTypeLen = ConvertEndian (*((DWORD*)(pBlob)));
456+ LPCSTR lpszKeyType = (LPCSTR)(pBlob + 4 );
457+
458+ // get the comment of key
428459 DWORD dwCommentLen = ConvertEndian (*((DWORD*)p));
429460 CMyStringW str;
430461 str.SetUTF8String ((LPCBYTE)(p + 4 ), static_cast <size_t >(dwCommentLen));
431462 p += dwCommentLen + 4 ;
432- CMyStringW strType (lpszKeyType), strDebug;
463+ CMyStringW strType, strDebug;
464+ strType.SetString (lpszKeyType, dwKeyTypeLen);
433465 strDebug.Format (L" trying key '%s' (type: %s)" , str.operator LPCWSTR (), strType.operator LPCWSTR ());
434466 theApp.Log (EasySFTPLogLevel::Debug, strDebug, S_OK);
435467 }
436468
437469 void * abstract = pAuthSession;
438470 auto ret = libssh2_userauth_publickey (pSession, lpszUser, pBlob, nBlobLen,
439- [](LIBSSH2_SESSION*, LPBYTE* sig, size_t * sig_len, LPCBYTE data, size_t data_len, void ** abstract) -> int
471+ [](LIBSSH2_SESSION* session , LPBYTE* sig, size_t * sig_len, LPCBYTE data, size_t data_len, void ** abstract) -> int
440472 {
441473 *sig = NULL ;
442474 *sig_len = 0 ;
443475 CAuthSession* pAuthSession = static_cast <CAuthSession*>(*abstract);
444476 LPBYTE lpCurrentKey = pAuthSession->lpCurrentKey ;
477+
445478 size_t nSignedLen;
446- auto buff = pAuthSession->pAgent ->SignSSH2Key (lpCurrentKey, data, data_len, &nSignedLen);
479+ auto buff = pAuthSession->pAgent ->SignSSH2Key (lpCurrentKey, pAuthSession-> nPrevFlags , data, data_len, &nSignedLen);
447480 LPBYTE pSignedData = static_cast <LPBYTE>(buff);
448481 if (nSignedLen < 4 || !buff)
449482 {
@@ -505,7 +538,12 @@ AuthReturnType CAuthentication::SSHAuthenticateWithAgent(IEasySFTPAuthentication
505538 return AuthReturnType::Again;
506539
507540 if (ret != 0 )
541+ {
542+ // trying any flags only needed when error is 'unverified'
543+ if (ret != LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED)
544+ pAuthSession->nPrevFlags = 0 ;
508545 return AuthReturnType::Error;
546+ }
509547
510548 delete pAuthSession;
511549 pAuth->put_AuthSession (reinterpret_cast <__int3264>(nullptr ));
0 commit comments