Merge branch 'dev' into gui_qml

This commit is contained in:
pokamest 2021-08-19 01:51:02 +03:00
commit febf9cfafb
144 changed files with 1200222 additions and 67592 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,50 +1,53 @@
INCLUDEPATH *= $$PWD/..
HEADERS += $$PWD/botan.h
INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD
SOURCES += $$PWD/botan.cpp
CONFIG += c++17
CONFIG += exceptions
DEPENDPATH += .
DEFINES += BOTAN_DLL=
unix:DEFINES += BOTAN_TARGET_OS_HAS_GETTIMEOFDAY BOTAN_HAS_ALLOC_MMAP \
BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM BOTAN_HAS_ENTROPY_SRC_EGD BOTAN_HAS_ENTROPY_SRC_FTW \
BOTAN_HAS_ENTROPY_SRC_UNIX BOTAN_HAS_MUTEX_PTHREAD BOTAN_HAS_PIPE_UNIXFD_IO
*linux*:DEFINES += BOTAN_TARGET_OS_IS_LINUX BOTAN_TARGET_OS_HAS_CLOCK_GETTIME \
BOTAN_TARGET_OS_HAS_DLOPEN BOTAN_TARGET_OS_HAS_GMTIME_R BOTAN_TARGET_OS_HAS_POSIX_MLOCK \
BOTAN_HAS_DYNAMICALLY_LOADED_ENGINE BOTAN_HAS_DYNAMIC_LOADER
macx:DEFINES += BOTAN_TARGET_OS_IS_DARWIN
*g++*:DEFINES += BOTAN_BUILD_COMPILER_IS_GCC
*clang*:DEFINES += BOTAN_BUILD_COMPILER_IS_CLANG
*icc*:DEFINES += BOTAN_BUILD_COMPILER_IS_INTEL
CONFIG(x86_64):DEFINES += BOTAN_TARGET_ARCH_IS_X86_64
INCLUDEPATH += $$PWD/include/external
win32 {
DEFINES += BOTAN_TARGET_OS_IS_WINDOWS \
BOTAN_TARGET_OS_HAS_LOADLIBRARY BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME \
BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK \
BOTAN_HAS_ENTROPY_SRC_CAPI BOTAN_HAS_ENTROPY_SRC_WIN32 \
BOTAN_HAS_MUTEX_WIN32
QMAKE_CXXFLAGS += -bigobj
LIBS += \
-lcrypt32 \
msvc {
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHs
QMAKE_CXXFLAGS += -wd4251 -wd4290 -wd4250 -wd4297 -wd4267 -wd4334
DEFINES += BOTAN_BUILD_COMPILER_IS_MSVC BOTAN_TARGET_OS_HAS_GMTIME_S _SCL_SECURE_NO_WARNINGS
} else {
QMAKE_CFLAGS += -fpermissive -finline-functions -Wno-long-long
QMAKE_CXXFLAGS += -fpermissive -finline-functions -Wno-long-long
}
LIBS += -ladvapi32 -luser32
!contains(QMAKE_TARGET.arch, x86_64) {
message("Windows x86 build")
INCLUDEPATH += $$PWD/windows/x86_64
HEADERS += $$PWD/windows/x86/botan_all.h
SOURCES += $$PWD/windows/x86/botan_all.cpp
}
else {
message("Windows x86_64 build")
INCLUDEPATH += $$PWD/windows/x86_64
HEADERS += $$PWD/windows/x86_64/botan_all.h
SOURCES += $$PWD/windows/x86_64/botan_all.cpp
}
}
unix:*-g++* {
QMAKE_CFLAGS += -fPIC -fpermissive -finline-functions -Wno-long-long
QMAKE_CXXFLAGS += -fPIC -fpermissive -finline-functions -Wno-long-long
macx {
message("macOS build")
INCLUDEPATH += $$PWD/macos
HEADERS += $$PWD/macos/botan_all.h
SOURCES += $$PWD/macos/botan_all.cpp
}
linux*|freebsd* {
LIBS += -lrt $$QMAKE_LIBS_DYNLOAD
linux-g++ {
message("Linux build")
INCLUDEPATH += $$PWD/linux
HEADERS += $$PWD/linux/botan_all.h
SOURCES += $$PWD/linux/botan_all.cpp
LIBS += -ldl
}
android {
for (abi, ANDROID_ABIS): {
equals(ANDROID_TARGET_ARCH,$$abi) {
message("Android build for ANDROID_TARGET_ARCH" $$abi)
INCLUDEPATH += $$PWD/android/$${abi}
HEADERS += $$PWD/android/$${abi}/botan_all.h
SOURCES += $$PWD/android/$${abi}/botan_all.cpp
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,49 +0,0 @@
.. _license:
.. highlight:: none
License
========================================
Botan (http://botan.randombit.net/) is distributed under these terms::
Copyright (C) 1999-2011 Jack Lloyd
2001 Peter J Jones
2004-2007 Justin Karneges
2004 Vaclav Ovsik
2005 Matthew Gregan
2005-2006 Matt Johnston
2006 Luca Piccarreta
2007 Yves Jerschow
2007-2008 FlexSecure GmbH
2007-2008 Technische Universitat Darmstadt
2007-2008 Falko Strenzke
2007-2008 Martin Doering
2007 Manuel Hartl
2007 Christoph Ludwig
2007 Patrick Sona
2010 Olivier de Gaalon
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,264 @@
/*
* PKCS #11 Cryptographic Token Interface Base Specification Version 2.40 Errata 01
* Committee Specification Draft 01 / Public Review Draft 01
* 09 December 2015
* Copyright (c) OASIS Open 2015. All Rights Reserved.
* Source: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/csprd01/include/pkcs11-v2.40/
* Latest version of the specification: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
* https://www.oasis-open.org/policies-guidelines/ipr
*/
#ifndef _PKCS11_H_
#define _PKCS11_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* Before including this file (pkcs11.h) (or pkcs11t.h by
* itself), 5 platform-specific macros must be defined. These
* macros are described below, and typical definitions for them
* are also given. Be advised that these definitions can depend
* on both the platform and the compiler used (and possibly also
* on whether a Cryptoki library is linked statically or
* dynamically).
*
* In addition to defining these 5 macros, the packing convention
* for Cryptoki structures should be set. The Cryptoki
* convention on packing is that structures should be 1-byte
* aligned.
*
* If you're using Microsoft Developer Studio 5.0 to produce
* Win32 stuff, this might be done by using the following
* preprocessor directive before including pkcs11.h or pkcs11t.h:
*
* #pragma pack(push, cryptoki, 1)
*
* and using the following preprocessor directive after including
* pkcs11.h or pkcs11t.h:
*
* #pragma pack(pop, cryptoki)
*
* If you're using an earlier version of Microsoft Developer
* Studio to produce Win16 stuff, this might be done by using
* the following preprocessor directive before including
* pkcs11.h or pkcs11t.h:
*
* #pragma pack(1)
*
* In a UNIX environment, you're on your own for this. You might
* not need to do (or be able to do!) anything.
*
*
* Now for the macros:
*
*
* 1. CK_PTR: The indirection string for making a pointer to an
* object. It can be used like this:
*
* typedef CK_BYTE CK_PTR CK_BYTE_PTR;
*
* If you're using Microsoft Developer Studio 5.0 to produce
* Win32 stuff, it might be defined by:
*
* #define CK_PTR *
*
* If you're using an earlier version of Microsoft Developer
* Studio to produce Win16 stuff, it might be defined by:
*
* #define CK_PTR far *
*
* In a typical UNIX environment, it might be defined by:
*
* #define CK_PTR *
*
*
* 2. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
* an importable Cryptoki library function declaration out of a
* return type and a function name. It should be used in the
* following fashion:
*
* extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
* CK_VOID_PTR pReserved
* );
*
* If you're using Microsoft Developer Studio 5.0 to declare a
* function in a Win32 Cryptoki .dll, it might be defined by:
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType __declspec(dllimport) name
*
* If you're using an earlier version of Microsoft Developer
* Studio to declare a function in a Win16 Cryptoki .dll, it
* might be defined by:
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType __export _far _pascal name
*
* In a UNIX environment, it might be defined by:
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType name
*
*
* 3. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
* which makes a Cryptoki API function pointer declaration or
* function pointer type declaration out of a return type and a
* function name. It should be used in the following fashion:
*
* // Define funcPtr to be a pointer to a Cryptoki API function
* // taking arguments args and returning CK_RV.
* CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
*
* or
*
* // Define funcPtrType to be the type of a pointer to a
* // Cryptoki API function taking arguments args and returning
* // CK_RV, and then define funcPtr to be a variable of type
* // funcPtrType.
* typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
* funcPtrType funcPtr;
*
* If you're using Microsoft Developer Studio 5.0 to access
* functions in a Win32 Cryptoki .dll, in might be defined by:
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType __declspec(dllimport) (* name)
*
* If you're using an earlier version of Microsoft Developer
* Studio to access functions in a Win16 Cryptoki .dll, it might
* be defined by:
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType __export _far _pascal (* name)
*
* In a UNIX environment, it might be defined by:
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType (* name)
*
*
* 4. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
* a function pointer type for an application callback out of
* a return type for the callback and a name for the callback.
* It should be used in the following fashion:
*
* CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
*
* to declare a function pointer, myCallback, to a callback
* which takes arguments args and returns a CK_RV. It can also
* be used like this:
*
* typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
* myCallbackType myCallback;
*
* If you're using Microsoft Developer Studio 5.0 to do Win32
* Cryptoki development, it might be defined by:
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
* If you're using an earlier version of Microsoft Developer
* Studio to do Win16 development, it might be defined by:
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType _far _pascal (* name)
*
* In a UNIX environment, it might be defined by:
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
*
* 5. NULL_PTR: This macro is the value of a NULL pointer.
*
* In any ANSI/ISO C environment (and in many others as well),
* this should best be defined by
*
* #ifndef NULL_PTR
* #define NULL_PTR 0
* #endif
*/
/* All the various Cryptoki types and #define'd values are in the
* file pkcs11t.h.
*/
#include "pkcs11t.h"
#define __PASTE(x,y) x##y
/* ==============================================================
* Define the "extern" form of all the entry points.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
extern CK_DECLARE_FUNCTION(CK_RV, name)
/* pkcs11f.h has all the information about the Cryptoki
* function prototypes.
*/
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define the typedef form of all the entry points. That is, for
* each Cryptoki function C_XXX, define a type CK_C_XXX which is
* a pointer to that kind of function.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
/* pkcs11f.h has all the information about the Cryptoki
* function prototypes.
*/
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define structed vector of entry points. A CK_FUNCTION_LIST
* contains a CK_VERSION indicating a library's Cryptoki version
* and then a whole slew of function pointers to the routines in
* the library. This type was declared, but not defined, in
* pkcs11t.h.
* ==============================================================
*/
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(CK_,name) name;
struct CK_FUNCTION_LIST {
CK_VERSION version; /* Cryptoki version */
/* Pile all the function pointers into the CK_FUNCTION_LIST. */
/* pkcs11f.h has all the information about the Cryptoki
* function prototypes.
*/
#include "pkcs11f.h"
};
#undef CK_PKCS11_FUNCTION_INFO
#undef __PASTE
#ifdef __cplusplus
}
#endif
#endif /* _PKCS11_H_ */

View file

@ -0,0 +1,938 @@
/*
* PKCS #11 Cryptographic Token Interface Base Specification Version 2.40 Errata 01
* Committee Specification Draft 01 / Public Review Draft 01
* 09 December 2015
* Copyright (c) OASIS Open 2015. All Rights Reserved.
* Source: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/csprd01/include/pkcs11-v2.40/
* Latest version of the specification: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
* https://www.oasis-open.org/policies-guidelines/ipr
*/
/* This header file contains pretty much everything about all the
* Cryptoki function prototypes. Because this information is
* used for more than just declaring function prototypes, the
* order of the functions appearing herein is important, and
* should not be altered.
*/
/* General-purpose */
/* C_Initialize initializes the Cryptoki library. */
CK_PKCS11_FUNCTION_INFO(C_Initialize)
#ifdef CK_NEED_ARG_LIST
(
CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
* cast to CK_C_INITIALIZE_ARGS_PTR
* and dereferenced
*/
);
#endif
/* C_Finalize indicates that an application is done with the
* Cryptoki library.
*/
CK_PKCS11_FUNCTION_INFO(C_Finalize)
#ifdef CK_NEED_ARG_LIST
(
CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
);
#endif
/* C_GetInfo returns general information about Cryptoki. */
CK_PKCS11_FUNCTION_INFO(C_GetInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_INFO_PTR pInfo /* location that receives information */
);
#endif
/* C_GetFunctionList returns the function list. */
CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
#ifdef CK_NEED_ARG_LIST
(
CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
* function list
*/
);
#endif
/* Slot and token management */
/* C_GetSlotList obtains a list of slots in the system. */
CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
#ifdef CK_NEED_ARG_LIST
(
CK_BBOOL tokenPresent, /* only slots with tokens */
CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
CK_ULONG_PTR pulCount /* receives number of slots */
);
#endif
/* C_GetSlotInfo obtains information about a particular slot in
* the system.
*/
CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* the ID of the slot */
CK_SLOT_INFO_PTR pInfo /* receives the slot information */
);
#endif
/* C_GetTokenInfo obtains information about a particular token
* in the system.
*/
CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_TOKEN_INFO_PTR pInfo /* receives the token information */
);
#endif
/* C_GetMechanismList obtains a list of mechanism types
* supported by a token.
*/
CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of token's slot */
CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
CK_ULONG_PTR pulCount /* gets # of mechs. */
);
#endif
/* C_GetMechanismInfo obtains information about a particular
* mechanism possibly supported by a token.
*/
CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_MECHANISM_TYPE type, /* type of mechanism */
CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
);
#endif
/* C_InitToken initializes a token. */
CK_PKCS11_FUNCTION_INFO(C_InitToken)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
CK_ULONG ulPinLen, /* length in bytes of the PIN */
CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
);
#endif
/* C_InitPIN initializes the normal user's PIN. */
CK_PKCS11_FUNCTION_INFO(C_InitPIN)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
CK_ULONG ulPinLen /* length in bytes of the PIN */
);
#endif
/* C_SetPIN modifies the PIN of the user who is logged in. */
CK_PKCS11_FUNCTION_INFO(C_SetPIN)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
CK_ULONG ulOldLen, /* length of the old PIN */
CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
CK_ULONG ulNewLen /* length of the new PIN */
);
#endif
/* Session management */
/* C_OpenSession opens a session between an application and a
* token.
*/
CK_PKCS11_FUNCTION_INFO(C_OpenSession)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* the slot's ID */
CK_FLAGS flags, /* from CK_SESSION_INFO */
CK_VOID_PTR pApplication, /* passed to callback */
CK_NOTIFY Notify, /* callback function */
CK_SESSION_HANDLE_PTR phSession /* gets session handle */
);
#endif
/* C_CloseSession closes a session between an application and a
* token.
*/
CK_PKCS11_FUNCTION_INFO(C_CloseSession)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* C_CloseAllSessions closes all sessions with a token. */
CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID /* the token's slot */
);
#endif
/* C_GetSessionInfo obtains information about the session. */
CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_SESSION_INFO_PTR pInfo /* receives session info */
);
#endif
/* C_GetOperationState obtains the state of the cryptographic operation
* in a session.
*/
CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pOperationState, /* gets state */
CK_ULONG_PTR pulOperationStateLen /* gets state length */
);
#endif
/* C_SetOperationState restores the state of the cryptographic
* operation in a session.
*/
CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pOperationState, /* holds state */
CK_ULONG ulOperationStateLen, /* holds state length */
CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
);
#endif
/* C_Login logs a user into a token. */
CK_PKCS11_FUNCTION_INFO(C_Login)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_USER_TYPE userType, /* the user type */
CK_UTF8CHAR_PTR pPin, /* the user's PIN */
CK_ULONG ulPinLen /* the length of the PIN */
);
#endif
/* C_Logout logs a user out from a token. */
CK_PKCS11_FUNCTION_INFO(C_Logout)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* Object management */
/* C_CreateObject creates a new object. */
CK_PKCS11_FUNCTION_INFO(C_CreateObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
CK_ULONG ulCount, /* attributes in template */
CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
);
#endif
/* C_CopyObject copies an object, creating a new object for the
* copy.
*/
CK_PKCS11_FUNCTION_INFO(C_CopyObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
CK_ULONG ulCount, /* attributes in template */
CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
);
#endif
/* C_DestroyObject destroys an object. */
CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject /* the object's handle */
);
#endif
/* C_GetObjectSize gets the size of an object in bytes. */
CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ULONG_PTR pulSize /* receives size of object */
);
#endif
/* C_GetAttributeValue obtains the value of one or more object
* attributes.
*/
CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
CK_ULONG ulCount /* attributes in template */
);
#endif
/* C_SetAttributeValue modifies the value of one or more object
* attributes.
*/
CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
CK_ULONG ulCount /* attributes in template */
);
#endif
/* C_FindObjectsInit initializes a search for token and session
* objects that match a template.
*/
CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
CK_ULONG ulCount /* attrs in search template */
);
#endif
/* C_FindObjects continues a search for token and session
* objects that match a template, obtaining additional object
* handles.
*/
CK_PKCS11_FUNCTION_INFO(C_FindObjects)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
CK_ULONG ulMaxObjectCount, /* max handles to get */
CK_ULONG_PTR pulObjectCount /* actual # returned */
);
#endif
/* C_FindObjectsFinal finishes a search for token and session
* objects.
*/
CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* Encryption and decryption */
/* C_EncryptInit initializes an encryption operation. */
CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
CK_OBJECT_HANDLE hKey /* handle of encryption key */
);
#endif
/* C_Encrypt encrypts single-part data. */
CK_PKCS11_FUNCTION_INFO(C_Encrypt)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pData, /* the plaintext data */
CK_ULONG ulDataLen, /* bytes of plaintext */
CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
);
#endif
/* C_EncryptUpdate continues a multiple-part encryption
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext data len */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
);
#endif
/* C_EncryptFinal finishes a multiple-part encryption
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session handle */
CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
);
#endif
/* C_DecryptInit initializes a decryption operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
CK_OBJECT_HANDLE hKey /* handle of decryption key */
);
#endif
/* C_Decrypt decrypts encrypted data in a single part. */
CK_PKCS11_FUNCTION_INFO(C_Decrypt)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedData, /* ciphertext */
CK_ULONG ulEncryptedDataLen, /* ciphertext length */
CK_BYTE_PTR pData, /* gets plaintext */
CK_ULONG_PTR pulDataLen /* gets p-text size */
);
#endif
/* C_DecryptUpdate continues a multiple-part decryption
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* encrypted data */
CK_ULONG ulEncryptedPartLen, /* input length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* p-text size */
);
#endif
/* C_DecryptFinal finishes a multiple-part decryption
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pLastPart, /* gets plaintext */
CK_ULONG_PTR pulLastPartLen /* p-text size */
);
#endif
/* Message digesting */
/* C_DigestInit initializes a message-digesting operation. */
CK_PKCS11_FUNCTION_INFO(C_DigestInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
);
#endif
/* C_Digest digests data in a single part. */
CK_PKCS11_FUNCTION_INFO(C_Digest)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* data to be digested */
CK_ULONG ulDataLen, /* bytes of data to digest */
CK_BYTE_PTR pDigest, /* gets the message digest */
CK_ULONG_PTR pulDigestLen /* gets digest length */
);
#endif
/* C_DigestUpdate continues a multiple-part message-digesting
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* data to be digested */
CK_ULONG ulPartLen /* bytes of data to be digested */
);
#endif
/* C_DigestKey continues a multi-part message-digesting
* operation, by digesting the value of a secret key as part of
* the data already digested.
*/
CK_PKCS11_FUNCTION_INFO(C_DigestKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hKey /* secret key to digest */
);
#endif
/* C_DigestFinal finishes a multiple-part message-digesting
* operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pDigest, /* gets the message digest */
CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
);
#endif
/* Signing and MACing */
/* C_SignInit initializes a signature (private key encryption)
* operation, where the signature is (will be) an appendix to
* the data, and plaintext cannot be recovered from the
* signature.
*/
CK_PKCS11_FUNCTION_INFO(C_SignInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
CK_OBJECT_HANDLE hKey /* handle of signature key */
);
#endif
/* C_Sign signs (encrypts with private key) data in a single
* part, where the signature is (will be) an appendix to the
* data, and plaintext cannot be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_Sign)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* the data to sign */
CK_ULONG ulDataLen, /* count of bytes to sign */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* C_SignUpdate continues a multiple-part signature operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* the data to sign */
CK_ULONG ulPartLen /* count of bytes to sign */
);
#endif
/* C_SignFinal finishes a multiple-part signature operation,
* returning the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_SignFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* C_SignRecoverInit initializes a signature operation, where
* the data can be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
CK_OBJECT_HANDLE hKey /* handle of the signature key */
);
#endif
/* C_SignRecover signs data in a single operation, where the
* data can be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_SignRecover)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* the data to sign */
CK_ULONG ulDataLen, /* count of bytes to sign */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* Verifying signatures and MACs */
/* C_VerifyInit initializes a verification operation, where the
* signature is an appendix to the data, and plaintext cannot
* cannot be recovered from the signature (e.g. DSA).
*/
CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
CK_OBJECT_HANDLE hKey /* verification key */
);
#endif
/* C_Verify verifies a signature in a single-part operation,
* where the signature is an appendix to the data, and plaintext
* cannot be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_Verify)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* signed data */
CK_ULONG ulDataLen, /* length of signed data */
CK_BYTE_PTR pSignature, /* signature */
CK_ULONG ulSignatureLen /* signature length*/
);
#endif
/* C_VerifyUpdate continues a multiple-part verification
* operation, where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* signed data */
CK_ULONG ulPartLen /* length of signed data */
);
#endif
/* C_VerifyFinal finishes a multiple-part verification
* operation, checking the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* signature to verify */
CK_ULONG ulSignatureLen /* signature length */
);
#endif
/* C_VerifyRecoverInit initializes a signature verification
* operation, where the data is recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
CK_OBJECT_HANDLE hKey /* verification key */
);
#endif
/* C_VerifyRecover verifies a signature in a single-part
* operation, where the data is recovered from the signature.
*/
CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* signature to verify */
CK_ULONG ulSignatureLen, /* signature length */
CK_BYTE_PTR pData, /* gets signed data */
CK_ULONG_PTR pulDataLen /* gets signed data len */
);
#endif
/* Dual-function cryptographic operations */
/* C_DigestEncryptUpdate continues a multiple-part digesting
* and encryption operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext length */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
);
#endif
/* C_DecryptDigestUpdate continues a multiple-part decryption and
* digesting operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* gets plaintext len */
);
#endif
/* C_SignEncryptUpdate continues a multiple-part signing and
* encryption operation.
*/
CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext length */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
);
#endif
/* C_DecryptVerifyUpdate continues a multiple-part decryption and
* verify operation.
*/
CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* gets p-text length */
);
#endif
/* Key management */
/* C_GenerateKey generates a secret key, creating a new key
* object.
*/
CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* key generation mech. */
CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
CK_ULONG ulCount, /* # of attrs in template */
CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
);
#endif
/* C_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects.
*/
CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session handle */
CK_MECHANISM_PTR pMechanism, /* key-gen mech. */
CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template for pub. key */
CK_ULONG ulPublicKeyAttributeCount, /* # pub. attrs. */
CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template for priv. key */
CK_ULONG ulPrivateKeyAttributeCount, /* # priv. attrs. */
CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. key handle */
CK_OBJECT_HANDLE_PTR phPrivateKey /* gets priv. key handle */
);
#endif
/* C_WrapKey wraps (i.e., encrypts) a key. */
CK_PKCS11_FUNCTION_INFO(C_WrapKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
CK_OBJECT_HANDLE hKey, /* key to be wrapped */
CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
);
#endif
/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
* key object.
*/
CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
CK_ULONG ulWrappedKeyLen, /* wrapped key len */
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
CK_ULONG ulAttributeCount, /* template length */
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
);
#endif
/* C_DeriveKey derives a key from a base key, creating a new key
* object.
*/
CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
CK_OBJECT_HANDLE hBaseKey, /* base key */
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
CK_ULONG ulAttributeCount, /* template length */
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
);
#endif
/* Random number generation */
/* C_SeedRandom mixes additional seed material into the token's
* random number generator.
*/
CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSeed, /* the seed material */
CK_ULONG ulSeedLen /* length of seed material */
);
#endif
/* C_GenerateRandom generates random data. */
CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR RandomData, /* receives the random data */
CK_ULONG ulRandomLen /* # of bytes to generate */
);
#endif
/* Parallel function management */
/* C_GetFunctionStatus is a legacy function; it obtains an
* updated status of a function running in parallel with an
* application.
*/
CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* C_CancelFunction is a legacy function; it cancels a function
* running in parallel.
*/
CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* C_WaitForSlotEvent waits for a slot event (token insertion,
* removal, etc.) to occur.
*/
CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
#ifdef CK_NEED_ARG_LIST
(
CK_FLAGS flags, /* blocking/nonblocking flag */
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
);
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
Botan 1.10.2, 2012-06-17
http://botan.randombit.net/
Botan is a C++ class library for performing a wide variety of
cryptographic operations. It is released under the 2 clause BSD
license; see doc/license.txt for the specifics. You can file bugs in
Bugzilla (http://bugs.randombit.net/) or by sending a report to the
botan-devel mailing list. More information about the mailing list is
at http://lists.randombit.net/mailman/listinfo/botan-devel/
You can find documentation online at http://botan.randombit.net/ as
well as in the doc directory in the distribution. Several examples can
be found in doc/examples as well.
Jack Lloyd (lloyd@randombit.net)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
TEMPLATE = subdirs
SUBDIRS = ssh

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

View file

@ -0,0 +1,200 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "opensshkeyfilereader_p.h"
#include "sshcapabilities_p.h"
#include "ssherrors.h"
#include "sshexception_p.h"
#include "sshlogging_p.h"
#include "sshpacketparser_p.h"
#include "ssh_global.h"
#include <botan_all.h>
#include <memory>
namespace QSsh {
namespace Internal {
using namespace Botan;
bool OpenSshKeyFileReader::parseKey(const QByteArray &privKeyFileContents)
{
static const QByteArray magicPrefix = "-----BEGIN OPENSSH PRIVATE KEY-----\n";
static const QByteArray magicSuffix = "-----END OPENSSH PRIVATE KEY-----\n";
if (!privKeyFileContents.startsWith(magicPrefix)) {
qCDebug(sshLog) << "not an OpenSSH key file: prefix does not match";
return false;
}
if (!privKeyFileContents.endsWith(magicSuffix))
throwException(SSH_TR("Unexpected end-of-file marker."));
const QByteArray payload = QByteArray::fromBase64
(privKeyFileContents.mid(magicPrefix.size(), privKeyFileContents.size()
- magicPrefix.size() - magicSuffix.size()));
doParse(payload);
return true;
}
std::unique_ptr<Private_Key> OpenSshKeyFileReader::privateKey() const
{
if (m_keyType == SshCapabilities::PubKeyRsa) {
QSSH_ASSERT_AND_RETURN_VALUE(m_parameters.size() == 5, nullptr);
const BigInt &e = m_parameters.at(0);
const BigInt &n = m_parameters.at(1);
const BigInt &p = m_parameters.at(2);
const BigInt &q = m_parameters.at(3);
const BigInt &d = m_parameters.at(4);
return std::make_unique<RSA_PrivateKey>(p, q, e, d, n);
} else if (m_keyType == SshCapabilities::PubKeyDss) {
QSSH_ASSERT_AND_RETURN_VALUE(m_parameters.size() == 5, nullptr);
const BigInt &p = m_parameters.at(0);
const BigInt &q = m_parameters.at(1);
const BigInt &g = m_parameters.at(2);
const BigInt &x = m_parameters.at(4);
return std::make_unique<DSA_PrivateKey>(m_rng, DL_Group(p, q, g), x);
} else if (m_keyType.startsWith(SshCapabilities::PubKeyEcdsaPrefix)) {
QSSH_ASSERT_AND_RETURN_VALUE(m_parameters.size() == 1, nullptr);
const BigInt &value = m_parameters.first();
const EC_Group group(SshCapabilities::oid(m_keyType));
return std::make_unique<ECDSA_PrivateKey>(m_rng, group, value);
}
QSSH_ASSERT_AND_RETURN_VALUE(false, nullptr);
}
QList<BigInt> OpenSshKeyFileReader::publicParameters() const
{
if (m_keyType == SshCapabilities::PubKeyRsa)
return m_parameters.mid(0, 2);
if (m_keyType == SshCapabilities::PubKeyDss)
return m_parameters.mid(0, 4);
if (m_keyType.startsWith(SshCapabilities::PubKeyEcdsaPrefix))
return QList<BigInt>();
QSSH_ASSERT_AND_RETURN_VALUE(false, QList<BigInt>());
}
void OpenSshKeyFileReader::doParse(const QByteArray &payload)
{
// See PROTOCOL.key in OpenSSH sources.
static const QByteArray magicString = "openssh-key-v1";
if (!payload.startsWith(magicString))
throwException(SSH_TR("Unexpected magic string."));
try {
quint32 offset = magicString.size() + 1; // null byte
m_cipherName = SshPacketParser::asString(payload, &offset);
qCDebug(sshLog) << "cipher:" << m_cipherName;
m_kdf = SshPacketParser::asString(payload, &offset);
qCDebug(sshLog) << "kdf:" << m_kdf;
parseKdfOptions(SshPacketParser::asString(payload, &offset));
const quint32 keyCount = SshPacketParser::asUint32(payload, &offset);
if (keyCount != 1) {
qCWarning(sshLog) << "more than one key found in OpenSSH private key file, ignoring "
"all but the first one";
}
for (quint32 i = 0; i < keyCount; ++i) // Skip the public key blob(s).
SshPacketParser::asString(payload, &offset);
m_privateKeyList = SshPacketParser::asString(payload, &offset);
decryptPrivateKeyList();
parsePrivateKeyList();
} catch (const SshPacketParseException &) {
throwException(SSH_TR("Parse error."));
} catch (const Exception &e) {
throwException(QLatin1String(e.what()));
}
}
void OpenSshKeyFileReader::parseKdfOptions(const QByteArray &kdfOptions)
{
if (m_cipherName == "none")
return;
quint32 offset = 0;
m_salt = SshPacketParser::asString(kdfOptions, &offset);
if (m_salt.size() != 16)
throwException(SSH_TR("Invalid salt size %1.").arg(m_salt.size()));
m_rounds = SshPacketParser::asUint32(kdfOptions, &offset);
qCDebug(sshLog) << "salt:" << m_salt.toHex();
qCDebug(sshLog) << "rounds:" << m_rounds;
}
void OpenSshKeyFileReader::decryptPrivateKeyList()
{
if (m_cipherName == "none")
return;
if (m_kdf != "bcrypt") {
throwException(SSH_TR("Unexpected key derivation function '%1'.")
.arg(QLatin1String(m_kdf)));
}
// OpenSSH uses a proprietary algorithm for the key derivation. We'd basically have to
// copy the code.
// TODO: If the lower-level operations (hashing primitives, blowfish stuff) can be taken
// over by Botan, that might be feasible. Investigate.
throwException(SSH_TR("Encrypted keys are currently not supported in this format."));
}
void OpenSshKeyFileReader::parsePrivateKeyList()
{
quint32 offset = 0;
const quint32 checkInt1 = SshPacketParser::asUint32(m_privateKeyList, &offset);
const quint32 checkInt2 = SshPacketParser::asUint32(m_privateKeyList, &offset);
if (checkInt1 != checkInt2)
throwException(SSH_TR("Verification failed."));
m_keyType = SshPacketParser::asString(m_privateKeyList, &offset);
qCDebug(sshLog) << "key type:" << m_keyType;
if (m_keyType == SshCapabilities::PubKeyRsa) {
const BigInt n = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt e = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt d = SshPacketParser::asBigInt(m_privateKeyList, &offset);
SshPacketParser::asBigInt(m_privateKeyList, &offset); // iqmp
const BigInt p = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt q = SshPacketParser::asBigInt(m_privateKeyList, &offset);
m_parameters = QList<BigInt>{e, n, p, q, d};
} else if (m_keyType == SshCapabilities::PubKeyDss) {
const BigInt p = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt q = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt g = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt y = SshPacketParser::asBigInt(m_privateKeyList, &offset);
const BigInt x = SshPacketParser::asBigInt(m_privateKeyList, &offset);
m_parameters = QList<BigInt>{p, q, g, y, x};
} else if (m_keyType.startsWith(SshCapabilities::PubKeyEcdsaPrefix)) {
SshPacketParser::asString(m_privateKeyList, &offset); // name
SshPacketParser::asString(m_privateKeyList, &offset); // pubkey representation
m_parameters = {SshPacketParser::asBigInt(m_privateKeyList, &offset)};
} else {
throwException(SSH_TR("Private key type '%1' is not supported.")
.arg(QString::fromLatin1(m_keyType)));
}
const QByteArray comment = SshPacketParser::asString(m_privateKeyList, &offset);
qCDebug(sshLog) << "comment:" << comment;
}
void OpenSshKeyFileReader::throwException(const QString &reason)
{
throw SshClientException(SshKeyFileError,
SSH_TR("Processing OpenSSH private key file failed: %1").arg(reason));
}
} // namespace Internal
} // namespace QSsh

View file

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@ -23,27 +23,51 @@
**
****************************************************************************/
#include "sshinit_p.h"
#pragma once
#include <botan/botan.h>
#include <QByteArray>
#include <QList>
#include <QMutex>
#include <QMutexLocker>
#include <botan_all.h>
#include <memory>
namespace Botan {
class Private_Key;
class RandomNumberGenerator;
}
namespace QSsh {
namespace Internal {
static bool initialized = false;
static QMutex initMutex;
void initSsh()
class OpenSshKeyFileReader
{
QMutexLocker locker(&initMutex);
if (!initialized) {
Botan::LibraryInitializer::initialize("thread_safe=true");
initialized = true;
}
}
public:
OpenSshKeyFileReader(Botan::RandomNumberGenerator &rng) : m_rng(rng) {}
bool parseKey(const QByteArray &privKeyFileContents);
QByteArray keyType() const { return m_keyType; }
std::unique_ptr<Botan::Private_Key> privateKey() const;
QList<Botan::BigInt> allParameters() const { return m_parameters; }
QList<Botan::BigInt> publicParameters() const;
private:
void doParse(const QByteArray &payload);
void parseKdfOptions(const QByteArray &kdfOptions);
void decryptPrivateKeyList();
void parsePrivateKeyList();
[[noreturn]] void throwException(const QString &reason);
Botan::RandomNumberGenerator &m_rng;
QByteArray m_keyType;
QList<Botan::BigInt> m_parameters;
QByteArray m_cipherName;
QByteArray m_kdf;
QByteArray m_salt;
quint32 m_rounds;
QByteArray m_privateKeyList;
};
} // namespace Internal
} // namespace QSsh

View file

@ -3,7 +3,13 @@ QT += gui network widgets
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
SOURCES += $$PWD/sshsendfacility.cpp \
#!win32-msvc* {
# QMAKE_CXXFLAGS += -Wextra -pedantic
#}
#contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
SOURCES = $$PWD/sshsendfacility.cpp \
$$PWD/sshremoteprocess.cpp \
$$PWD/sshpacketparser.cpp \
$$PWD/sshpacket.cpp \
@ -26,28 +32,44 @@ SOURCES += $$PWD/sshsendfacility.cpp \
$$PWD/sshconnectionmanager.cpp \
$$PWD/sshkeypasswordretriever.cpp \
$$PWD/sftpfilesystemmodel.cpp \
$$PWD/sshkeycreationdialog.cpp \
$$PWD/sshinit.cpp \
$$PWD/sshdirecttcpiptunnel.cpp \
$$PWD/sshlogging.cpp \
$$PWD/sshhostkeydatabase.cpp \
$$PWD/sshlogging.cpp \
$$PWD/sshtcpipforwardserver.cpp \
$$PWD/sshtcpiptunnel.cpp \
$$PWD/sshforwardedtcpiptunnel.cpp
$$PWD/sshforwardedtcpiptunnel.cpp \
$$PWD/sshagent.cpp \
$$PWD/sshx11channel.cpp \
$$PWD/sshx11inforetriever.cpp \
$$PWD/opensshkeyfilereader.cpp \
HEADERS += $$PWD/sshsendfacility_p.h \
PUBLIC_HEADERS = \
$$PWD/sftpdefs.h \
$$PWD/ssherrors.h \
$$PWD/sshremoteprocess.h \
$$PWD/sftpchannel.h \
$$PWD/sshkeygenerator.h \
$$PWD/sshremoteprocessrunner.h \
$$PWD/sshconnectionmanager.h \
$$PWD/sshpseudoterminal.h \
$$PWD/sftpfilesystemmodel.h \
$$PWD/sshdirecttcpiptunnel.h \
$$PWD/sshtcpipforwardserver.h \
$$PWD/sshhostkeydatabase.h \
$$PWD/sshforwardedtcpiptunnel.h \
$$PWD/ssh_global.h \
$$PWD/sshconnection.h \
HEADERS = $$PUBLIC_HEADERS \
$$PWD/sshsendfacility_p.h \
$$PWD/sshremoteprocess_p.h \
$$PWD/sshpacketparser_p.h \
$$PWD/sshpacket_p.h \
$$PWD/sshoutgoingpacket_p.h \
$$PWD/sshkeygenerator.h \
$$PWD/sshkeyexchange_p.h \
$$PWD/sshincomingpacket_p.h \
$$PWD/sshexception_p.h \
$$PWD/ssherrors.h \
$$PWD/sshcryptofacility_p.h \
$$PWD/sshconnection.h \
$$PWD/sshconnection_p.h \
$$PWD/sshchannelmanager_p.h \
$$PWD/sshchannel_p.h \
@ -57,25 +79,19 @@ HEADERS += $$PWD/sshsendfacility_p.h \
$$PWD/sftpoutgoingpacket_p.h \
$$PWD/sftpoperation_p.h \
$$PWD/sftpincomingpacket_p.h \
$$PWD/sftpdefs.h \
$$PWD/sftpchannel.h \
$$PWD/sftpchannel_p.h \
$$PWD/sshremoteprocessrunner.h \
$$PWD/sshconnectionmanager.h \
$$PWD/sshpseudoterminal.h \
$$PWD/sshkeypasswordretriever_p.h \
$$PWD/sftpfilesystemmodel.h \
$$PWD/sshkeycreationdialog.h \
$$PWD/ssh_global.h \
$$PWD/sshdirecttcpiptunnel_p.h \
$$PWD/sshinit_p.h \
$$PWD/sshdirecttcpiptunnel.h \
$$PWD/sshlogging_p.h \
$$PWD/sshhostkeydatabase.h \
$$PWD/sshtcpipforwardserver.h \
$$PWD/sshtcpipforwardserver_p.h \
$$PWD/sshtcpiptunnel_p.h \
$$PWD/sshforwardedtcpiptunnel.h \
$$PWD/sshforwardedtcpiptunnel_p.h
$$PWD/sshforwardedtcpiptunnel_p.h \
$$PWD/sshagent_p.h \
$$PWD/sshx11channel_p.h \
$$PWD/sshx11displayinfo_p.h \
$$PWD/sshx11inforetriever_p.h \
$$PWD/opensshkeyfilereader_p.h \
RESOURCES += $$PWD/qssh.qrc
FORMS += $$PWD/sshkeycreationdialog.ui

View file

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/ssh">
<file>images/dir.png</file>
<file>images/help.png</file>
<file>images/unknownfile.png</file>
</qresource>
</RCC>

View file

@ -1,31 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpchannel.h"
#include "sftpchannel_p.h"
#include "sftpdefs.h"
#include "sshexception_p.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
@ -34,33 +40,9 @@
#include <QDir>
#include <QFile>
/*!
\class QSsh::SftpChannel
\brief The SftpChannel class provides SFTP operations.
Objects are created via SshConnection::createSftpChannel().
The channel needs to be initialized with
a call to initialize() and is closed via closeChannel(). After closing
a channel, no more operations are possible. It cannot be re-opened
using initialize(); use SshConnection::createSftpChannel() if you need
a new one.
After the initialized() signal has been emitted, operations can be started.
All SFTP operations are asynchronous (non-blocking) and can be in-flight
simultaneously (though callers must ensure that concurrently running jobs
are independent of each other, e.g. they must not write to the same file).
Operations are identified by their job id, which is returned by
the respective member function. If the function can right away detect that
the operation cannot succeed, it returns SftpInvalidJob. If an error occurs
later, the finished() signal is emitted for the respective job with a
non-empty error string.
Note that directory names must not have a trailing slash.
*/
namespace QSsh {
namespace Internal {
namespace {
const quint32 ProtocolVersion = 3;
@ -76,9 +58,53 @@ namespace {
return response.status == SSH_FX_OK ? QString()
: errorMessage(response.errorString, alternativeMessage);
}
bool openFile(QFile *localFile, SftpOverwriteMode mode)
{
if (mode == SftpSkipExisting && localFile->exists())
return false;
QIODevice::OpenMode openMode = QIODevice::WriteOnly;
if (mode == SftpOverwriteExisting)
openMode |= QIODevice::Truncate;
else if (mode == SftpAppendToExisting)
openMode |= QIODevice::Append;
return localFile->open(openMode);
}
SftpError sftpStatusToError(const SftpStatusCode status)
{
switch (status) {
case SSH_FX_OK:
return SftpError::NoError;
case SSH_FX_EOF:
return SftpError::EndOfFile;
case SSH_FX_NO_SUCH_FILE:
return SftpError::FileNotFound;
case SSH_FX_PERMISSION_DENIED:
return SftpError::PermissionDenied;
case SSH_FX_BAD_MESSAGE:
return SftpError::BadMessage;
case SSH_FX_NO_CONNECTION:
return SftpError::NoConnection;
case SSH_FX_CONNECTION_LOST:
return SftpError::ConnectionLost;
case SSH_FX_OP_UNSUPPORTED:
return SftpError::UnsupportedOperation;
case SSH_FX_FAILURE:
default:
return SftpError::GenericFailure;
}
}
} // anonymous namespace
} // namespace Internal
//--------------------------------------------------------------------------------------------------
// SftpChannel
//--------------------------------------------------------------------------------------------------
SftpChannel::SftpChannel(quint32 channelId,
Internal::SshSendFacility &sendFacility)
: d(new Internal::SftpChannelPrivate(channelId, sendFacility, this))
@ -95,6 +121,8 @@ SftpChannel::SftpChannel(quint32 channelId,
this, &SftpChannel::finished, Qt::QueuedConnection);
connect(d, &Internal::SftpChannelPrivate::closed,
this, &SftpChannel::closed, Qt::QueuedConnection);
connect(d, &Internal::SftpChannelPrivate::transferProgress,
this, &SftpChannel::transferProgress, Qt::QueuedConnection);
}
SftpChannel::State SftpChannel::state() const
@ -177,6 +205,15 @@ SftpJobId SftpChannel::createFile(const QString &path, SftpOverwriteMode mode)
new Internal::SftpCreateFile(++d->m_nextJobId, path, mode)));
}
SftpJobId SftpChannel::uploadFile(QSharedPointer<QIODevice> device,
const QString &remoteFilePath, SftpOverwriteMode mode)
{
if (!device->isOpen() && !device->open(QIODevice::ReadOnly))
return SftpInvalidJob;
return d->createJob(Internal::SftpUploadFile::Ptr(
new Internal::SftpUploadFile(++d->m_nextJobId, remoteFilePath, device, mode)));
}
SftpJobId SftpChannel::uploadFile(const QString &localFilePath,
const QString &remoteFilePath, SftpOverwriteMode mode)
{
@ -191,17 +228,14 @@ SftpJobId SftpChannel::downloadFile(const QString &remoteFilePath,
const QString &localFilePath, SftpOverwriteMode mode)
{
QSharedPointer<QFile> localFile(new QFile(localFilePath));
if (mode == SftpSkipExisting && localFile->exists())
return SftpInvalidJob;
QIODevice::OpenMode openMode = QIODevice::WriteOnly;
if (mode == SftpOverwriteExisting)
openMode |= QIODevice::Truncate;
else if (mode == SftpAppendToExisting)
openMode |= QIODevice::Append;
if (!localFile->open(openMode))
return SftpInvalidJob;
return d->createJob(Internal::SftpDownload::Ptr(
new Internal::SftpDownload(++d->m_nextJobId, remoteFilePath, localFile)));
new Internal::SftpDownload(++d->m_nextJobId, remoteFilePath, localFile, mode)));
}
SftpJobId SftpChannel::downloadFile(const QString &remoteFilePath, QSharedPointer<QIODevice> device)
{
return d->createJob(Internal::SftpDownload::Ptr(
new Internal::SftpDownload(++d->m_nextJobId, remoteFilePath, device, SftpOverwriteExisting)));
}
SftpJobId SftpChannel::uploadDir(const QString &localDirPath,
@ -224,11 +258,31 @@ SftpJobId SftpChannel::uploadDir(const QString &localDirPath,
return uploadDirOp->jobId;
}
SftpJobId SftpChannel::downloadDir(const QString &remoteDirPath,
const QString &localDirPath, SftpOverwriteMode mode)
{
if (state() != Initialized)
return SftpInvalidJob;
if (!QDir().mkpath(localDirPath))
return SftpInvalidJob;
const Internal::SftpDownloadDir::Ptr downloadDirOp(
new Internal::SftpDownloadDir(++d->m_nextJobId, mode));
const Internal::SftpListDir::Ptr lsdirOp(
new Internal::SftpListDir(++d->m_nextJobId, remoteDirPath, downloadDirOp));
downloadDirOp->lsdirsInProgress.insert(lsdirOp,
Internal::SftpDownloadDir::Dir(localDirPath, remoteDirPath));
d->createJob(lsdirOp);
return downloadDirOp->jobId;
}
SftpChannel::~SftpChannel()
{
delete d;
}
//--------------------------------------------------------------------------------------------------
// SftpChannelPrivate
//--------------------------------------------------------------------------------------------------
namespace Internal {
@ -396,21 +450,21 @@ void SftpChannelPrivate::handleHandle()
}
}
void SftpChannelPrivate::handleLsHandle(const JobMap::Iterator &it)
void SftpChannelPrivate::handleLsHandle(JobMap::Iterator it)
{
SftpListDir::Ptr op = it.value().staticCast<SftpListDir>();
sendData(m_outgoingPacket.generateReadDir(op->remoteHandle,
op->jobId).rawData());
}
void SftpChannelPrivate::handleCreateFileHandle(const JobMap::Iterator &it)
void SftpChannelPrivate::handleCreateFileHandle(JobMap::Iterator it)
{
SftpCreateFile::Ptr op = it.value().staticCast<SftpCreateFile>();
sendData(m_outgoingPacket.generateCloseHandle(op->remoteHandle,
op->jobId).rawData());
}
void SftpChannelPrivate::handleGetHandle(const JobMap::Iterator &it)
void SftpChannelPrivate::handleGetHandle(JobMap::Iterator it)
{
SftpDownload::Ptr op = it.value().staticCast<SftpDownload>();
sendData(m_outgoingPacket.generateFstat(op->remoteHandle,
@ -418,7 +472,7 @@ void SftpChannelPrivate::handleGetHandle(const JobMap::Iterator &it)
op->statRequested = true;
}
void SftpChannelPrivate::handlePutHandle(const JobMap::Iterator &it)
void SftpChannelPrivate::handlePutHandle(JobMap::Iterator it)
{
SftpUploadFile::Ptr op = it.value().staticCast<SftpUploadFile>();
if (op->parentJob && op->parentJob->hasError)
@ -464,16 +518,16 @@ void SftpChannelPrivate::handleStatus()
}
}
void SftpChannelPrivate::handleStatusGeneric(const JobMap::Iterator &it,
void SftpChannelPrivate::handleStatusGeneric(JobMap::Iterator it,
const SftpStatusResponse &response)
{
AbstractSftpOperation::Ptr op = it.value();
const QString error = errorMessage(response, tr("Unknown error."));
emit finished(op->jobId, error);
emit finished(op->jobId, sftpStatusToError(response.status), error);
m_jobs.erase(it);
}
void SftpChannelPrivate::handleMkdirStatus(const JobMap::Iterator &it,
void SftpChannelPrivate::handleMkdirStatus(JobMap::Iterator it,
const SftpStatusResponse &response)
{
SftpMakeDir::Ptr op = it.value().staticCast<SftpMakeDir>();
@ -500,6 +554,7 @@ void SftpChannelPrivate::handleMkdirStatus(const JobMap::Iterator &it,
} else {
parentJob->setError();
emit finished(parentJob->jobId,
sftpStatusToError(response.status),
tr("Error creating directory \"%1\": %2")
.arg(remoteDir, response.errorString));
m_jobs.erase(it);
@ -524,6 +579,7 @@ void SftpChannelPrivate::handleMkdirStatus(const JobMap::Iterator &it,
if (!localFile->open(QIODevice::ReadOnly)) {
parentJob->setError();
emit finished(parentJob->jobId,
sftpStatusToError(response.status),
tr("Could not open local file \"%1\": %2")
.arg(fileInfo.absoluteFilePath(), localFile->errorString()));
m_jobs.erase(it);
@ -544,29 +600,58 @@ void SftpChannelPrivate::handleMkdirStatus(const JobMap::Iterator &it,
m_jobs.erase(it);
}
void SftpChannelPrivate::handleLsStatus(const JobMap::Iterator &it,
void SftpChannelPrivate::handleLsStatus(JobMap::Iterator it,
const SftpStatusResponse &response)
{
SftpListDir::Ptr op = it.value().staticCast<SftpListDir>();
if (op->parentJob && op->parentJob->hasError) {
m_jobs.erase(it);
return;
}
switch (op->state) {
case SftpListDir::OpenRequested:
emit finished(op->jobId, errorMessage(response.errorString,
reportRequestError(op, sftpStatusToError(response.status), errorMessage(response.errorString,
tr("Remote directory could not be opened for reading.")));
m_jobs.erase(it);
break;
case SftpListDir::Open:
if (response.status != SSH_FX_EOF)
reportRequestError(op, errorMessage(response.errorString,
reportRequestError(op,
sftpStatusToError(response.status),
errorMessage(response.errorString,
tr("Failed to list remote directory contents.")));
op->state = SftpListDir::CloseRequested;
sendData(m_outgoingPacket.generateCloseHandle(op->remoteHandle,
op->jobId).rawData());
break;
case SftpListDir::CloseRequested:
if (!op->hasError) {
if (op->hasError || (op->parentJob && op->parentJob->hasError)) {
m_jobs.erase(it);
return;
}
{
const QString error = errorMessage(response,
tr("Failed to close remote directory."));
emit finished(op->jobId, error);
if (op->parentJob) {
if (!error.isEmpty()) {
op->parentJob->setError();
}
if (op->parentJob->hasError) {
emit finished(op->parentJob->jobId, sftpStatusToError(response.status), error);
} else {
op->parentJob->lsdirsInProgress.remove(op);
if (op->parentJob->lsdirsInProgress.isEmpty() &&
op->parentJob->downloadsInProgress.isEmpty()) {
emit finished(op->parentJob->jobId);
}
}
} else {
emit finished(op->jobId, sftpStatusToError(response.status), error);
}
}
m_jobs.erase(it);
break;
@ -576,26 +661,31 @@ void SftpChannelPrivate::handleLsStatus(const JobMap::Iterator &it,
}
}
void SftpChannelPrivate::handleGetStatus(const JobMap::Iterator &it,
void SftpChannelPrivate::handleGetStatus(JobMap::Iterator it,
const SftpStatusResponse &response)
{
SftpDownload::Ptr op = it.value().staticCast<SftpDownload>();
if (op->parentJob && op->parentJob->hasError) {
m_jobs.erase(it);
return;
}
switch (op->state) {
case SftpDownload::OpenRequested:
emit finished(op->jobId,
errorMessage(response.errorString,
tr("Failed to open remote file for reading.")));
reportRequestError(op, sftpStatusToError(response.status), errorMessage(response.errorString,
tr("Failed to open remote file for reading.")));
m_jobs.erase(it);
break;
case SftpDownload::Open:
if (op->statRequested) {
reportRequestError(op, errorMessage(response.errorString,
reportRequestError(op, sftpStatusToError(response.status), errorMessage(response.errorString,
tr("Failed to retrieve information on the remote file ('stat' failed).")));
sendTransferCloseHandle(op, response.requestId);
} else {
if ((response.status != SSH_FX_EOF || response.requestId != op->eofId)
&& !op->hasError)
reportRequestError(op, errorMessage(response.errorString,
reportRequestError(op, sftpStatusToError(response.status), errorMessage(response.errorString,
tr("Failed to read remote file.")));
finishTransferRequest(it);
}
@ -603,11 +693,20 @@ void SftpChannelPrivate::handleGetStatus(const JobMap::Iterator &it,
case SftpDownload::CloseRequested:
Q_ASSERT(op->inFlightCount == 1);
if (!op->hasError) {
if (response.status == SSH_FX_OK)
emit finished(op->jobId);
else
reportRequestError(op, errorMessage(response.errorString,
tr("Failed to close remote file.")));
if (response.status == SSH_FX_OK) {
if (op->parentJob) {
op->parentJob->downloadsInProgress.removeOne(op);
if (op->parentJob->lsdirsInProgress.isEmpty()
&& op->parentJob->downloadsInProgress.isEmpty())
emit finished(op->parentJob->jobId);
} else {
emit finished(op->jobId);
}
} else {
const QString error = errorMessage(response.errorString,
tr("Failed to close remote file."));
reportRequestError(op, sftpStatusToError(response.status), error);
}
}
removeTransferRequest(it);
break;
@ -617,7 +716,7 @@ void SftpChannelPrivate::handleGetStatus(const JobMap::Iterator &it,
}
}
void SftpChannelPrivate::handlePutStatus(const JobMap::Iterator &it,
void SftpChannelPrivate::handlePutStatus(JobMap::Iterator it,
const SftpStatusResponse &response)
{
SftpUploadFile::Ptr job = it.value().staticCast<SftpUploadFile>();
@ -635,6 +734,7 @@ void SftpChannelPrivate::handlePutStatus(const JobMap::Iterator &it,
if (emitError) {
emit finished(job->jobId,
sftpStatusToError(response.status),
errorMessage(response.errorString,
tr("Failed to open remote file for writing.")));
}
@ -653,7 +753,7 @@ void SftpChannelPrivate::handlePutStatus(const JobMap::Iterator &it,
} else {
if (job->parentJob)
job->parentJob->setError();
reportRequestError(job, errorMessage(response.errorString,
reportRequestError(job, sftpStatusToError(response.status), errorMessage(response.errorString,
tr("Failed to write remote file.")));
finishTransferRequest(it);
}
@ -679,9 +779,9 @@ void SftpChannelPrivate::handlePutStatus(const JobMap::Iterator &it,
tr("Failed to close remote file."));
if (job->parentJob) {
job->parentJob->setError();
emit finished(job->parentJob->jobId, error);
emit finished(job->parentJob->jobId, sftpStatusToError(response.status), error);
} else {
emit finished(job->jobId, error);
emit finished(job->jobId, sftpStatusToError(response.status), error);
}
}
m_jobs.erase(it);
@ -713,7 +813,13 @@ void SftpChannelPrivate::handleName()
attributesToFileInfo(file.attributes, fileInfo);
fileInfoList << fileInfo;
}
emit fileInfoAvailable(op->jobId, fileInfoList);
if (op->parentJob) {
handleDownloadDir(op, fileInfoList);
} else {
emit fileInfoAvailable(op->jobId, fileInfoList);
}
sendData(m_outgoingPacket.generateReadDir(op->remoteHandle,
op->jobId).rawData());
break;
@ -739,18 +845,35 @@ void SftpChannelPrivate::handleReadData()
return;
}
if (!op->localFile->isOpen()) {
QFile *fileDevice = qobject_cast<QFile*>(op->localFile.data());
if (fileDevice){
if (!Internal::openFile(fileDevice, op->mode)) {
reportRequestError(op, SftpError::GenericFailure, tr("Cannot open file ") + fileDevice->fileName());
finishTransferRequest(it);
return;
}
} else {
reportRequestError(op, SftpError::GenericFailure, tr("File to upload is not open"));
finishTransferRequest(it);
return;
}
}
if (!op->localFile->seek(op->offsets[response.requestId])) {
reportRequestError(op, op->localFile->errorString());
reportRequestError(op, SftpError::GenericFailure, op->localFile->errorString());
finishTransferRequest(it);
return;
}
if (op->localFile->write(response.data) != response.data.size()) {
reportRequestError(op, op->localFile->errorString());
reportRequestError(op, SftpError::GenericFailure, op->localFile->errorString());
finishTransferRequest(it);
return;
}
emit transferProgress(op->jobId, op->localFile->pos(), op->fileSize);
if (op->offset >= op->fileSize && op->fileSize != 0)
finishTransferRequest(it);
else
@ -792,6 +915,7 @@ void SftpChannelPrivate::handleAttrs()
op->eofId = op->jobId;
}
op->statRequested = false;
emit transferProgress(op->jobId, op->offset, op->fileSize);
spawnReadRequests(op);
} else {
SftpUploadFile::Ptr op = transfer.staticCast<SftpUploadFile>();
@ -803,17 +927,62 @@ void SftpChannelPrivate::handleAttrs()
if (response.attrs.sizePresent) {
op->offset = response.attrs.size;
emit transferProgress(op->jobId, op->offset, op->fileSize);
spawnWriteRequests(it);
} else {
if (op->parentJob)
op->parentJob->setError();
reportRequestError(op, tr("Cannot append to remote file: "
reportRequestError(op, SftpError::UnsupportedOperation, tr("Cannot append to remote file: "
"Server does not support the file size attribute."));
sendTransferCloseHandle(op, op->jobId);
}
}
}
void SftpChannelPrivate::handleDownloadDir(SftpListDir::Ptr op,
const QList<SftpFileInfo> &fileInfoList)
{
if (op->parentJob->hasError) {
return;
}
foreach (SftpFileInfo fileInfo, fileInfoList) {
Internal::SftpDownloadDir::Dir dir = op->parentJob->lsdirsInProgress[op];
QString fullPathRemote = QDir(dir.remoteDir).path() + QLatin1Char('/') + fileInfo.name;
QString fullPathLocal = QDir(dir.localDir).path() + QLatin1Char('/') + fileInfo.name;
if (fileInfo.type == FileTypeRegular) {
QSharedPointer<QFile> localFile(new QFile(fullPathLocal));
Internal::SftpDownload::Ptr downloadJob = Internal::SftpDownload::Ptr(
new Internal::SftpDownload(++m_nextJobId, fullPathRemote, localFile,
op->parentJob->mode, op->parentJob));
op->parentJob->downloadsInProgress.append(downloadJob);
createJob(downloadJob);
} else if (fileInfo.type == FileTypeDirectory) {
if (fileInfo.name == QLatin1String(".") || fileInfo.name == QLatin1String("..")) {
continue;
}
if (!QDir().mkpath(fullPathLocal)) {
reportRequestError(op, SftpError::GenericFailure, tr("Cannot create directory ") + fullPathLocal);
break;
}
Internal::SftpListDir::Ptr lsdir = Internal::SftpListDir::Ptr(
new Internal::SftpListDir(++m_nextJobId, fullPathRemote, op->parentJob));
op->parentJob->lsdirsInProgress.insert(lsdir,
Internal::SftpDownloadDir::Dir(fullPathLocal, fullPathRemote));
createJob(lsdir);
} else {
// andres.pagliano TODO handle?
}
}
}
SftpChannelPrivate::JobMap::Iterator SftpChannelPrivate::lookupJob(SftpJobId id)
{
JobMap::Iterator it = m_jobs.find(id);
@ -827,7 +996,7 @@ SftpChannelPrivate::JobMap::Iterator SftpChannelPrivate::lookupJob(SftpJobId id)
void SftpChannelPrivate::closeHook()
{
for (JobMap::ConstIterator it = m_jobs.constBegin(); it != m_jobs.constEnd(); ++it)
emit finished(it.key(), tr("SFTP channel closed unexpectedly."));
emit finished(it.key(), SftpError::EndOfFile, tr("SFTP channel closed unexpectedly."));
m_jobs.clear();
m_incomingData.clear();
m_incomingPacket.clear();
@ -863,13 +1032,35 @@ void SftpChannelPrivate::sendReadRequest(const SftpDownload::Ptr &job,
}
void SftpChannelPrivate::reportRequestError(const AbstractSftpOperationWithHandle::Ptr &job,
const SftpError errorType,
const QString &error)
{
emit finished(job->jobId, error);
// andres.pagliano TODO refactor
// Report list error during download dir
SftpListDir::Ptr lsjob = job.dynamicCast<SftpListDir>();
if (!lsjob.isNull() && lsjob->parentJob) {
if (!lsjob->parentJob->hasError) {
emit finished(lsjob->parentJob->jobId, errorType, error);
lsjob->parentJob->hasError = true;
}
} else {
// Report download error during recursive download dir
SftpDownload::Ptr djob = job.dynamicCast<SftpDownload>();
if (!djob.isNull() && djob->parentJob) {
if (!djob->parentJob->hasError) {
emit finished(djob->parentJob->jobId, errorType, error);
djob->parentJob->hasError = true;
}
} else {
// Other error
emit finished(job->jobId, errorType, error);
}
}
job->hasError = true;
}
void SftpChannelPrivate::finishTransferRequest(const JobMap::Iterator &it)
void SftpChannelPrivate::finishTransferRequest(JobMap::Iterator it)
{
AbstractSftpTransfer::Ptr job = it.value().staticCast<AbstractSftpTransfer>();
if (job->inFlightCount == 1)
@ -901,7 +1092,14 @@ void SftpChannelPrivate::attributesToFileInfo(const SftpFileAttributes &attribut
else
fileInfo.type = FileTypeOther;
fileInfo.permissionsValid = true;
fileInfo.permissions = 0;
fileInfo.permissions = {};
if (attributes.timesPresent) {
fileInfo.atime = attributes.atime;
fileInfo.mtime = attributes.mtime;
fileInfo.timestampsValid = true;
}
if (attributes.permissions & 00001) // S_IXOTH
fileInfo.permissions |= QFile::ExeOther;
if (attributes.permissions & 00002) // S_IWOTH
@ -923,20 +1121,25 @@ void SftpChannelPrivate::attributesToFileInfo(const SftpFileAttributes &attribut
}
}
void SftpChannelPrivate::removeTransferRequest(const JobMap::Iterator &it)
void SftpChannelPrivate::removeTransferRequest(JobMap::Iterator it)
{
--it.value().staticCast<AbstractSftpTransfer>()->inFlightCount;
m_jobs.erase(it);
}
void SftpChannelPrivate::sendWriteRequest(const JobMap::Iterator &it)
void SftpChannelPrivate::sendWriteRequest(JobMap::Iterator it)
{
SftpUploadFile::Ptr job = it.value().staticCast<SftpUploadFile>();
emit transferProgress(job->jobId, job->localFile->pos(), job->localFile->size());
QByteArray data = job->localFile->read(AbstractSftpPacket::MaxDataSize);
if (job->localFile->error() != QFile::NoError) {
QFileDevice *fileDevice = qobject_cast<QFileDevice*>(job->localFile.data());
if (fileDevice && fileDevice->error() != QFileDevice::NoError) {
if (job->parentJob)
job->parentJob->setError();
reportRequestError(job, tr("Error reading local file: %1")
reportRequestError(job, SftpError::GenericFailure, tr("Error reading local file: %1")
.arg(job->localFile->errorString()));
finishTransferRequest(it);
} else if (data.isEmpty()) {
@ -948,7 +1151,7 @@ void SftpChannelPrivate::sendWriteRequest(const JobMap::Iterator &it)
}
}
void SftpChannelPrivate::spawnWriteRequests(const JobMap::Iterator &it)
void SftpChannelPrivate::spawnWriteRequests(JobMap::Iterator it)
{
SftpUploadFile::Ptr op = it.value().staticCast<SftpUploadFile>();
op->calculateInFlightCount(AbstractSftpPacket::MaxDataSize);

View file

@ -1,32 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTCHANNEL_H
#define SFTCHANNEL_H
#include "sftpdefs.h"
#include "sftpincomingpacket_p.h"
#include "ssh_global.h"
@ -43,6 +48,32 @@ class SshChannelManager;
class SshSendFacility;
} // namespace Internal
/*!
\class QSsh::SftpChannel
\brief This class provides SFTP operations.
Objects are created via SshConnection::createSftpChannel().
The channel needs to be initialized with
a call to initialize() and is closed via closeChannel(). After closing
a channel, no more operations are possible. It cannot be re-opened
using initialize(); use SshConnection::createSftpChannel() if you need
a new one.
After the initialized() signal has been emitted, operations can be started.
All SFTP operations are asynchronous (non-blocking) and can be in-flight
simultaneously (though callers must ensure that concurrently running jobs
are independent of each other, e.g. they must not write to the same file).
Operations are identified by their job id, which is returned by
the respective member function. If the function can right away detect that
the operation cannot succeed, it returns SftpInvalidJob. If an error occurs
later, the finished() signal is emitted for the respective job with a
non-empty error string.
Note that directory names must not have a trailing slash.
*/
class QSSH_EXPORT SftpChannel : public QObject
{
Q_OBJECT
@ -50,50 +81,177 @@ class QSSH_EXPORT SftpChannel : public QObject
friend class Internal::SftpChannelPrivate;
friend class Internal::SshChannelManager;
public:
/// Convenience typedef
typedef QSharedPointer<SftpChannel> Ptr;
/// \see state
enum State { Uninitialized, Initializing, Initialized, Closing, Closed };
/// Current state of this channel
State state() const;
/*!
* @brief Makes this channel ready to use.
*/
void initialize();
/*!
* @brief Call this when you are done with the channel.
*/
void closeChannel();
/*!
* \brief Get information about a remote path, file or directory
* \param path Remote path to state
* \return A unique ID identifying this job
*/
SftpJobId statFile(const QString &path);
/*!
* \brief Get list of contents of a directory
* \param dirPath Remote path of directory
* \return A unique ID identifying this job
*/
SftpJobId listDirectory(const QString &dirPath);
/*!
* \brief Create remote directory
* \param dirPath Remote path of directory
* \return A unique ID identifying this job
*/
SftpJobId createDirectory(const QString &dirPath);
/*!
* \brief Remove remote directory
* \param dirPath Remote path of directory
* \return A unique ID identifying this job
*/
SftpJobId removeDirectory(const QString &dirPath);
/*!
* \brief Remove remote file
* \param filePath Remote path of file
* \return A unique ID identifying this job
*/
SftpJobId removeFile(const QString &filePath);
/*!
* \brief Rename or move a remote file or directory
* \param oldPath Path of existing file or directory
* \param newPath New path the file or directory should be available as
* \return A unique ID identifying this job
*/
SftpJobId renameFileOrDirectory(const QString &oldPath,
const QString &newPath);
/*!
* \brief Create a new empty file.
* \param filePath Remote path of the file.
* \param mode The behavior if the file already exists.
* \return A unique ID identifying this job
*/
SftpJobId createFile(const QString &filePath, SftpOverwriteMode mode);
/*!
* \brief Creates a symbolic link pointing to another file.
* \param filePath The path of the symbolic
* \param target The path the symbolic link should point to
* \return A unique ID identifying this job
*/
SftpJobId createLink(const QString &filePath, const QString &target);
/*!
* \brief Creates a remote file and fills it with data from \a device
* \param device If this is not open already it will be opened in \a QIODevice::ReadOnly mode
* \param remoteFilePath The path on the server to upload the file to
* \param mode #QSsh::SftpOverwriteMode defines the behavior if the file already exists
* \return A unique ID identifying this job
*/
SftpJobId uploadFile(QSharedPointer<QIODevice> device,
const QString &remoteFilePath, SftpOverwriteMode mode);
/*!
* \brief Uploads a local file to the remote host.
* \param localFilePath The local path to an existing file
* \param remoteFilePath The remote path the file should be uploaded to
* \param mode What it will do if the file already exists
* \return A unique ID identifying this job
*/
SftpJobId uploadFile(const QString &localFilePath,
const QString &remoteFilePath, SftpOverwriteMode mode);
/*!
* \brief Downloads a remote file to a local path
* \param remoteFilePath The remote path to the file to be downloaded
* \param localFilePath The local path for where to download the file
* \param mode Controls what happens if the local file already exists
* \return A unique ID identifying this job
*/
SftpJobId downloadFile(const QString &remoteFilePath,
const QString &localFilePath, SftpOverwriteMode mode);
/*!
* \brief Retrieves the contents of a remote file and writes it to \a device
* \param remoteFilePath The remote path of the file to retrieve the contents of
* \param device The QIODevice to write the data to, this needs to be open in a writable mode
* \return A unique ID identifying this job
*/
SftpJobId downloadFile(const QString &remoteFilePath,
QSharedPointer<QIODevice> device);
/*!
* \brief Uploads a local directory (recursively) with files to the remote host
* \param localDirPath The path to an existing local directory
* \param remoteParentDirPath The remote path to upload it to, the name of the local directory will be appended to this
* \return A unique ID identifying this job
*/
SftpJobId uploadDir(const QString &localDirPath,
const QString &remoteParentDirPath);
/*!
* \brief Downloads a remote directory (recursively) to a local path
* \param remoteDirPath The remote path of an existing directory to download
* \param localDirPath The local path to download the directory to
* \param mode
* \return
*/
SftpJobId downloadDir(const QString &remoteDirPath,
const QString &localDirPath, SftpOverwriteMode mode);
~SftpChannel();
signals:
/// Emitted when you can start using the channel
void initialized();
/// Emitted when an error happened
void channelError(const QString &reason);
/// Emitted when the channel has closed for some reason, either an error occured or it was asked for.
void closed();
// error.isEmpty <=> finished successfully
void finished(QSsh::SftpJobId job, const QString &error = QString());
/// error.isEmpty means it finished successfully
void finished(QSsh::SftpJobId job, const SftpError errorType = SftpError::NoError, const QString &error = QString());
// TODO: Also emit for each file copied by uploadDir().
/*!
* Continously emitted during data transfer.
* Does not emit for each file copied by uploadDir().
*/
void dataAvailable(QSsh::SftpJobId job, const QString &data);
/*
/*!
* This signal is emitted as a result of:
* - statFile() (with the list having exactly one element)
* - listDirectory() (potentially more than once)
* It will continously be emitted as data is discovered, not only when the job is done.
*/
void fileInfoAvailable(QSsh::SftpJobId job, const QList<QSsh::SftpFileInfo> &fileInfoList);
/*!
* Emitted during upload or download
*/
void transferProgress(QSsh::SftpJobId job, quint64 progress, quint64 total);
private:
SftpChannel(quint32 channelId, Internal::SshSendFacility &sendFacility);
@ -101,3 +259,5 @@ private:
};
} // namespace QSsh
#endif // SFTPCHANNEL_H

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTCHANNEL_P_H
#define SFTCHANNEL_P_H
#include "sftpdefs.h"
#include "sftpincomingpacket_p.h"
@ -49,9 +55,10 @@ signals:
void initialized();
void channelError(const QString &reason);
void closed();
void finished(QSsh::SftpJobId job, const QString &error = QString());
void finished(QSsh::SftpJobId job, const SftpError errorType = SftpError::NoError, const QString &error = QString());
void dataAvailable(QSsh::SftpJobId job, const QString &data);
void fileInfoAvailable(QSsh::SftpJobId job, const QList<QSsh::SftpFileInfo> &fileInfoList);
void transferProgress(QSsh::SftpJobId job, quint64 progress, quint64 total);
private:
typedef QMap<SftpJobId, AbstractSftpOperation::Ptr> JobMap;
@ -81,29 +88,31 @@ private:
void handleReadData();
void handleAttrs();
void handleStatusGeneric(const JobMap::Iterator &it,
void handleDownloadDir(SftpListDir::Ptr op, const QList<SftpFileInfo> & fileInfoList);
void handleStatusGeneric(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleMkdirStatus(const JobMap::Iterator &it,
void handleMkdirStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleLsStatus(const JobMap::Iterator &it,
void handleLsStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleGetStatus(const JobMap::Iterator &it,
void handleGetStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handlePutStatus(const JobMap::Iterator &it,
void handlePutStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleLsHandle(const JobMap::Iterator &it);
void handleCreateFileHandle(const JobMap::Iterator &it);
void handleGetHandle(const JobMap::Iterator &it);
void handlePutHandle(const JobMap::Iterator &it);
void handleLsHandle(JobMap::Iterator it);
void handleCreateFileHandle(JobMap::Iterator it);
void handleGetHandle(JobMap::Iterator it);
void handlePutHandle(JobMap::Iterator it);
void spawnReadRequests(const SftpDownload::Ptr &job);
void spawnWriteRequests(const JobMap::Iterator &it);
void spawnWriteRequests(JobMap::Iterator it);
void sendReadRequest(const SftpDownload::Ptr &job, quint32 requestId);
void sendWriteRequest(const JobMap::Iterator &it);
void finishTransferRequest(const JobMap::Iterator &it);
void removeTransferRequest(const JobMap::Iterator &it);
void reportRequestError(const AbstractSftpOperationWithHandle::Ptr &job,
void sendWriteRequest(JobMap::Iterator it);
void finishTransferRequest(JobMap::Iterator it);
void removeTransferRequest(JobMap::Iterator it);
void reportRequestError(const AbstractSftpOperationWithHandle::Ptr &job, const SftpError errorType,
const QString &error);
void sendTransferCloseHandle(const AbstractSftpTransfer::Ptr &job,
quint32 requestId);
@ -122,3 +131,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SFTPCHANNEL_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpdefs.h"

View file

@ -1,59 +1,119 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTPDEFS_H
#define SFTPDEFS_H
#include "ssh_global.h"
#include <QFile>
#include <QString>
/*!
* \namespace QSsh
* \brief The namespace used for the entire library
*/
namespace QSsh {
/*!
*\brief Unique ID used for tracking individual jobs.
*/
typedef quint32 SftpJobId;
/*!
Special ID representing an invalid job, e. g. if a requested job could not be started.
*/
QSSH_EXPORT extern const SftpJobId SftpInvalidJob;
/*!
* \brief The behavior when uploading a file and the remote path already exists
*/
enum SftpOverwriteMode {
SftpOverwriteExisting, SftpAppendToExisting, SftpSkipExisting
/*! Overwrite any existing files */
SftpOverwriteExisting,
/*! Append new content if the file already exists */
SftpAppendToExisting,
/*! If the file or directory already exists skip it */
SftpSkipExisting
};
/*!
* \brief The type of a remote file.
*/
enum SftpFileType { FileTypeRegular, FileTypeDirectory, FileTypeOther, FileTypeUnknown };
/*!
* \brief Possible errors.
*/
enum SftpError { NoError, EndOfFile, FileNotFound, PermissionDenied, GenericFailure, BadMessage, NoConnection, ConnectionLost, UnsupportedOperation };
/*!
\brief Contains information about a remote file.
*/
class QSSH_EXPORT SftpFileInfo
{
public:
SftpFileInfo() : type(FileTypeUnknown), sizeValid(false), permissionsValid(false) { }
/// The remote file name, only file attribute required by the RFC to be present so this is always set
QString name;
SftpFileType type;
quint64 size;
QFile::Permissions permissions;
// The RFC allows an SFTP server not to support any file attributes beyond the name.
bool sizeValid;
bool permissionsValid;
/// The type of file
SftpFileType type = FileTypeUnknown;
/// The remote file size in bytes.
quint64 size = 0;
/// The permissions set on the file, might be empty as the RFC allows an SFTP server not to support any file attributes beyond the name.
QFileDevice::Permissions permissions{};
/// Last time file was accessed.
quint32 atime = 0;
/// Last time file was modified.
quint32 mtime = 0;
/// If the timestamps (\ref atime and \ref mtime) are valid, the RFC allows an SFTP server not to support any file attributes beyond the name.
bool timestampsValid = false;
/// The RFC allows an SFTP server not to support any file attributes beyond the name.
bool sizeValid = false;
/// The RFC allows an SFTP server not to support any file attributes beyond the name.
bool permissionsValid = false;
};
} // namespace QSsh
#endif // SFTPDEFS_H

View file

@ -1,28 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpfilesystemmodel.h"
#include "sftpchannel.h"
@ -43,7 +47,7 @@ class SftpDirNode;
class SftpFileNode
{
public:
SftpFileNode() : parent(0) { }
SftpFileNode() : parent(nullptr) { }
virtual ~SftpFileNode() { }
QString path;
@ -95,9 +99,9 @@ using namespace Internal;
SftpFileSystemModel::SftpFileSystemModel(QObject *parent)
: QAbstractItemModel(parent), d(new SftpFileSystemModelPrivate)
{
d->sshConnection = 0;
d->sshConnection = nullptr;
d->rootDirectory = QLatin1Char('/');
d->rootNode = 0;
d->rootNode = nullptr;
d->statJobId = SftpInvalidJob;
}
@ -128,7 +132,7 @@ void SftpFileSystemModel::setRootDirectory(const QString &path)
beginResetModel();
d->rootDirectory = path;
delete d->rootNode;
d->rootNode = 0;
d->rootNode = nullptr;
d->lsOps.clear();
d->statJobId = SftpInvalidJob;
endResetModel();
@ -161,16 +165,20 @@ int SftpFileSystemModel::columnCount(const QModelIndex &parent) const
QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const
{
if (!index.internalPointer()) {
return QVariant();
}
const SftpFileNode * const node = indexToFileNode(index);
if (index.column() == 0 && role == Qt::DecorationRole) {
switch (node->fileInfo.type) {
case FileTypeRegular:
case FileTypeOther:
return QIcon(":/utils/images/unknownfile.png");
return QIcon(QStringLiteral(":/ssh/images/unknownfile.png"));
case FileTypeDirectory:
return QIcon(":/utils/images/dir.png");
return QIcon(QStringLiteral(":/ssh/images/dir.png"));
case FileTypeUnknown:
return QIcon(":/utils/images/help.png"); // Shows a question mark.
return QIcon(QStringLiteral(":/ssh/images/help.png")); // Shows a question mark.
}
}
if (index.column() == 1) {
@ -237,7 +245,7 @@ QModelIndex SftpFileSystemModel::parent(const QModelIndex &child) const
int SftpFileSystemModel::rowCount(const QModelIndex &parent) const
{
if (!d->rootNode)
return 0;
return 1; // fake it until we make it, otherwise QTreeView isn't happy
if (!parent.isValid())
return 1;
if (parent.column() != 0)
@ -254,23 +262,27 @@ int SftpFileSystemModel::rowCount(const QModelIndex &parent) const
void SftpFileSystemModel::statRootDirectory()
{
if (!d->sftpChannel) {
return;
}
d->statJobId = d->sftpChannel->statFile(d->rootDirectory);
}
void SftpFileSystemModel::shutDown()
{
if (d->sftpChannel) {
disconnect(d->sftpChannel.data(), 0, this, 0);
disconnect(d->sftpChannel.data(), nullptr, this, nullptr);
d->sftpChannel->closeChannel();
d->sftpChannel.clear();
}
if (d->sshConnection) {
disconnect(d->sshConnection, 0, this, 0);
disconnect(d->sshConnection, nullptr, this, nullptr);
QSsh::releaseConnection(d->sshConnection);
d->sshConnection = 0;
d->sshConnection = nullptr;
}
delete d->rootNode;
d->rootNode = 0;
d->rootNode = nullptr;
}
void SftpFileSystemModel::handleSshConnectionFailure()
@ -332,9 +344,13 @@ void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QList<SftpFileIn
if (filteredList.isEmpty())
return;
// In theory beginInsertRows() should suffice, but that fails to have an effect
// if rowCount() returned 0 earlier.
emit layoutAboutToBeChanged();
if (parentNode->parent) {
QModelIndex parentIndex = createIndex(parentNode->parent->children.indexOf(parentNode), 0, parentNode);
beginInsertRows(parentIndex, rowCount(parentIndex), rowCount(parentIndex) + filteredList.count());
} else {
// root node
beginInsertRows(QModelIndex(), 0, 1);
}
foreach (const SftpFileInfo &fileInfo, filteredList) {
SftpFileNode *childNode;
@ -350,11 +366,13 @@ void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QList<SftpFileIn
childNode->parent = parentNode;
parentNode->children << childNode;
}
emit layoutChanged(); // Should be endInsertRows(), see above.
endInsertRows();
}
void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const QString &errorMessage)
void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const SftpError error, const QString &errorMessage)
{
Q_UNUSED(error);
if (jobId == d->statJobId) {
d->statJobId = SftpInvalidJob;
if (!errorMessage.isEmpty())

View file

@ -1,29 +1,34 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#ifndef SFTPFILESYSTEMMODEL_H
#define SFTPFILESYSTEMMODEL_H
#include "sftpdefs.h"
@ -41,7 +46,7 @@ class QSSH_EXPORT SftpFileSystemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit SftpFileSystemModel(QObject *parent = 0);
explicit SftpFileSystemModel(QObject *parent = nullptr);
~SftpFileSystemModel();
/*
@ -82,7 +87,7 @@ private:
void handleSftpChannelInitialized();
void handleSftpChannelError(const QString &reason);
void handleFileInfo(QSsh::SftpJobId jobId, const QList<QSsh::SftpFileInfo> &fileInfoList);
void handleSftpJobFinished(QSsh::SftpJobId jobId, const QString &errorMessage);
void handleSftpJobFinished(QSsh::SftpJobId jobId, const SftpError error, const QString &errorMessage);
int columnCount(const QModelIndex &parent = QModelIndex()) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
@ -98,3 +103,5 @@ private:
};
} // namespace QSsh;
#endif // SFTPFILESYSTEMMODEL_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpincomingpacket_p.h"
@ -191,8 +196,9 @@ SftpFileAttributes SftpIncomingPacket::asFileAttributes(quint32 &offset) const
attributes.timesPresent = flags & SSH_FILEXFER_ATTR_ACMODTIME;
attributes.uidAndGidPresent = flags & SSH_FILEXFER_ATTR_UIDGID;
attributes.permissionsPresent = flags & SSH_FILEXFER_ATTR_PERMISSIONS;
if (attributes.sizePresent)
if (attributes.sizePresent) {
attributes.size = SshPacketParser::asUint64(m_data, &offset);
}
if (attributes.uidAndGidPresent) {
attributes.uid = SshPacketParser::asUint32(m_data, &offset);
attributes.gid = SshPacketParser::asUint32(m_data, &offset);

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTPINCOMINGPACKET_P_H
#define SFTPINCOMINGPACKET_P_H
#include "sftppacket_p.h"
@ -102,3 +108,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SFTPINCOMINGPACKET_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpoperation_p.h"
@ -114,8 +119,9 @@ AbstractSftpOperationWithHandle::AbstractSftpOperationWithHandle(SftpJobId jobId
AbstractSftpOperationWithHandle::~AbstractSftpOperationWithHandle() { }
SftpListDir::SftpListDir(SftpJobId jobId, const QString &path)
: AbstractSftpOperationWithHandle(jobId, path)
SftpListDir::SftpListDir(SftpJobId jobId, const QString &path,
const QSharedPointer<SftpDownloadDir> &parentJob)
: AbstractSftpOperationWithHandle(jobId, path), parentJob(parentJob)
{
}
@ -143,7 +149,7 @@ SftpOutgoingPacket & SftpCreateFile::initialPacket(SftpOutgoingPacket &packet)
const int AbstractSftpTransfer::MaxInFlightCount = 10; // Experimentally found to be enough.
AbstractSftpTransfer::AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile)
const QSharedPointer<QIODevice> &localFile)
: AbstractSftpOperationWithHandle(jobId, remotePath),
localFile(localFile), fileSize(0), offset(0), inFlightCount(0),
statRequested(false)
@ -167,8 +173,10 @@ void AbstractSftpTransfer::calculateInFlightCount(quint32 chunkSize)
SftpDownload::SftpDownload(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile)
: AbstractSftpTransfer(jobId, remotePath, localFile), eofId(SftpInvalidJob)
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const QSharedPointer<QSsh::Internal::SftpDownloadDir> &parentJob)
: AbstractSftpTransfer(jobId, remotePath, localFile), eofId(SftpInvalidJob), mode(mode),
parentJob(parentJob)
{
}
@ -180,7 +188,7 @@ SftpOutgoingPacket &SftpDownload::initialPacket(SftpOutgoingPacket &packet)
SftpUploadFile::SftpUploadFile(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile, SftpOverwriteMode mode,
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const SftpUploadDir::Ptr &parentJob)
: AbstractSftpTransfer(jobId, remotePath, localFile),
parentJob(parentJob), mode(mode)
@ -192,25 +200,33 @@ SftpOutgoingPacket &SftpUploadFile::initialPacket(SftpOutgoingPacket &packet)
{
state = OpenRequested;
quint32 permissions = 0;
const QFile::Permissions &qtPermissions = localFile->permissions();
if (qtPermissions & QFile::ExeOther)
permissions |= 1 << 0;
if (qtPermissions & QFile::WriteOther)
permissions |= 1 << 1;
if (qtPermissions & QFile::ReadOther)
permissions |= 1 << 2;
if (qtPermissions & QFile::ExeGroup)
permissions |= 1<< 3;
if (qtPermissions & QFile::WriteGroup)
permissions |= 1<< 4;
if (qtPermissions & QFile::ReadGroup)
permissions |= 1<< 5;
if (qtPermissions & QFile::ExeOwner)
permissions |= 1<< 6;
if (qtPermissions & QFile::WriteOwner)
QFileDevice *fileDevice = qobject_cast<QFileDevice*>(localFile.data());
if (fileDevice) {
const QFile::Permissions &qtPermissions = fileDevice->permissions();
if (qtPermissions & QFile::ExeOther)
permissions |= 1 << 0;
if (qtPermissions & QFile::WriteOther)
permissions |= 1 << 1;
if (qtPermissions & QFile::ReadOther)
permissions |= 1 << 2;
if (qtPermissions & QFile::ExeGroup)
permissions |= 1<< 3;
if (qtPermissions & QFile::WriteGroup)
permissions |= 1<< 4;
if (qtPermissions & QFile::ReadGroup)
permissions |= 1<< 5;
if (qtPermissions & QFile::ExeOwner)
permissions |= 1<< 6;
if (qtPermissions & QFile::WriteOwner)
permissions |= 1<< 7;
if (qtPermissions & QFile::ReadOwner)
permissions |= 1<< 8;
} else {
// write owner
permissions |= 1<< 7;
if (qtPermissions & QFile::ReadOwner)
// read owner
permissions |= 1<< 8;
}
return packet.generateOpenFileForWriting(remotePath, mode, permissions, jobId);
}

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTPOPERATION_P_H
#define SFTPOPERATION_P_H
#include "sftpdefs.h"
@ -33,7 +39,7 @@
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
class QFile;
class QIODevice;
QT_END_NAMESPACE
namespace QSsh {
@ -61,6 +67,7 @@ private:
};
struct SftpUploadDir;
struct SftpDownloadDir;
struct SftpStatFile : public AbstractSftpOperation
{
@ -152,9 +159,12 @@ struct SftpListDir : public AbstractSftpOperationWithHandle
{
typedef QSharedPointer<SftpListDir> Ptr;
SftpListDir(SftpJobId jobId, const QString &path);
SftpListDir(SftpJobId jobId, const QString &path,
const QSharedPointer<SftpDownloadDir> &parentJob = QSharedPointer<SftpDownloadDir>());
virtual Type type() const { return ListDir; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QSharedPointer<SftpDownloadDir> parentJob;
};
@ -174,13 +184,13 @@ struct AbstractSftpTransfer : public AbstractSftpOperationWithHandle
typedef QSharedPointer<AbstractSftpTransfer> Ptr;
AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile);
const QSharedPointer<QIODevice> &localFile);
~AbstractSftpTransfer();
void calculateInFlightCount(quint32 chunkSize);
static const int MaxInFlightCount;
const QSharedPointer<QFile> localFile;
const QSharedPointer<QIODevice> localFile;
quint64 fileSize;
quint64 offset;
int inFlightCount;
@ -191,12 +201,15 @@ struct SftpDownload : public AbstractSftpTransfer
{
typedef QSharedPointer<SftpDownload> Ptr;
SftpDownload(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile);
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const QSharedPointer<SftpDownloadDir> &parentJob = QSharedPointer<SftpDownloadDir>());
virtual Type type() const { return Download; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
QMap<quint32, quint64> offsets;
SftpJobId eofId;
SftpOverwriteMode mode;
const QSharedPointer<QSsh::Internal::SftpDownloadDir> parentJob;
};
struct SftpUploadFile : public AbstractSftpTransfer
@ -204,7 +217,7 @@ struct SftpUploadFile : public AbstractSftpTransfer
typedef QSharedPointer<SftpUploadFile> Ptr;
SftpUploadFile(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QFile> &localFile, SftpOverwriteMode mode,
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const QSharedPointer<SftpUploadDir> &parentJob = QSharedPointer<SftpUploadDir>());
virtual Type type() const { return UploadFile; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
@ -240,5 +253,38 @@ struct SftpUploadDir
QMap<SftpMakeDir::Ptr, Dir> mkdirsInProgress;
};
// Composite operation.
struct SftpDownloadDir
{
typedef QSharedPointer<SftpDownloadDir> Ptr;
struct Dir {
Dir() {}
Dir(const QString &l, const QString &r) : localDir(l), remoteDir(r) {}
QString localDir;
QString remoteDir;
};
SftpDownloadDir(SftpJobId jobId, SftpOverwriteMode mode)
: jobId(jobId), hasError(false), mode(mode) {}
~SftpDownloadDir() {}
void setError()
{
hasError = true;
downloadsInProgress.clear();
lsdirsInProgress.clear();
}
const SftpJobId jobId;
bool hasError;
SftpOverwriteMode mode;
QList<SftpDownload::Ptr> downloadsInProgress;
QMap<SftpListDir::Ptr, Dir> lsdirsInProgress;
};
} // namespace Internal
} // namespace QSsh
#endif // SFTPOPERATION_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftpoutgoingpacket_p.h"

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTPOUTGOINGPACKET_P_H
#define SFTPOUTGOINGPACKET_P_H
#include "sftppacket_p.h"
#include "sftpdefs.h"
@ -82,3 +88,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SFTPOUTGOINGPACKET_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sftppacket_p.h"
@ -30,8 +35,11 @@
namespace QSsh {
namespace Internal {
const quint32 AbstractSftpPacket::MaxDataSize = 32000;
const quint32 AbstractSftpPacket::MaxPacketSize = 34000;
// There's no "standard" or negotiation between server and client for this, so
// just use the same as openssh's sftp implementation
const quint32 AbstractSftpPacket::MaxDataSize = 32768;
const quint32 AbstractSftpPacket::MaxPacketSize = 256 * 1024;
const int AbstractSftpPacket::TypeOffset = 4;
const int AbstractSftpPacket::RequestIdOffset = TypeOffset + 1;
const int AbstractSftpPacket::PayloadOffset = RequestIdOffset + 4;

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SFTPPACKET_P_H
#define SFTPPACKET_P_H
#include <QByteArray>
#include <QList>
@ -107,3 +113,5 @@ protected:
} // namespace Internal
} // namespace QSsh
#endif // SFTPPACKET_P_H

View file

@ -1,8 +0,0 @@
TARGET = QtSsh
load(qt_module)
DEFINES += QTCSSH_LIBRARY
include($$PWD/ssh.pri)
include($$PWD/../botan/botan.pri)

View file

@ -1 +0,0 @@
QTC_LIB_NAME = QtcSsh

View file

@ -1,41 +1,54 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSH_GLOBAL_H
#define SSH_GLOBAL_H
#include <QtGlobal>
//#if defined(QTCSSH_LIBRARY)
//# define QSSH_EXPORT Q_DECL_EXPORT
//#else
//# define QSSH_EXPORT Q_DECL_IMPORT
//#endif
#ifdef _MSC_VER
// For static cmake building removing dll export/import
# define QSSH_EXPORT
#else
#define QSSH_EXPORT
#if defined(QTCSSH_LIBRARY)
# define QSSH_EXPORT Q_DECL_EXPORT
#else
# define QSSH_EXPORT Q_DECL_IMPORT
#endif
#endif
#define QSSH_PRINT_WARNING qWarning("Soft assert at %s:%d", __FILE__, __LINE__)
#define QSSH_ASSERT(cond) do { if (!(cond)) { QSSH_PRINT_WARNING; } } while (false)
#define QSSH_ASSERT_AND_RETURN(cond) do { if (!(cond)) { QSSH_PRINT_WARNING; return; } } while (false)
#define QSSH_ASSERT_AND_RETURN_VALUE(cond, value) do { if (!(cond)) { QSSH_PRINT_WARNING; return value; } } while (false)
#endif // SSH_GLOBAL_H

View file

@ -0,0 +1,313 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sshagent_p.h"
#include "sshlogging_p.h"
#include "sshpacket_p.h"
#include "sshpacketparser_p.h"
#include "ssh_global.h"
#include <QTimer>
#include <QtEndian>
#include <algorithm>
namespace QSsh {
namespace Internal {
// https://github.com/openssh/openssh-portable/blob/V_7_2/PROTOCOL.agent
enum PacketType {
SSH_AGENT_FAILURE = 5,
SSH2_AGENTC_REQUEST_IDENTITIES = 11,
SSH2_AGENTC_SIGN_REQUEST = 13,
SSH2_AGENT_IDENTITIES_ANSWER = 12,
SSH2_AGENT_SIGN_RESPONSE = 14,
};
// TODO: Remove once we require 5.7, where the endianness functions have a sane input type.
template<typename T> static T fromBigEndian(const QByteArray &ba)
{
return qFromBigEndian<T>(reinterpret_cast<const uchar *>(ba.constData()));
}
void SshAgent::refreshKeysImpl()
{
if (state() != Connected)
return;
const auto keysRequestIt = std::find_if(m_pendingRequests.constBegin(),
m_pendingRequests.constEnd(), [](const Request &r) { return r.isKeysRequest(); });
if (keysRequestIt != m_pendingRequests.constEnd()) {
qCDebug(sshLog) << "keys request already pending, not adding another one";
return;
}
qCDebug(sshLog) << "queueing keys request";
m_pendingRequests << Request();
sendNextRequest();
}
void SshAgent::requestSignatureImpl(const QByteArray &key, uint token)
{
if (state() != Connected)
return;
const QByteArray data = m_dataToSign.take(qMakePair(key, token));
QSSH_ASSERT(!data.isEmpty());
qCDebug(sshLog) << "queueing signature request";
m_pendingRequests.enqueue(Request(key, data, token));
sendNextRequest();
}
void SshAgent::sendNextRequest()
{
if (m_pendingRequests.isEmpty())
return;
if (m_outgoingPacket.isComplete())
return;
if (hasError())
return;
const Request &request = m_pendingRequests.head();
m_outgoingPacket = request.isKeysRequest() ? generateKeysPacket() : generateSigPacket(request);
sendPacket();
}
SshAgent::Packet SshAgent::generateKeysPacket()
{
qCDebug(sshLog) << "requesting keys from agent";
Packet p;
p.size = 1;
p.data += char(SSH2_AGENTC_REQUEST_IDENTITIES);
return p;
}
SshAgent::Packet SshAgent::generateSigPacket(const SshAgent::Request &request)
{
qCDebug(sshLog) << "requesting signature from agent for key" << request.key << "and token"
<< request.token;
Packet p;
p.data += char(SSH2_AGENTC_SIGN_REQUEST);
p.data += AbstractSshPacket::encodeString(request.key);
p.data += AbstractSshPacket::encodeString(request.dataToSign);
p.data += AbstractSshPacket::encodeInt(quint32(0));
p.size = p.data.count();
return p;
}
SshAgent::~SshAgent()
{
m_agentSocket.disconnect(this);
}
void SshAgent::storeDataToSign(const QByteArray &key, const QByteArray &data, uint token)
{
instance().m_dataToSign.insert(qMakePair(key, token), data);
}
void SshAgent::removeDataToSign(const QByteArray &key, uint token)
{
instance().m_dataToSign.remove(qMakePair(key, token));
}
SshAgent &QSsh::Internal::SshAgent::instance()
{
static SshAgent agent;
return agent;
}
SshAgent::SshAgent()
{
connect(&m_agentSocket, &QLocalSocket::connected, this, &SshAgent::handleConnected);
connect(&m_agentSocket, &QLocalSocket::disconnected, this, &SshAgent::handleDisconnected);
connect(&m_agentSocket, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(handleSocketError()));
connect(&m_agentSocket, &QLocalSocket::readyRead, this, &SshAgent::handleIncomingData);
QTimer::singleShot(0, this, &SshAgent::connectToServer);
}
void SshAgent::connectToServer()
{
const QByteArray serverAddress = qgetenv("SSH_AUTH_SOCK");
if (serverAddress.isEmpty()) {
qCDebug(sshLog) << "agent failure: socket address unknown";
m_error = tr("Cannot connect to ssh-agent: SSH_AUTH_SOCK is not set.");
emit errorOccurred();
return;
}
qCDebug(sshLog) << "connecting to ssh-agent socket" << serverAddress;
m_state = Connecting;
m_agentSocket.connectToServer(QString::fromLocal8Bit(serverAddress));
}
void SshAgent::handleConnected()
{
m_state = Connected;
qCDebug(sshLog) << "connection to ssh-agent established";
refreshKeys();
}
void SshAgent::handleDisconnected()
{
qCDebug(sshLog) << "lost connection to ssh-agent";
m_error = tr("Lost connection to ssh-agent for unknown reason.");
setDisconnected();
}
void SshAgent::handleSocketError()
{
qCDebug(sshLog) << "agent socket error" << m_agentSocket.error();
m_error = m_agentSocket.errorString();
setDisconnected();
}
void SshAgent::handleIncomingData()
{
qCDebug(sshLog) << "getting data from agent";
m_incomingData += m_agentSocket.readAll();
while (!hasError() && !m_incomingData.isEmpty()) {
if (m_incomingPacket.size == 0) {
if (m_incomingData.count() < int(sizeof m_incomingPacket.size))
break;
m_incomingPacket.size = fromBigEndian<quint32>(m_incomingData);
m_incomingData.remove(0, sizeof m_incomingPacket.size);
}
const int bytesToTake = qMin<quint32>(m_incomingPacket.size - m_incomingPacket.data.count(),
m_incomingData.count());
m_incomingPacket.data += m_incomingData.left(bytesToTake);
m_incomingData.remove(0, bytesToTake);
if (m_incomingPacket.isComplete())
handleIncomingPacket();
else
break;
}
}
void SshAgent::handleIncomingPacket()
{
try {
qCDebug(sshLog) << "received packet from agent:" << m_incomingPacket.data.toHex();
const char messageType = m_incomingPacket.data.at(0);
switch (messageType) {
case SSH2_AGENT_IDENTITIES_ANSWER:
handleIdentitiesPacket();
break;
case SSH2_AGENT_SIGN_RESPONSE:
handleSignaturePacket();
break;
case SSH_AGENT_FAILURE:
if (m_pendingRequests.isEmpty()) {
qCWarning(sshLog) << "unexpected failure message from agent";
} else {
const Request request = m_pendingRequests.dequeue();
if (request.isSignatureRequest()) {
qCWarning(sshLog) << "agent failed to sign message for key"
<< request.key.toHex();
emit signatureAvailable(request.key, QByteArray(), request.token);
} else {
qCWarning(sshLog) << "agent failed to retrieve key list";
if (m_keys.isEmpty()) {
m_error = tr("ssh-agent failed to retrieve keys.");
setDisconnected();
}
}
}
break;
default:
qCWarning(sshLog) << "unexpected message type from agent:" << messageType;
}
} catch (const SshPacketParseException &) {
qCWarning(sshLog()) << "received malformed packet from agent";
handleProtocolError();
}
m_incomingPacket.invalidate();
m_incomingPacket.size = 0;
m_outgoingPacket.invalidate();
sendNextRequest();
}
void SshAgent::handleIdentitiesPacket()
{
qCDebug(sshLog) << "got keys packet from agent";
if (m_pendingRequests.isEmpty() || !m_pendingRequests.dequeue().isKeysRequest()) {
qCDebug(sshLog) << "packet was not requested";
handleProtocolError();
return;
}
quint32 offset = 1;
const auto keyCount = SshPacketParser::asUint32(m_incomingPacket.data, &offset);
qCDebug(sshLog) << "packet contains" << keyCount << "keys";
QList<QByteArray> newKeys;
for (quint32 i = 0; i < keyCount; ++i) {
const QByteArray key = SshPacketParser::asString(m_incomingPacket.data, &offset);
quint32 keyOffset = 0;
const QByteArray algoName = SshPacketParser::asString(key, &keyOffset);
SshPacketParser::asString(key, &keyOffset); // rest of key blob
SshPacketParser::asString(m_incomingPacket.data, &offset); // comment
qCDebug(sshLog) << "adding key of type" << algoName;
newKeys << key;
}
m_keys = newKeys;
emit keysUpdated();
}
void SshAgent::handleSignaturePacket()
{
qCDebug(sshLog) << "got signature packet from agent";
if (m_pendingRequests.isEmpty()) {
qCDebug(sshLog) << "signature packet was not requested";
handleProtocolError();
return;
}
const Request request = m_pendingRequests.dequeue();
if (!request.isSignatureRequest()) {
qCDebug(sshLog) << "signature packet was not requested";
handleProtocolError();
return;
}
const QByteArray signature = SshPacketParser::asString(m_incomingPacket.data, 1);
qCDebug(sshLog) << "signature for key" << request.key.toHex() << "is" << signature.toHex();
emit signatureAvailable(request.key, signature, request.token);
}
void SshAgent::handleProtocolError()
{
m_error = tr("Protocol error when talking to ssh-agent.");
setDisconnected();
}
void SshAgent::setDisconnected()
{
m_state = Unconnected;
m_agentSocket.disconnect(this);
emit errorOccurred();
}
void SshAgent::sendPacket()
{
const quint32 sizeMsb = qToBigEndian(m_outgoingPacket.size);
m_agentSocket.write(reinterpret_cast<const char *>(&sizeMsb), sizeof sizeMsb);
m_agentSocket.write(m_outgoingPacket.data);
}
} // namespace Internal
} // namespace QSsh

View file

@ -0,0 +1,125 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QByteArray>
#include <QHash>
#include <QList>
#include <QLocalSocket>
#include <QObject>
#include <QPair>
#include <QQueue>
#include <QString>
namespace QSsh {
namespace Internal {
class SshAgent : public QObject
{
Q_OBJECT
public:
enum State { Unconnected, Connecting, Connected, };
~SshAgent();
static State state() { return instance().m_state; }
static bool hasError() { return !instance().m_error.isEmpty(); }
static QString errorString() { return instance().m_error; }
static QList<QByteArray> publicKeys() { return instance().m_keys; }
static void refreshKeys() { instance().refreshKeysImpl(); }
static void storeDataToSign(const QByteArray &key, const QByteArray &data, uint token);
static void removeDataToSign(const QByteArray &key, uint token);
static void requestSignature(const QByteArray &key, uint token) {
instance().requestSignatureImpl(key, token);
}
static SshAgent &instance();
signals:
void errorOccurred();
void keysUpdated();
// Empty signature means signing failure.
void signatureAvailable(const QByteArray &key, const QByteArray &signature, uint token);
private:
struct Request {
Request() { }
Request(const QByteArray &k, const QByteArray &d, uint t)
: key(k), dataToSign(d), token(t) { }
bool isKeysRequest() const { return !isSignatureRequest(); }
bool isSignatureRequest() const { return !key.isEmpty(); }
QByteArray key;
QByteArray dataToSign;
uint token = 0;
};
struct Packet {
bool isComplete() const { return size != 0 && int(size) == data.count(); }
void invalidate() { size = 0; data.clear(); }
quint32 size = 0;
QByteArray data;
};
SshAgent();
void connectToServer();
void refreshKeysImpl();
void requestSignatureImpl(const QByteArray &key, uint token);
void sendNextRequest();
Packet generateKeysPacket();
Packet generateSigPacket(const Request &request);
void handleConnected();
void handleDisconnected();
void handleSocketError();
void handleIncomingData();
void handleIncomingPacket();
void handleIdentitiesPacket();
void handleSignaturePacket();
void handleProtocolError();
void setDisconnected();
void sendPacket();
State m_state = Unconnected;
QString m_error;
QList<QByteArray> m_keys;
QHash<QPair<QByteArray, uint>, QByteArray> m_dataToSign;
QLocalSocket m_agentSocket;
QByteArray m_incomingData;
Packet m_incomingPacket;
Packet m_outgoingPacket;
QQueue<Request> m_pendingRequests;
};
} // namespace Internal
} // namespace QSsh

View file

@ -1,34 +1,40 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef BYTEARRAYCONVERSIONS_P_H
#define BYTEARRAYCONVERSIONS_P_H
#include "sshcapabilities_p.h"
#include "sshexception_p.h"
#include <botan/botan.h>
#include <botan_all.h>
namespace QSsh {
namespace Internal {
@ -43,9 +49,14 @@ inline Botan::byte *convertByteArray(QByteArray &a)
return reinterpret_cast<Botan::byte *>(a.data());
}
inline QByteArray convertByteArray(const Botan::SecureVector<Botan::byte> &v)
inline QByteArray convertByteArray(const Botan::secure_vector<Botan::byte> &v)
{
return QByteArray(reinterpret_cast<const char *>(v.begin()), static_cast<int>(v.size()));
return QByteArray(reinterpret_cast<const char *>(v.data()), static_cast<int>(v.size()));
}
inline QByteArray convertByteArray(const std::vector<uint8_t> &v)
{
return QByteArray(reinterpret_cast<const char *>(v.data()), v.size());
}
inline const char *botanKeyExchangeAlgoName(const QByteArray &rfcAlgoName)
@ -64,8 +75,35 @@ inline const char *botanKeyExchangeAlgoName(const QByteArray &rfcAlgoName)
.arg(QString::fromLatin1(rfcAlgoName)));
}
inline const char *botanCipherAlgoName(const QByteArray &rfcAlgoName)
{
if (rfcAlgoName == SshCapabilities::CryptAlgoAes128Cbc) {
return "CBC(AES-128)";
}
if (rfcAlgoName == SshCapabilities::CryptAlgoAes128Ctr) {
return "CTR(AES-128)";
}
if (rfcAlgoName == SshCapabilities::CryptAlgo3DesCbc) {
return "CBC(TripleDES)";
}
if (rfcAlgoName == SshCapabilities::CryptAlgo3DesCtr) {
return "CTR(TripleDES)";
}
if (rfcAlgoName == SshCapabilities::CryptAlgoAes192Ctr) {
return "CBR(AES-192)";
}
if (rfcAlgoName == SshCapabilities::CryptAlgoAes256Ctr) {
return "CTR(AES-256)";
}
throw SshClientException(SshInternalError, SSH_TR("Unexpected cipher \"%1\"")
.arg(QString::fromLatin1(rfcAlgoName)));
}
inline const char *botanCryptAlgoName(const QByteArray &rfcAlgoName)
{
if (rfcAlgoName == SshCapabilities::CryptAlgoAes128Cbc
|| rfcAlgoName == SshCapabilities::CryptAlgoAes128Ctr) {
return "AES-128";
@ -91,7 +129,7 @@ inline const char *botanEmsaAlgoName(const QByteArray &rfcAlgoName)
if (rfcAlgoName == SshCapabilities::PubKeyRsa)
return "EMSA3(SHA-1)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa256)
return "EMSA1_BSI(SHA-256)";
return "EMSA1(SHA-256)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa384)
return "EMSA1_BSI(SHA-384)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa521)
@ -130,3 +168,5 @@ inline quint32 botanHMacKeyLen(const QByteArray &rfcAlgoName)
} // namespace Internal
} // namespace QSsh
#endif // BYTEARRAYCONVERSIONS_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshcapabilities_p.h"
@ -37,7 +42,7 @@ namespace {
QByteArray listAsByteArray(const QList<QByteArray> &list)
{
QByteArray array;
foreach (const QByteArray &elem, list)
foreach(const QByteArray &elem, list)
array += elem + ',';
if (!array.isEmpty())
array.remove(array.count() - 1, 1);
@ -103,7 +108,7 @@ const QList<QByteArray> SshCapabilities::CompressionAlgorithms
const QByteArray SshCapabilities::SshConnectionService("ssh-connection");
QList<QByteArray> SshCapabilities::commonCapabilities(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities)
const QList<QByteArray> &serverCapabilities, const QByteArray &group)
{
QList<QByteArray> capabilities;
foreach (const QByteArray &myCapability, myCapabilities) {
@ -117,17 +122,19 @@ QList<QByteArray> SshCapabilities::commonCapabilities(const QList<QByteArray> &m
throw SshServerException(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Server and client capabilities do not match.",
QCoreApplication::translate("SshConnection",
"Server and client capabilities don't match. "
"Client list was: %1.\nServer list was %2.")
"Server and client %1 capabilities don't match.\n"
"Client list: %2\n"
"Server list: %3")
.arg(QString::fromLatin1(group))
.arg(QString::fromLocal8Bit(listAsByteArray(myCapabilities).data()))
.arg(QString::fromLocal8Bit(listAsByteArray(serverCapabilities).data())));
}
QByteArray SshCapabilities::findBestMatch(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities)
const QList<QByteArray> &serverCapabilities, const QByteArray &group)
{
return commonCapabilities(myCapabilities, serverCapabilities).first();
return commonCapabilities(myCapabilities, serverCapabilities, group).first();
}
int SshCapabilities::ecdsaIntegerWidthInBytes(const QByteArray &ecdsaAlgo)

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef CAPABILITIES_P_H
#define CAPABILITIES_P_H
#include <QByteArray>
#include <QList>
@ -70,9 +76,9 @@ public:
static const QByteArray SshConnectionService;
static QList<QByteArray> commonCapabilities(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities);
const QList<QByteArray> &serverCapabilities, const QByteArray &group);
static QByteArray findBestMatch(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities);
const QList<QByteArray> &serverCapabilities, const QByteArray &group);
static int ecdsaIntegerWidthInBytes(const QByteArray &ecdsaAlgo);
static QByteArray ecdsaPubKeyAlgoForKeyWidth(int keyWidthInBytes);
@ -81,3 +87,5 @@ public:
} // namespace Internal
} // namespace QSsh
#endif // CAPABILITIES_P_H

View file

@ -1,45 +1,46 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshchannel_p.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include "sshsendfacility_p.h"
#include "sshlogging_p.h"
#include <botan/botan.h>
#include <botan_all.h>
#include <QTimer>
namespace QSsh {
namespace Internal {
// "Payload length" (RFC 4253, 6.1), i.e. minus packet type, channel number
// and length field for string.
const quint32 MinMaxPacketSize = 32768 - sizeof(quint32) - sizeof(quint32) - 1;
const quint32 NoChannel = 0xffffffffu;
AbstractSshChannel::AbstractSshChannel(quint32 channelId,
@ -49,6 +50,7 @@ AbstractSshChannel::AbstractSshChannel(quint32 channelId,
m_localWindowSize(initialWindowSize()), m_remoteWindowSize(0),
m_state(Inactive)
{
m_timeoutTimer.setTimerType(Qt::VeryCoarseTimer);
m_timeoutTimer.setSingleShot(true);
connect(&m_timeoutTimer, &QTimer::timeout, this, &AbstractSshChannel::timeout);
}
@ -102,7 +104,7 @@ quint32 AbstractSshChannel::maxPacketSize()
return 16 * 1024 * 1024;
}
void AbstractSshChannel::handleWindowAdjust(quint32 bytesToAdd)
void AbstractSshChannel::handleWindowAdjust(quint64 bytesToAdd)
{
checkChannelActive();
@ -145,11 +147,6 @@ void AbstractSshChannel::handleOpenSuccess(quint32 remoteChannelId,
m_timeoutTimer.stop();
if (remoteMaxPacketSize < MinMaxPacketSize) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Maximum packet size too low.");
}
qCDebug(sshLog, "Channel opened. remote channel id: %u, remote window size: %u, "
"remote max packet size: %u",
remoteChannelId, remoteWindowSize, remoteMaxPacketSize);
@ -264,7 +261,7 @@ void AbstractSshChannel::closeChannel()
}
}
void AbstractSshChannel::checkChannelActive()
void AbstractSshChannel::checkChannelActive() const
{
if (channelState() == Inactive || channelState() == Closed)
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCHANNEL_P_H
#define SSHCHANNEL_P_H
#include <QByteArray>
#include <QObject>
@ -55,7 +61,7 @@ public:
void handleOpenSuccess(quint32 remoteChannelId, quint32 remoteWindowSize,
quint32 remoteMaxPacketSize);
void handleOpenFailure(const QString &reason);
void handleWindowAdjust(quint32 bytesToAdd);
void handleWindowAdjust(quint64 bytesToAdd);
void handleChannelEof();
void handleChannelClose();
void handleChannelData(const QByteArray &data);
@ -85,7 +91,7 @@ protected:
static quint32 maxPacketSize();
quint32 maxDataSize() const;
void checkChannelActive();
void checkChannelActive() const;
SshSendFacility &m_sendFacility;
QTimer m_timeoutTimer;
@ -115,3 +121,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SSHCHANNEL_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshchannelmanager_p.h"
@ -38,6 +43,8 @@
#include "sshsendfacility_p.h"
#include "sshtcpipforwardserver.h"
#include "sshtcpipforwardserver_p.h"
#include "sshx11channel_p.h"
#include "sshx11inforetriever_p.h"
#include <QList>
@ -58,52 +65,21 @@ void SshChannelManager::handleChannelRequest(const SshIncomingPacket &packet)
void SshChannelManager::handleChannelOpen(const SshIncomingPacket &packet)
{
SshChannelOpen channelOpen = packet.extractChannelOpen();
SshTcpIpForwardServer::Ptr server;
foreach (const SshTcpIpForwardServer::Ptr &candidate, m_listeningForwardServers) {
if (candidate->port() == channelOpen.remotePort
&& candidate->bindAddress().toUtf8() == channelOpen.remoteAddress) {
server = candidate;
break;
}
};
if (server.isNull()) {
// Apparently the server knows a remoteAddress we are not aware of. There are plenty of ways
// to make that happen: /etc/hosts on the server, different writings for localhost,
// different DNS servers, ...
// Rather than trying to figure that out, we just use the first listening forwarder with the
// same port.
foreach (const SshTcpIpForwardServer::Ptr &candidate, m_listeningForwardServers) {
if (candidate->port() == channelOpen.remotePort) {
server = candidate;
break;
}
};
}
if (server.isNull()) {
SshOpenFailureType reason = (channelOpen.remotePort == 0) ?
SSH_OPEN_UNKNOWN_CHANNEL_TYPE : SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
try {
m_sendFacility.sendChannelOpenFailurePacket(channelOpen.remoteChannel, reason,
QByteArray());
} catch (const std::exception &e) {
qCWarning(sshLog, "Botan error: %s", e.what());
}
const SshChannelOpenGeneric channelOpen = packet.extractChannelOpen();
if (channelOpen.channelType == SshIncomingPacket::ForwardedTcpIpType) {
handleChannelOpenForwardedTcpIp(channelOpen);
return;
}
SshForwardedTcpIpTunnel::Ptr tunnel(new SshForwardedTcpIpTunnel(m_nextLocalChannelId++,
m_sendFacility));
tunnel->d->handleOpenSuccess(channelOpen.remoteChannel, channelOpen.remoteWindowSize,
channelOpen.remoteMaxPacketSize);
tunnel->open(QIODevice::ReadWrite);
server->setNewConnection(tunnel);
insertChannel(tunnel->d, tunnel);
if (channelOpen.channelType == "x11") {
handleChannelOpenX11(channelOpen);
return;
}
try {
m_sendFacility.sendChannelOpenFailurePacket(channelOpen.commonData.remoteChannel,
SSH_OPEN_UNKNOWN_CHANNEL_TYPE, QByteArray());
} catch (const std::exception &e) {
qCWarning(sshLog, "Botan error: %s", e.what());
}
}
void SshChannelManager::handleChannelOpenFailure(const SshIncomingPacket &packet)
@ -114,7 +90,7 @@ void SshChannelManager::handleChannelOpenFailure(const SshIncomingPacket &packet
it.value()->handleOpenFailure(failure.reasonString);
} catch (const SshServerException &e) {
removeChannel(it);
throw e;
throw;
}
removeChannel(it);
}
@ -223,13 +199,50 @@ AbstractSshChannel *SshChannelManager::lookupChannel(quint32 channelId,
bool allowNotFound)
{
ChannelIterator it = lookupChannelAsIterator(channelId, allowNotFound);
return it == m_channels.end() ? 0 : it.value();
return it == m_channels.end() ? nullptr : it.value();
}
QSsh::SshRemoteProcess::Ptr SshChannelManager::createRemoteProcess(const QByteArray &command)
{
SshRemoteProcess::Ptr proc(new SshRemoteProcess(command, m_nextLocalChannelId++, m_sendFacility));
insertChannel(proc->d, proc);
connect(proc->d, &SshRemoteProcessPrivate::destroyed, this, [this] {
m_x11ForwardingRequests.removeOne(static_cast<SshRemoteProcessPrivate *>(sender()));
});
connect(proc->d, &SshRemoteProcessPrivate::x11ForwardingRequested, this,
[this, proc = proc->d](const QString &displayName) {
if (!x11DisplayName().isEmpty()) {
if (x11DisplayName() != displayName) {
proc->failToStart(tr("Cannot forward to display %1 on SSH connection that is "
"already forwarding to display %2.")
.arg(displayName, x11DisplayName()));
return;
}
if (!m_x11DisplayInfo.cookie.isEmpty())
proc->startProcess(m_x11DisplayInfo);
else
m_x11ForwardingRequests << proc;
return;
}
m_x11DisplayInfo.displayName = displayName;
m_x11ForwardingRequests << proc;
auto * const x11InfoRetriever = new SshX11InfoRetriever(displayName, this);
const auto failureHandler = [this](const QString &errorMessage) {
for (SshRemoteProcessPrivate * const proc : qAsConst(m_x11ForwardingRequests))
proc->failToStart(errorMessage);
m_x11ForwardingRequests.clear();
};
connect(x11InfoRetriever, &SshX11InfoRetriever::failure, this, failureHandler);
const auto successHandler = [this](const X11DisplayInfo &displayInfo) {
m_x11DisplayInfo = displayInfo;
for (SshRemoteProcessPrivate * const proc : qAsConst(m_x11ForwardingRequests))
proc->startProcess(displayInfo);
m_x11ForwardingRequests.clear();
};
connect(x11InfoRetriever, &SshX11InfoRetriever::success, this, successHandler);
qCDebug(sshLog) << "starting x11 info retriever";
x11InfoRetriever->start();
});
return proc;
}
@ -266,7 +279,7 @@ SshTcpIpForwardServer::Ptr SshChannelManager::createForwardServer(const QString
switch (state) {
case SshTcpIpForwardServer::Closing:
m_listeningForwardServers.removeOne(server);
// fall through
Q_FALLTHROUGH();
case SshTcpIpForwardServer::Initializing:
m_waitingForwardServers.append(server);
break;
@ -286,6 +299,77 @@ void SshChannelManager::insertChannel(AbstractSshChannel *priv,
m_sessions.insert(priv, pub);
}
void SshChannelManager::handleChannelOpenForwardedTcpIp(
const SshChannelOpenGeneric &channelOpenGeneric)
{
const SshChannelOpenForwardedTcpIp channelOpen
= SshIncomingPacket::extractChannelOpenForwardedTcpIp(channelOpenGeneric);
SshTcpIpForwardServer::Ptr server;
foreach (const SshTcpIpForwardServer::Ptr &candidate, m_listeningForwardServers) {
if (candidate->port() == channelOpen.remotePort
&& candidate->bindAddress().toUtf8() == channelOpen.remoteAddress) {
server = candidate;
break;
}
};
if (server.isNull()) {
// Apparently the server knows a remoteAddress we are not aware of. There are plenty of ways
// to make that happen: /etc/hosts on the server, different writings for localhost,
// different DNS servers, ...
// Rather than trying to figure that out, we just use the first listening forwarder with the
// same port.
foreach (const SshTcpIpForwardServer::Ptr &candidate, m_listeningForwardServers) {
if (candidate->port() == channelOpen.remotePort) {
server = candidate;
break;
}
};
}
if (server.isNull()) {
try {
m_sendFacility.sendChannelOpenFailurePacket(channelOpen.common.remoteChannel,
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
QByteArray());
} catch (const std::exception &e) {
qCWarning(sshLog, "Botan error: %s", e.what());
}
return;
}
SshForwardedTcpIpTunnel::Ptr tunnel(new SshForwardedTcpIpTunnel(m_nextLocalChannelId++,
m_sendFacility));
tunnel->d->handleOpenSuccess(channelOpen.common.remoteChannel,
channelOpen.common.remoteWindowSize,
channelOpen.common.remoteMaxPacketSize);
tunnel->open(QIODevice::ReadWrite);
server->setNewConnection(tunnel);
insertChannel(tunnel->d, tunnel);
}
void SshChannelManager::handleChannelOpenX11(const SshChannelOpenGeneric &channelOpenGeneric)
{
qCDebug(sshLog) << "incoming X11 channel open request";
const SshChannelOpenX11 channelOpen
= SshIncomingPacket::extractChannelOpenX11(channelOpenGeneric);
if (m_x11DisplayInfo.cookie.isEmpty()) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server attempted to open an unrequested X11 channel.");
}
SshX11Channel * const x11Channel = new SshX11Channel(m_x11DisplayInfo,
m_nextLocalChannelId++,
m_sendFacility);
x11Channel->setParent(this);
x11Channel->handleOpenSuccess(channelOpen.common.remoteChannel,
channelOpen.common.remoteWindowSize,
channelOpen.common.remoteMaxPacketSize);
insertChannel(x11Channel, QSharedPointer<QObject>());
}
int SshChannelManager::closeAllChannels(CloseAllMode mode)
{
int count = 0;

View file

@ -1,29 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCHANNELLAYER_P_H
#define SSHCHANNELLAYER_P_H
#include "sshx11displayinfo_p.h"
#include <QHash>
#include <QObject>
@ -38,8 +46,10 @@ class SshTcpIpForwardServer;
namespace Internal {
class AbstractSshChannel;
struct SshChannelOpenGeneric;
class SshIncomingPacket;
class SshSendFacility;
class SshRemoteProcessPrivate;
class SshChannelManager : public QObject
{
@ -58,6 +68,7 @@ public:
int channelCount() const;
enum CloseAllMode { CloseAllRegular, CloseAllAndReset };
int closeAllChannels(CloseAllMode mode);
QString x11DisplayName() const { return m_x11DisplayInfo.displayName; }
void handleChannelRequest(const SshIncomingPacket &packet);
void handleChannelOpen(const SshIncomingPacket &packet);
@ -87,13 +98,20 @@ private:
void insertChannel(AbstractSshChannel *priv,
const QSharedPointer<QObject> &pub);
void handleChannelOpenForwardedTcpIp(const SshChannelOpenGeneric &channelOpenGeneric);
void handleChannelOpenX11(const SshChannelOpenGeneric &channelOpenGeneric);
SshSendFacility &m_sendFacility;
QHash<quint32, AbstractSshChannel *> m_channels;
QHash<AbstractSshChannel *, QSharedPointer<QObject> > m_sessions;
quint32 m_nextLocalChannelId;
QList<QSharedPointer<SshTcpIpForwardServer>> m_waitingForwardServers;
QList<QSharedPointer<SshTcpIpForwardServer>> m_listeningForwardServers;
QList<SshRemoteProcessPrivate *> m_x11ForwardingRequests;
X11DisplayInfo m_x11DisplayInfo;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHCHANNELLAYER_P_H

View file

@ -1,44 +1,47 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshconnection.h"
#include "sshconnection_p.h"
#include "sftpchannel.h"
#include "sshagent_p.h"
#include "sshcapabilities_p.h"
#include "sshchannelmanager_p.h"
#include "sshcryptofacility_p.h"
#include "sshdirecttcpiptunnel.h"
#include "sshtcpipforwardserver.h"
#include "sshexception_p.h"
#include "sshinit_p.h"
#include "sshkeyexchange_p.h"
#include "sshlogging_p.h"
#include "sshremoteprocess.h"
#include <botan/botan.h>
#include "sshlogging_p.h"
#include <QFile>
#include <QMutex>
@ -47,36 +50,28 @@
#include <QRegExp>
#include <QTcpSocket>
/*!
\class QSsh::SshConnection
\brief The SshConnection class provides an SSH connection, implementing
protocol version 2.0.
It can spawn channels for remote execution and SFTP operations (version 3).
It operates asynchronously (non-blocking) and is not thread-safe.
*/
namespace QSsh {
namespace {
const QByteArray ClientId("SSH-2.0-QtCreator\r\n");
}
SshConnectionParameters::SshConnectionParameters() :
timeout(0), authenticationType(AuthenticationTypePublicKey), port(0),
timeout(0), authenticationType(AuthenticationTypePublicKey),
hostKeyCheckingMode(SshHostKeyCheckingNone)
{
url.setPort(0);
options |= SshIgnoreDefaultProxy;
options |= SshEnableStrictConformanceChecks;
hostKeyDatabase = SshHostKeyDatabasePtr(new SshHostKeyDatabase);
}
static inline bool equals(const SshConnectionParameters &p1, const SshConnectionParameters &p2)
{
return p1.host == p2.host && p1.userName == p2.userName
return p1.url == p2.url
&& p1.authenticationType == p2.authenticationType
&& (p1.authenticationType == SshConnectionParameters::AuthenticationTypePassword ?
p1.password == p2.password : p1.privateKeyFile == p2.privateKeyFile)
&& p1.privateKeyFile == p2.privateKeyFile
&& p1.hostKeyCheckingMode == p2.hostKeyCheckingMode
&& p1.timeout == p2.timeout && p1.port == p2.port;
&& p1.timeout == p2.timeout;
}
bool operator==(const SshConnectionParameters &p1, const SshConnectionParameters &p2)
@ -89,14 +84,14 @@ bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters
return !equals(p1, p2);
}
SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject *parent)
: QObject(parent)
{
Internal::initSsh();
qRegisterMetaType<QSsh::SshError>("QSsh::SshError");
qRegisterMetaType<QSsh::SftpJobId>("QSsh::SftpJobId");
qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo");
qRegisterMetaType<QSsh::SftpError>("QSsh::SftpError");
qRegisterMetaType<QSsh::SftpError>("SftpError");
qRegisterMetaType<QList <QSsh::SftpFileInfo> >("QList<QSsh::SftpFileInfo>");
d = new Internal::SshConnectionPrivate(this, serverInfo);
@ -110,6 +105,11 @@ SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject
&SshConnection::error, Qt::QueuedConnection);
}
const QByteArray &SshConnection::hostKeyFingerprint() const
{
return d->hostKeyFingerprint();
}
void SshConnection::connectToHost()
{
d->connectToHost();
@ -210,6 +210,11 @@ int SshConnection::channelCount() const
return d->m_channelManager->channelCount();
}
QString SshConnection::x11DisplayName() const
{
return d->m_channelManager->x11DisplayName();
}
namespace Internal {
SshConnectionPrivate::SshConnectionPrivate(SshConnection *conn,
@ -221,10 +226,17 @@ SshConnectionPrivate::SshConnectionPrivate(SshConnection *conn,
m_conn(conn)
{
setupPacketHandlers();
if (m_connParams.options & SshLowDelaySocket) {
m_socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
}
m_socket->setProxy((m_connParams.options & SshIgnoreDefaultProxy)
? QNetworkProxy::NoProxy : QNetworkProxy::DefaultProxy);
m_timeoutTimer.setTimerType(Qt::VeryCoarseTimer);
m_timeoutTimer.setSingleShot(true);
m_timeoutTimer.setInterval(m_connParams.timeout * 1000);
m_keepAliveTimer.setTimerType(Qt::VeryCoarseTimer);
m_keepAliveTimer.setSingleShot(true);
m_keepAliveTimer.setInterval(10000);
connect(m_channelManager, &SshChannelManager::timeout,
@ -270,6 +282,7 @@ void SshConnectionPrivate::setupPacketHandlers()
setupPacketHandler(SSH_MSG_USERAUTH_INFO_REQUEST, authReqList,
&This::handleUserAuthInfoRequestPacket);
}
setupPacketHandler(SSH_MSG_USERAUTH_PK_OK, authReqList, &This::handleUserAuthKeyOkPacket);
const StateList connectedList
= StateList() << ConnectionEstablished;
@ -299,7 +312,7 @@ void SshConnectionPrivate::setupPacketHandlers()
setupPacketHandler(SSH_MSG_CHANNEL_CLOSE, connectedOrClosedList,
&This::handleChannelClose);
setupPacketHandler(SSH_MSG_DISCONNECT, StateList() << SocketConnected
setupPacketHandler(SSH_MSG_DISCONNECT, StateList() << SocketConnected << WaitingForAgentKeys
<< UserAuthServiceRequested << UserAuthRequested
<< ConnectionEstablished, &This::handleDisconnect);
@ -346,7 +359,7 @@ void SshConnectionPrivate::handleIncomingData()
e.errorString);
} catch (const std::exception &e) {
closeConnection(SSH_DISCONNECT_BY_APPLICATION, SshInternalError, "",
tr("Botan library exception: %1").arg(QString::fromLatin1(e.what())));
tr("Botan library exception: %1").arg(QString::fromLocal8Bit(e.what())));
}
}
@ -369,8 +382,8 @@ void SshConnectionPrivate::handleServerId()
if (newLinePos > 255 - 1) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Identification string too long.",
tr("Server identification string is %n characters long, but the maximum "
"allowed length is 255.", 0, newLinePos + 1));
tr("Server identification string is %1 characters long, but the maximum "
"allowed length is 255.").arg(newLinePos + 1));
}
const bool hasCarriageReturn = m_incomingData.at(newLinePos - 1) == '\r';
@ -388,7 +401,7 @@ void SshConnectionPrivate::handleServerId()
// "printable US-ASCII characters, with the exception of whitespace characters
// and the minus sign"
QString legalString = QLatin1String("[]!\"#$!&'()*+,./0-9:;<=>?@A-Z[\\\\^_`a-z{|}~]+");
const QRegExp versionIdpattern(QString::fromLatin1("SSH-(%1)-%1(?: .+)?").arg(legalString));
const QRegExp versionIdpattern(QString::fromLatin1("SSH-(%1)-%1(?: .+)?.*").arg(legalString));
if (!versionIdpattern.exactMatch(QString::fromLatin1(m_serverId))) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Identification string is invalid.",
@ -403,18 +416,25 @@ void SshConnectionPrivate::handleServerId()
.arg(serverProtoVersion));
}
if (m_connParams.options & SshEnableStrictConformanceChecks) {
if (serverProtoVersion == QLatin1String("2.0") && !hasCarriageReturn) {
if (serverProtoVersion == QLatin1String("2.0") && !hasCarriageReturn) {
if (m_connParams.options & SshEnableStrictConformanceChecks) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Identification string is invalid.",
tr("Server identification string is invalid (missing carriage return)."));
} else {
qCWarning(Internal::sshLog, "Server identification string is invalid (missing carriage return).");
}
}
if (serverProtoVersion == QLatin1String("1.99") && m_serverHasSentDataBeforeId) {
if (serverProtoVersion == QLatin1String("1.99") && m_serverHasSentDataBeforeId) {
if (m_connParams.options & SshEnableStrictConformanceChecks) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"No extra data preceding identification string allowed for 1.99.",
tr("Server reports protocol version 1.99, but sends data "
"before the identification string, which is not allowed."));
"before the identification string, which is not allowed."));
} else {
qCWarning(Internal::sshLog, "Server reports protocol version 1.99, but sends data "
"before the identification string, which is not allowed.");
}
}
@ -474,8 +494,9 @@ void SshConnectionPrivate::handleKeyExchangeInitPacket()
// If the server sends a guessed packet, the guess must be wrong,
// because the algorithms we support require us to initiate the
// key exchange.
if (m_keyExchange->sendDhInitPacket(m_incomingPacket))
if (m_keyExchange->sendDhInitPacket(m_incomingPacket)) {
m_ignoreNextPacket = true;
}
m_keyExchangeState = DhInitSent;
}
@ -490,6 +511,7 @@ void SshConnectionPrivate::handleKeyExchangeReplyPacket()
m_keyExchange->sendNewKeysPacket(m_incomingPacket,
ClientId.left(ClientId.size() - 2));
m_hostFingerprint = m_keyExchange->hostKeyFingerprint();
m_sendFacility.recreateKeys(*m_keyExchange);
m_keyExchangeState = NewKeysSent;
}
@ -517,18 +539,28 @@ void SshConnectionPrivate::handleServiceAcceptPacket()
switch (m_connParams.authenticationType) {
case SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods:
m_triedAllPasswordBasedMethods = false;
// Fall-through.
Q_FALLTHROUGH();
case SshConnectionParameters::AuthenticationTypePassword:
m_sendFacility.sendUserAuthByPasswordRequestPacket(m_connParams.userName.toUtf8(),
SshCapabilities::SshConnectionService, m_connParams.password.toUtf8());
m_sendFacility.sendUserAuthByPasswordRequestPacket(m_connParams.userName().toUtf8(),
SshCapabilities::SshConnectionService, m_connParams.password().toUtf8());
break;
case SshConnectionParameters::AuthenticationTypeKeyboardInteractive:
m_sendFacility.sendUserAuthByKeyboardInteractiveRequestPacket(m_connParams.userName.toUtf8(),
m_sendFacility.sendUserAuthByKeyboardInteractiveRequestPacket(m_connParams.userName().toUtf8(),
SshCapabilities::SshConnectionService);
break;
case SshConnectionParameters::AuthenticationTypePublicKey:
m_sendFacility.sendUserAuthByPublicKeyRequestPacket(m_connParams.userName.toUtf8(),
SshCapabilities::SshConnectionService);
authenticateWithPublicKey();
break;
case SshConnectionParameters::AuthenticationTypeAgent:
if (SshAgent::publicKeys().isEmpty()) {
if (m_agentKeysUpToDate)
throw SshClientException(SshAuthenticationError, tr("ssh-agent has no keys."));
qCDebug(sshLog) << "agent has no keys yet, waiting";
m_state = WaitingForAgentKeys;
return;
} else {
tryAllAgentKeys();
}
break;
}
m_state = UserAuthRequested;
@ -563,7 +595,7 @@ void SshConnectionPrivate::handleUserAuthInfoRequestPacket()
// Not very interactive, admittedly, but we don't want to be for now.
for (int i = 0; i < requestPacket.prompts.count(); ++i)
responses << m_connParams.password;
responses << m_connParams.password();
m_sendFacility.sendUserAuthInfoResponsePacket(responses);
}
@ -596,22 +628,69 @@ void SshConnectionPrivate::handleUserAuthSuccessPacket()
void SshConnectionPrivate::handleUserAuthFailurePacket()
{
if (!m_pendingKeyChecks.isEmpty()) {
const QByteArray key = m_pendingKeyChecks.dequeue();
SshAgent::removeDataToSign(key, tokenForAgent());
qCDebug(sshLog) << "server rejected one of the keys supplied by the agent,"
<< m_pendingKeyChecks.count() << "keys remaining";
if (m_pendingKeyChecks.isEmpty() && m_agentKeyToUse.isEmpty()) {
throw SshClientException(SshAuthenticationError, tr("The server rejected all keys "
"known to the ssh-agent."));
}
return;
}
// TODO: Evaluate "authentications that can continue" field and act on it.
if (m_connParams.authenticationType
== SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods
&& !m_triedAllPasswordBasedMethods) {
m_triedAllPasswordBasedMethods = true;
m_sendFacility.sendUserAuthByKeyboardInteractiveRequestPacket(
m_connParams.userName.toUtf8(),
m_connParams.userName().toUtf8(),
SshCapabilities::SshConnectionService);
return;
}
m_timeoutTimer.stop();
const QString errorMsg = m_connParams.authenticationType == SshConnectionParameters::AuthenticationTypePublicKey
? tr("Server rejected key.") : tr("Server rejected password.");
QString errorMsg;
switch (m_connParams.authenticationType) {
case SshConnectionParameters::AuthenticationTypePublicKey:
case SshConnectionParameters::AuthenticationTypeAgent:
errorMsg = tr("Server rejected key.");
break;
default:
errorMsg = tr("Server rejected password.");
break;
}
throw SshClientException(SshAuthenticationError, errorMsg);
}
void SshConnectionPrivate::handleUserAuthKeyOkPacket()
{
const SshUserAuthPkOkPacket &msg = m_incomingPacket.extractUserAuthPkOk();
qCDebug(sshLog) << "server accepted key of type" << msg.algoName;
if (m_pendingKeyChecks.isEmpty()) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected packet",
tr("Server sent unexpected SSH_MSG_USERAUTH_PK_OK packet."));
}
const QByteArray key = m_pendingKeyChecks.dequeue();
if (key != msg.keyBlob) {
// The server must answer the requests in the order we sent them.
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected packet content",
tr("Server sent unexpected key in SSH_MSG_USERAUTH_PK_OK packet."));
}
const uint token = tokenForAgent();
if (!m_agentKeyToUse.isEmpty()) {
qCDebug(sshLog) << "another key has already been accepted, ignoring this one";
SshAgent::removeDataToSign(key, token);
return;
}
m_agentKeyToUse = key;
qCDebug(sshLog) << "requesting signature from agent";
SshAgent::requestSignature(key, token);
}
void SshConnectionPrivate::handleDebugPacket()
{
const SshDebug &msg = m_incomingPacket.extractDebug();
@ -710,6 +789,11 @@ void SshConnectionPrivate::sendData(const QByteArray &data)
m_socket->write(data);
}
uint SshConnectionPrivate::tokenForAgent() const
{
return qHash(m_sendFacility.sessionId());
}
void SshConnectionPrivate::handleSocketDisconnected()
{
closeConnection(SSH_DISCONNECT_CONNECTION_LOST, SshClosedByServerError,
@ -727,8 +811,10 @@ void SshConnectionPrivate::handleSocketError()
void SshConnectionPrivate::handleTimeout()
{
closeConnection(SSH_DISCONNECT_BY_APPLICATION, SshTimeoutError, "",
tr("Timeout waiting for reply from server."));
const QString errorMessage = m_state == WaitingForAgentKeys
? tr("Timeout waiting for keys from ssh-agent.")
: tr("Timeout waiting for reply from server.");
closeConnection(SSH_DISCONNECT_BY_APPLICATION, SshTimeoutError, "", errorMessage);
}
void SshConnectionPrivate::sendKeepAlivePacket()
@ -745,6 +831,66 @@ void SshConnectionPrivate::sendKeepAlivePacket()
m_timeoutTimer.start();
}
void SshConnectionPrivate::handleAgentKeysUpdated()
{
m_agentKeysUpToDate = true;
if (m_state == WaitingForAgentKeys) {
m_state = UserAuthRequested;
tryAllAgentKeys();
}
}
void SshConnectionPrivate::handleSignatureFromAgent(const QByteArray &key,
const QByteArray &signature, uint token)
{
if (token != tokenForAgent()) {
qCDebug(sshLog) << "signature is for different connection, ignoring";
return;
}
QSSH_ASSERT(key == m_agentKeyToUse);
m_agentSignature = signature;
authenticateWithPublicKey();
}
void SshConnectionPrivate::tryAllAgentKeys()
{
const QList<QByteArray> &keys = SshAgent::publicKeys();
if (keys.isEmpty())
throw SshClientException(SshAuthenticationError, tr("ssh-agent has no keys."));
qCDebug(sshLog) << "trying authentication with" << keys.count()
<< "public keys received from agent";
foreach (const QByteArray &key, keys) {
m_sendFacility.sendQueryPublicKeyPacket(m_connParams.userName().toUtf8(),
SshCapabilities::SshConnectionService, key);
m_pendingKeyChecks.enqueue(key);
}
}
void SshConnectionPrivate::authenticateWithPublicKey()
{
qCDebug(sshLog) << "sending actual authentication request";
QByteArray key;
QByteArray signature;
if (m_connParams.authenticationType == SshConnectionParameters::AuthenticationTypeAgent) {
// Agent is not needed anymore after this point.
disconnect(&SshAgent::instance(), nullptr, this, nullptr);
key = m_agentKeyToUse;
signature = m_agentSignature;
}
m_sendFacility.sendUserAuthByPublicKeyRequestPacket(m_connParams.userName().toUtf8(),
SshCapabilities::SshConnectionService, key, signature);
}
void SshConnectionPrivate::setAgentError()
{
m_error = SshAgentError;
m_errorString = SshAgent::errorString();
emit error(m_error);
}
void SshConnectionPrivate::connectToHost()
{
QSSH_ASSERT_AND_RETURN(m_state == SocketUnconnected);
@ -757,31 +903,52 @@ void SshConnectionPrivate::connectToHost()
m_errorString.clear();
m_serverId.clear();
m_serverHasSentDataBeforeId = false;
m_agentSignature.clear();
m_agentKeysUpToDate = false;
m_pendingKeyChecks.clear();
m_agentKeyToUse.clear();
try {
if (m_connParams.authenticationType == SshConnectionParameters::AuthenticationTypePublicKey)
switch (m_connParams.authenticationType) {
case SshConnectionParameters::AuthenticationTypePublicKey:
try {
createPrivateKey();
} catch (const SshClientException &ex) {
m_error = ex.error;
m_errorString = ex.errorString;
emit error(m_error);
return;
break;
} catch (const SshClientException &ex) {
m_error = ex.error;
m_errorString = ex.errorString;
emit error(m_error);
return;
}
case SshConnectionParameters::AuthenticationTypeAgent:
if (SshAgent::hasError()) {
setAgentError();
return;
}
connect(&SshAgent::instance(), &SshAgent::errorOccurred,
this, &SshConnectionPrivate::setAgentError);
connect(&SshAgent::instance(), &SshAgent::keysUpdated,
this, &SshConnectionPrivate::handleAgentKeysUpdated);
SshAgent::refreshKeys();
connect(&SshAgent::instance(), &SshAgent::signatureAvailable,
this, &SshConnectionPrivate::handleSignatureFromAgent);
break;
default:
break;
}
connect(m_socket, &QAbstractSocket::connected,
this, &SshConnectionPrivate::handleSocketConnected);
connect(m_socket, &QIODevice::readyRead,
this, &SshConnectionPrivate::handleIncomingData);
connect(m_socket,
static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
this, &SshConnectionPrivate::handleSocketError);
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(handleSocketError()));
connect(m_socket, &QAbstractSocket::disconnected,
this, &SshConnectionPrivate::handleSocketDisconnected);
connect(&m_timeoutTimer, &QTimer::timeout, this, &SshConnectionPrivate::handleTimeout);
m_state = SocketConnecting;
m_keyExchangeState = NoKeyExchange;
m_timeoutTimer.start();
m_socket->connectToHost(m_connParams.host, m_connParams.port);
m_socket->connectToHost(m_connParams.host(), m_connParams.port());
}
void SshConnectionPrivate::closeConnection(SshErrorCode sshError,
@ -795,13 +962,17 @@ void SshConnectionPrivate::closeConnection(SshErrorCode sshError,
m_error = userError;
m_errorString = userErrorString;
m_timeoutTimer.stop();
disconnect(m_socket, 0, this, 0);
disconnect(&m_timeoutTimer, 0, this, 0);
disconnect(m_socket, nullptr, this, nullptr);
disconnect(&m_timeoutTimer, nullptr, this, nullptr);
m_keepAliveTimer.stop();
disconnect(&m_keepAliveTimer, 0, this, 0);
disconnect(&m_keepAliveTimer, nullptr, this, nullptr);
try {
m_channelManager->closeAllChannels(SshChannelManager::CloseAllAndReset);
m_sendFacility.sendDisconnectPacket(sshError, serverErrorString);
// Crypto initialization failed
if (m_sendFacility.encrypterIsValid()) {
m_sendFacility.sendDisconnectPacket(sshError, serverErrorString);
}
} catch (...) {} // Nothing sensible to be done here.
if (m_error != SshNoError)
emit error(userError);
@ -823,7 +994,13 @@ void SshConnectionPrivate::createPrivateKey()
if (m_connParams.privateKeyFile.isEmpty())
throw SshClientException(SshKeyFileError, tr("No private key file given."));
QFile keyFile(m_connParams.privateKeyFile);
// if (!keyFile.open(QIODevice::ReadOnly)) {
// throw SshClientException(SshKeyFileError,
// tr("Private key file error: %1").arg(keyFile.errorString()));
// }
// m_sendFacility.createAuthenticationKey(keyFile.readAll());
// Patch supporting storing key in pass field
if (keyFile.open(QIODevice::ReadOnly)) {
m_sendFacility.createAuthenticationKey(keyFile.readAll());
}

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCONNECTION_H
#define SSHCONNECTION_H
#include "ssherrors.h"
#include "sshhostkeydatabase.h"
@ -32,10 +38,12 @@
#include <QByteArray>
#include <QFlags>
#include <QMetaType>
#include <QObject>
#include <QSharedPointer>
#include <QString>
#include <QHostAddress>
#include <QUrl>
namespace QSsh {
class SftpChannel;
@ -43,51 +51,134 @@ class SshDirectTcpIpTunnel;
class SshRemoteProcess;
class SshTcpIpForwardServer;
namespace Internal { class SshConnectionPrivate; }
namespace Internal {
class SshConnectionPrivate;
} // namespace Internal
/*!
* \brief Flags that control various general behavior
*/
enum SshConnectionOption {
/// Set this to ignore the system defined proxy
SshIgnoreDefaultProxy = 0x1,
SshEnableStrictConformanceChecks = 0x2
/// Fail instead of warn if the remote host violates the standard
SshEnableStrictConformanceChecks = 0x2,
/// Set the QAbstractSocket::LowDelayOption, which is the same as TCP_NODELAY
SshLowDelaySocket = 0x4
};
Q_DECLARE_FLAGS(SshConnectionOptions, SshConnectionOption)
/*!
* \brief How strict to be when checking the remote key
*/
enum SshHostKeyCheckingMode {
/// Ignore the remote key
SshHostKeyCheckingNone,
/// Fail connection if either there is no key stored for this host or the key is not the same as earlier
SshHostKeyCheckingStrict,
/// Allow connecting if there is no stored key for the host, but fail if the key has changed
SshHostKeyCheckingAllowNoMatch,
/// Continue connection if the key doesn't match the stored key for the host
SshHostKeyCheckingAllowMismatch
};
/*!
* \brief Class to use to specify parameters used during connection.
*/
class QSSH_EXPORT SshConnectionParameters
{
public:
/*!
* \brief What kinds of authentication to attempt
*/
enum AuthenticationType {
AuthenticationTypePassword,
AuthenticationTypePublicKey,
AuthenticationTypePassword, ///< Only attempt to connect using the password set with setPassword().
AuthenticationTypePublicKey, ///< Only attempt to authenticate with public key
/// Only attempt keyboard interactive authentication.
/// For now this only changes what to send to the server,
/// we will still just try to use the password set here.
AuthenticationTypeKeyboardInteractive,
// Some servers disable "password", others disable "keyboard-interactive".
AuthenticationTypeTryAllPasswordBasedMethods
/// Any method using the password set with setPassword().
/// Some servers disable \a "password", others disable \a "keyboard-interactive"
AuthenticationTypeTryAllPasswordBasedMethods,
/// ssh-agent authentication only
AuthenticationTypeAgent,
};
SshConnectionParameters();
QString host;
QString userName;
QString password;
/*!
* \brief Returns the hostname or IP set with setHost()
*/
QString host() const { return url.host(); }
/*!
* \brief Returns the port set with setPort()
*/
int port() const { return url.port(); }
/*!
* \brief Returns the username set with setUsername()
* \return
*/
QString userName() const { return url.userName(); }
/*!
* \brief Returns the password set with setPassword()
*/
QString password() const { return url.password(); }
/*!
* \brief Sets the hostname or IP to connect to
* \param host The remote host
*/
void setHost(const QString &host) { url.setHost(host); }
/*!
* \brief Sets the remote port to use
* \param port
*/
void setPort(int port) { url.setPort(port); }
/*!
* \brief Sets the username to use
* \param name Username
*/
void setUserName(const QString &name) { url.setUserName(name); }
/*!
* \brief Sets the password to attempt to use
* \param password
*/
void setPassword(const QString &password) { url.setPassword(password); }
QUrl url;
QString privateKeyFile;
int timeout; // In seconds.
AuthenticationType authenticationType;
quint16 port;
SshConnectionOptions options;
SshHostKeyCheckingMode hostKeyCheckingMode;
SshHostKeyDatabasePtr hostKeyDatabase;
};
/// @cond
QSSH_EXPORT bool operator==(const SshConnectionParameters &p1, const SshConnectionParameters &p2);
QSSH_EXPORT bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters &p2);
/// @endcond
/*!
* \brief Network connection info.
*/
class QSSH_EXPORT SshConnectionInfo
{
public:
@ -101,25 +192,61 @@ public:
quint16 peerPort;
};
/*!
\class QSsh::SshConnection
\brief This class provides an SSH connection, implementing protocol version 2.0
See acquireConnection() which provides a pool mechanism for re-use.
It can spawn channels for remote execution and SFTP operations (version 3).
It operates asynchronously (non-blocking) and is not thread-safe.
*/
class QSSH_EXPORT SshConnection : public QObject
{
Q_OBJECT
public:
/*!
* \brief The current state of a connection
*/
enum State { Unconnected, Connecting, Connected };
explicit SshConnection(const SshConnectionParameters &serverInfo, QObject *parent = 0);
/*!
* \param serverInfo serverInfo connection parameters
* \param parent Parent object.
*/
explicit SshConnection(const SshConnectionParameters &serverInfo, QObject *parent = nullptr);
void connectToHost();
void disconnectFromHost();
/*!
* \brief Current state of this connection
*/
State state() const;
/*!
* \brief Returns the error state of the connection
* \returns If there is no error, returns \ref SshNoError if the connection is OK
*/
SshError errorState() const;
QString errorString() const;
SshConnectionParameters connectionParameters() const;
SshConnectionInfo connectionInfo() const;
~SshConnection();
/*!
* \brief Use this to launch remote commands
* \param command The command to execute
*/
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
/*!
* \brief Creates a remote interactive session with a shell
*/
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createDirectTunnel(const QString &originatingHost,
@ -129,13 +256,35 @@ public:
// -1 if an error occurred, number of channels closed otherwise.
int closeAllChannels();
int channelCount() const;
const QByteArray &hostKeyFingerprint() const;
/*!
* \brief The X11 display name used for X11 forwarding
* \return The name of the X11 display set for this connection
*/
QString x11DisplayName() const;
signals:
/*!
* \brief Emitted when ready for use
*/
void connected();
/*!
* \brief Emitted when the connection has been closed
*/
void disconnected();
/*!
* \brief Emitted when data has been received
* \param message The content of the data, same as the output you would get when running \a ssh on the command line
*/
void dataAvailable(const QString &message);
/*!
* \brief Emitted when an error occured
*/
void error(QSsh::SshError);
private:
@ -143,3 +292,7 @@ private:
};
} // namespace QSsh
Q_DECLARE_METATYPE(QSsh::SshConnectionParameters::AuthenticationType)
#endif // SSHCONNECTION_H

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCONNECTION_P_H
#define SSHCONNECTION_P_H
#include "sshconnection.h"
#include "sshexception_p.h"
@ -32,6 +38,7 @@
#include <QHash>
#include <QList>
#include <QQueue>
#include <QObject>
#include <QPair>
#include <QScopedPointer>
@ -56,6 +63,7 @@ enum SshStateInternal {
SocketConnecting, // After connectToHost()
SocketConnected, // After socket's connected() signal
UserAuthServiceRequested,
WaitingForAgentKeys,
UserAuthRequested,
ConnectionEstablished // After service has been started
// ...
@ -92,6 +100,7 @@ public:
SshStateInternal state() const { return m_state; }
SshError errorState() const { return m_error; }
QString errorString() const { return m_errorString; }
const QByteArray &hostKeyFingerprint() const { return m_hostFingerprint; }
signals:
void connected();
@ -107,6 +116,12 @@ private:
void handleTimeout();
void sendKeepAlivePacket();
void handleAgentKeysUpdated();
void handleSignatureFromAgent(const QByteArray &key, const QByteArray &signature, uint token);
void tryAllAgentKeys();
void authenticateWithPublicKey();
void setAgentError();
void handleServerId();
void handlePackets();
void handleCurrentPacket();
@ -118,6 +133,7 @@ private:
void handleUserAuthInfoRequestPacket();
void handleUserAuthSuccessPacket();
void handleUserAuthFailurePacket();
void handleUserAuthKeyOkPacket();
void handleUserAuthBannerPacket();
void handleUnexpectedPacket();
void handleGlobalRequest();
@ -143,6 +159,8 @@ private:
void sendData(const QByteArray &data);
uint tokenForAgent() const;
typedef void (SshConnectionPrivate::*PacketHandler)();
typedef QList<SshStateInternal> StateList;
void setupPacketHandlers();
@ -165,15 +183,22 @@ private:
SshError m_error;
QString m_errorString;
QScopedPointer<SshKeyExchange> m_keyExchange;
QByteArray m_hostFingerprint;
QTimer m_timeoutTimer;
QTimer m_keepAliveTimer;
bool m_ignoreNextPacket;
SshConnection *m_conn;
quint64 m_lastInvalidMsgSeqNr;
QByteArray m_serverId;
QByteArray m_agentSignature;
QQueue<QByteArray> m_pendingKeyChecks;
QByteArray m_agentKeyToUse;
bool m_serverHasSentDataBeforeId;
bool m_triedAllPasswordBasedMethods;
bool m_agentKeysUpToDate;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHCONNECTION_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshconnectionmanager.h"
@ -44,10 +49,10 @@ public:
SshConnection *connection;
bool scheduledForRemoval;
};
bool operator==(const UnaquiredConnection &c1, const UnaquiredConnection &c2) {
bool operator==(UnaquiredConnection c1, UnaquiredConnection c2) {
return c1.connection == c2.connection;
}
bool operator!=(const UnaquiredConnection &c1, const UnaquiredConnection &c2) {
bool operator!=(UnaquiredConnection c1, UnaquiredConnection c2) {
return !(c1 == c2);
}
@ -61,13 +66,14 @@ public:
moveToThread(QCoreApplication::instance()->thread());
connect(&m_removalTimer, &QTimer::timeout,
this, &SshConnectionManager::removeInactiveConnections);
m_removalTimer.setTimerType(Qt::VeryCoarseTimer);
m_removalTimer.start(150000); // For a total timeout of five minutes.
}
~SshConnectionManager()
{
foreach (const UnaquiredConnection &connection, m_unacquiredConnections) {
disconnect(connection.connection, 0, this, 0);
disconnect(connection.connection, nullptr, this, nullptr);
delete connection.connection;
}
@ -160,7 +166,7 @@ public:
}
if (doDelete) {
disconnect(connection, 0, this, 0);
disconnect(connection, nullptr, this, nullptr);
m_deprecatedConnections.removeAll(connection);
connection->deleteLater();
}
@ -173,7 +179,7 @@ public:
for (int i = 0; i < m_unacquiredConnections.count(); ++i) {
SshConnection * const connection = m_unacquiredConnections.at(i).connection;
if (connection->connectionParameters() == sshParams) {
disconnect(connection, 0, this, 0);
disconnect(connection, nullptr, this, nullptr);
delete connection;
m_unacquiredConnections.removeAt(i);
break;
@ -203,7 +209,7 @@ private:
return;
if (m_unacquiredConnections.removeOne(UnaquiredConnection(currentConnection))) {
disconnect(currentConnection, 0, this, 0);
disconnect(currentConnection, nullptr, this, nullptr);
currentConnection->deleteLater();
}
}
@ -214,7 +220,7 @@ private:
for (int i = m_unacquiredConnections.count() - 1; i >= 0; --i) {
UnaquiredConnection &c = m_unacquiredConnections[i];
if (c.scheduledForRemoval) {
disconnect(c.connection, 0, this, 0);
disconnect(c.connection, nullptr, this, nullptr);
c.connection->deleteLater();
m_unacquiredConnections.removeAt(i);
} else {

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCONNECTIONMANAGER_H
#define SSHCONNECTIONMANAGER_H
#include "ssh_global.h"
@ -32,10 +38,26 @@ namespace QSsh {
class SshConnection;
class SshConnectionParameters;
/*!
* \brief Creates a new connection or returns an existing one if there already is one with identical sshParams
* \param sshParams Parameters used during connection
* \return A connection
*/
QSSH_EXPORT SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
/*!
* \brief Call this when you are done with a connection, might be disconnected and destroyed if there are no others who have called acquireConnection()
* \param connection The connection to be released
*/
QSSH_EXPORT void releaseConnection(SshConnection *connection);
// Make sure the next acquireConnection with the given parameters will return a new connection.
/*!
* \brief Creates a new connection, unlike acquireConnection() it will not reuse an existing one.
* \param sshParams Parameters used during connection
* Make sure the next acquireConnection with the given parameters will return a new connection.
*/
QSSH_EXPORT void forceNewConnection(const SshConnectionParameters &sshParams);
} // namespace QSsh
#endif // SSHCONNECTIONMANAGER_H

View file

@ -1,39 +1,45 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshcryptofacility_p.h"
#include "opensshkeyfilereader_p.h"
#include "sshbotanconversions_p.h"
#include "sshcapabilities_p.h"
#include "sshexception_p.h"
#include "sshkeyexchange_p.h"
#include "sshkeypasswordretriever_p.h"
#include "sshlogging_p.h"
#include "sshpacket_p.h"
#include "sshlogging_p.h"
#include <botan/botan.h>
#include <botan_all.h>
#include <QDebug>
#include <QList>
@ -57,8 +63,8 @@ void SshAbstractCryptoFacility::clearKeys()
m_cipherBlockSize = 0;
m_macLength = 0;
m_sessionId.clear();
m_pipe.reset(0);
m_hMac.reset(0);
m_pipe.reset(nullptr);
m_hMac.reset(nullptr);
}
SshAbstractCryptoFacility::Mode SshAbstractCryptoFacility::getMode(const QByteArray &algoName)
@ -77,28 +83,32 @@ void SshAbstractCryptoFacility::recreateKeys(const SshKeyExchange &kex)
if (m_sessionId.isEmpty())
m_sessionId = kex.h();
Algorithm_Factory &af = global_state().algorithm_factory();
const QByteArray &rfcCryptAlgoName = cryptAlgoName(kex);
BlockCipher * const cipher
= af.prototype_block_cipher(botanCryptAlgoName(rfcCryptAlgoName))->clone();
const QByteArray &rfcCryptAlgoName = cryptAlgoName(kex);
m_cipherBlockSize = static_cast<quint32>(cipher->block_size());
{ // Don't know how else to get this with the new botan API
std::unique_ptr<BlockCipher> cipher
= BlockCipher::create_or_throw(botanCryptAlgoName(rfcCryptAlgoName));
m_cipherBlockSize = static_cast<quint32>(cipher->block_size());
}
const QByteArray ivData = generateHash(kex, ivChar(), m_cipherBlockSize);
const InitializationVector iv(convertByteArray(ivData), m_cipherBlockSize);
const quint32 keySize = static_cast<quint32>(cipher->key_spec().maximum_keylength());
Keyed_Filter * const cipherMode
= makeCipherMode(botanCipherAlgoName(rfcCryptAlgoName), getMode(rfcCryptAlgoName));
const quint32 keySize = static_cast<quint32>(cipherMode->key_spec().maximum_keylength());
const QByteArray cryptKeyData = generateHash(kex, keyChar(), keySize);
SymmetricKey cryptKey(convertByteArray(cryptKeyData), keySize);
Keyed_Filter * const cipherMode
= makeCipherMode(cipher, getMode(rfcCryptAlgoName), iv, cryptKey);
cipherMode->set_key(cryptKey);
cipherMode->set_iv(iv);
m_pipe.reset(new Pipe(cipherMode));
m_macLength = botanHMacKeyLen(hMacAlgoName(kex));
const QByteArray hMacKeyData = generateHash(kex, macChar(), macLength());
SymmetricKey hMacKey(convertByteArray(hMacKeyData), macLength());
const HashFunction * const hMacProto
= af.prototype_hash_function(botanHMacAlgoName(hMacAlgoName(kex)));
m_hMac.reset(new HMAC(hMacProto->clone()));
m_hMac = MessageAuthenticationCode::create_or_throw("HMAC(" + std::string(botanHMacAlgoName(hMacAlgoName(kex))) + ")");
m_hMac->set_key(hMacKey);
}
@ -127,12 +137,9 @@ void SshAbstractCryptoFacility::convert(QByteArray &data, quint32 offset,
}
}
Keyed_Filter *SshAbstractCryptoFacility::makeCtrCipherMode(BlockCipher *cipher,
const InitializationVector &iv, const SymmetricKey &key)
Keyed_Filter *SshAbstractCryptoFacility::makeCtrCipherMode(const QByteArray &cipher)
{
StreamCipher_Filter * const filter = new StreamCipher_Filter(new CTR_BE(cipher));
filter->set_key(key);
filter->set_iv(iv);
StreamCipher_Filter *filter = new StreamCipher_Filter(cipher.toStdString());
return filter;
}
@ -155,13 +162,13 @@ QByteArray SshAbstractCryptoFacility::generateHash(const SshKeyExchange &kex,
SecureVector<byte> key
= kex.hash()->process(convertByteArray(data), data.size());
while (key.size() < length) {
SecureVector<byte> tmpKey;
tmpKey += SecureVector<byte>(convertByteArray(k), k.size());
tmpKey += SecureVector<byte>(convertByteArray(h), h.size());
secure_vector<byte> tmpKey;
tmpKey += secure_vector<byte>(k.begin(), k.end());
tmpKey += secure_vector<byte>(h.begin(), h.end());
tmpKey += key;
key += kex.hash()->process(tmpKey);
}
return QByteArray(reinterpret_cast<const char *>(key.begin()), length);
return QByteArray(reinterpret_cast<const char *>(key.data()), length);
}
void SshAbstractCryptoFacility::checkInvariant() const
@ -187,16 +194,17 @@ QByteArray SshEncryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
return kex.hMacAlgoClientToServer();
}
Keyed_Filter *SshEncryptionFacility::makeCipherMode(BlockCipher *cipher, Mode mode,
const InitializationVector &iv, const SymmetricKey &key)
Keyed_Filter *SshEncryptionFacility::makeCipherMode(const QByteArray &cipher, const Mode mode)
{
switch (mode) {
case CbcMode:
return new CBC_Encryption(cipher, new Null_Padding, key, iv);
case CtrMode:
return makeCtrCipherMode(cipher, iv, key);
if (mode == CtrMode) {
return new StreamCipher_Filter(cipher.toStdString());
}
return 0; // For dumb compilers.
qWarning() << "I haven't been able to test the CBC encryption modes, so if this files file a bug at https://github.com/sandsmark/QSsh";
Cipher_Mode_Filter *filter = new Cipher_Mode_Filter(
Cipher_Mode::create_or_throw(cipher.toStdString(), ENCRYPTION).release()); // We have to release, otherwise clang fails to link
return filter;
}
void SshEncryptionFacility::encrypt(QByteArray &data) const
@ -215,7 +223,14 @@ void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFil
QList<BigInt> allKeyParams;
QString error1;
QString error2;
if (!createAuthenticationKeyFromPKCS8(privKeyFileContents, pubKeyParams, allKeyParams, error1)
OpenSshKeyFileReader openSshReader(m_rng);
if (openSshReader.parseKey(privKeyFileContents)) {
m_authKeyAlgoName = openSshReader.keyType();
m_authKey.reset(openSshReader.privateKey().release());
pubKeyParams = openSshReader.publicParameters();
allKeyParams = openSshReader.allParameters();
} else if (!createAuthenticationKeyFromPKCS8(privKeyFileContents, pubKeyParams, allKeyParams,
error1)
&& !createAuthenticationKeyFromOpenSSL(privKeyFileContents, pubKeyParams, allKeyParams,
error2)) {
qCDebug(sshLog, "%s: %s\n\t%s\n", Q_FUNC_INFO, qPrintable(error1), qPrintable(error2));
@ -235,7 +250,7 @@ void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFil
if (ecdsaKey) {
m_authPubKeyBlob += AbstractSshPacket::encodeString(m_authKeyAlgoName.mid(11)); // Without "ecdsa-sha2-" prefix.
m_authPubKeyBlob += AbstractSshPacket::encodeString(
convertByteArray(EC2OSP(ecdsaKey->public_point(), PointGFp::UNCOMPRESSED)));
convertByteArray(ecdsaKey->public_point().encode(PointGFp::UNCOMPRESSED)));
} else {
foreach (const BigInt &b, pubKeyParams)
m_authPubKeyBlob += AbstractSshPacket::encodeMpInt(b);
@ -249,7 +264,7 @@ bool SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &p
try {
Pipe pipe;
pipe.process_msg(convertByteArray(privKeyFileContents), privKeyFileContents.size());
m_authKey.reset(PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever()));
m_authKey.reset(PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever::get_passphrase));
if (auto * const dsaKey = dynamic_cast<DSA_PrivateKey *>(m_authKey.data())) {
m_authKeyAlgoName = SshCapabilities::PubKeyDss;
pubKeyParams << dsaKey->group_p() << dsaKey->group_q()
@ -338,7 +353,7 @@ bool SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray
} else if (m_authKeyAlgoName == SshCapabilities::PubKeyRsa) {
BigInt p, q, e, d, n;
sequence.decode(n).decode(e).decode(d).decode(p).decode(q);
RSA_PrivateKey * const rsaKey = new RSA_PrivateKey(m_rng, p, q, e, d, n);
RSA_PrivateKey * const rsaKey = new RSA_PrivateKey(p, q, e, d, n);
m_authKey.reset(rsaKey);
pubKeyParams << e << n;
allKeyParams << pubKeyParams << p << q << d;
@ -375,6 +390,7 @@ QByteArray SshEncryptionFacility::authenticationKeySignature(const QByteArray &d
Q_ASSERT(m_authKey);
QScopedPointer<PK_Signer> signer(new PK_Signer(*m_authKey,
m_rng,
botanEmsaAlgoName(m_authKeyAlgoName)));
QByteArray dataToSign = AbstractSshPacket::encodeString(sessionId()) + data;
QByteArray signature
@ -412,16 +428,17 @@ QByteArray SshDecryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
return kex.hMacAlgoServerToClient();
}
Keyed_Filter *SshDecryptionFacility::makeCipherMode(BlockCipher *cipher, Mode mode, const InitializationVector &iv,
const SymmetricKey &key)
Keyed_Filter *SshDecryptionFacility::makeCipherMode(const QByteArray &cipher, const Mode mode)
{
switch (mode) {
case CbcMode:
return new CBC_Decryption(cipher, new Null_Padding, key, iv);
case CtrMode:
return makeCtrCipherMode(cipher, iv, key);
if (mode == CtrMode) {
return new StreamCipher_Filter(cipher.toStdString());
}
return 0; // For dumb compilers.
qWarning() << "I haven't been able to test the CBC decryption modes, so if this files file a bug at https://github.com/sandsmark/QSsh";
Cipher_Mode_Filter *filter = new Cipher_Mode_Filter(
Cipher_Mode::create_or_throw(cipher.toStdString(), DECRYPTION).release()); // We have to release, otherwise clang fails to link
return filter;
}
void SshDecryptionFacility::decrypt(QByteArray &data, quint32 offset,
@ -432,7 +449,7 @@ void SshDecryptionFacility::decrypt(QByteArray &data, quint32 offset,
const char * const start = data.constData() + offset;
const char * const end = start + dataSize;
for (const char *c = start; c < end; ++c)
qCDebug(sshLog, ) << "'" << *c << "' (0x" << (static_cast<int>(*c) & 0xff) << ")";
qCDebug(sshLog) << "'" << *c << "' (0x" << (static_cast<int>(*c) & 0xff) << ")";
}
} // namespace Internal

View file

@ -1,31 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHABSTRACTCRYPTOFACILITY_P_H
#define SSHABSTRACTCRYPTOFACILITY_P_H
#include <botan/botan.h>
#include <botan_all.h>
#include <QByteArray>
#include <QScopedPointer>
@ -45,15 +51,16 @@ public:
QByteArray generateMac(const QByteArray &data, quint32 dataSize) const;
quint32 cipherBlockSize() const { return m_cipherBlockSize; }
quint32 macLength() const { return m_macLength; }
QByteArray sessionId() const { return m_sessionId; }
bool isValid() const { return m_hMac && m_pipe; } // TODO: probably more, but this stops segfaulting
protected:
enum Mode { CbcMode, CtrMode };
SshAbstractCryptoFacility();
void convert(QByteArray &data, quint32 offset, quint32 dataSize) const;
QByteArray sessionId() const { return m_sessionId; }
Botan::Keyed_Filter *makeCtrCipherMode(Botan::BlockCipher *cipher,
const Botan::InitializationVector &iv, const Botan::SymmetricKey &key);
Botan::Keyed_Filter *makeCtrCipherMode(const QByteArray &cipher);
private:
SshAbstractCryptoFacility(const SshAbstractCryptoFacility &);
@ -61,8 +68,7 @@ private:
virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const = 0;
virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const = 0;
virtual Botan::Keyed_Filter *makeCipherMode(Botan::BlockCipher *cipher,
Mode mode, const Botan::InitializationVector &iv, const Botan::SymmetricKey &key) = 0;
virtual Botan::Keyed_Filter *makeCipherMode(const QByteArray &cipher, const Mode mode) = 0;
virtual char ivChar() const = 0;
virtual char keyChar() const = 0;
virtual char macChar() const = 0;
@ -72,8 +78,8 @@ private:
static Mode getMode(const QByteArray &algoName);
QByteArray m_sessionId;
QScopedPointer<Botan::Pipe> m_pipe;
QScopedPointer<Botan::HMAC> m_hMac;
std::unique_ptr<Botan::Pipe> m_pipe;
std::unique_ptr<Botan::MessageAuthenticationCode> m_hMac;
quint32 m_cipherBlockSize;
quint32 m_macLength;
};
@ -92,13 +98,12 @@ public:
~SshEncryptionFacility();
private:
virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const;
virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const;
virtual Botan::Keyed_Filter *makeCipherMode(Botan::BlockCipher *cipher,
Mode mode, const Botan::InitializationVector &iv, const Botan::SymmetricKey &key);
virtual char ivChar() const { return 'A'; }
virtual char keyChar() const { return 'C'; }
virtual char macChar() const { return 'E'; }
QByteArray cryptAlgoName(const SshKeyExchange &kex) const override;
QByteArray hMacAlgoName(const SshKeyExchange &kex) const override;
Botan::Keyed_Filter *makeCipherMode(const QByteArray &cipher, const Mode mode) override;
char ivChar() const override { return 'A'; }
char keyChar() const override { return 'C'; }
char macChar() const override { return 'E'; }
bool createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams, QString &error);
@ -125,14 +130,15 @@ public:
void decrypt(QByteArray &data, quint32 offset, quint32 dataSize) const;
private:
virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const;
virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const;
virtual Botan::Keyed_Filter *makeCipherMode(Botan::BlockCipher *cipher,
Mode mode, const Botan::InitializationVector &iv, const Botan::SymmetricKey &key);
virtual char ivChar() const { return 'B'; }
virtual char keyChar() const { return 'D'; }
virtual char macChar() const { return 'F'; }
QByteArray cryptAlgoName(const SshKeyExchange &kex) const override;
QByteArray hMacAlgoName(const SshKeyExchange &kex) const override;
Botan::Keyed_Filter *makeCipherMode(const QByteArray &cipher, const Mode mode) override;
char ivChar() const override { return 'B'; }
char keyChar() const override { return 'D'; }
char macChar() const override { return 'F'; }
};
} // namespace Internal
} // namespace QSsh
#endif // SSHABSTRACTCRYPTOFACILITY_P_H

View file

@ -1,28 +1,34 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "sshdirecttcpiptunnel.h"
#include "sshdirecttcpiptunnel_p.h"
@ -98,11 +104,12 @@ void SshDirectTcpIpTunnel::initialize()
try {
QIODevice::open(QIODevice::ReadWrite);
d->m_sendFacility.sendDirectTcpIpPacket(d->localChannelId(), d->initialWindowSize(),
d->maxPacketSize(), d->m_remoteHost.toUtf8(), d->m_remotePort,
d->m_sendFacility.sendDirectTcpIpPacket(d->localChannelId(), SshDirectTcpIpTunnelPrivate::initialWindowSize(),
SshDirectTcpIpTunnelPrivate::maxPacketSize(), d->m_remoteHost.toUtf8(), d->m_remotePort,
d->m_originatingHost.toUtf8(), d->m_originatingPort);
d->setChannelState(AbstractSshChannel::SessionRequested);
d->m_timeoutTimer.start(d->ReplyTimeout);
d->m_timeoutTimer.setTimerType(Qt::VeryCoarseTimer);
d->m_timeoutTimer.start(SshDirectTcpIpTunnelPrivate::ReplyTimeout);
} catch (const std::exception &e) { // Won't happen, but let's play it safe.
qCWarning(sshLog, "Botan error: %s", e.what());
d->closeChannel();

View file

@ -1,29 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#pragma once
#ifndef SSHDIRECTTCPIPTUNNEL_H
#define SSHDIRECTTCPIPTUNNEL_H
#include "ssh_global.h"
@ -77,3 +85,5 @@ private:
};
} // namespace QSsh
#endif // SSHDIRECTTCPIPTUNNEL_H

View file

@ -1,29 +1,36 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef DIRECTTCPIPCHANNEL_P_H
#define DIRECTTCPIPCHANNEL_P_H
#include "sshtcpiptunnel_p.h"
@ -57,3 +64,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // DIRECTTCPIPCHANNEL_P_H

View file

@ -1,37 +1,77 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHERRORS_P_H
#define SSHERRORS_P_H
#include <QMetaType>
namespace QSsh {
/*!
* \brief SSH specific errors
*/
enum SshError {
SshNoError, SshSocketError, SshTimeoutError, SshProtocolError,
SshHostKeyError, SshKeyFileError, SshAuthenticationError,
SshClosedByServerError, SshInternalError
/// No error has occured
SshNoError,
/// There was a network socket error
SshSocketError,
/// The connection timed out
SshTimeoutError,
/// There was an error communicating with the server
SshProtocolError,
/// There was a problem with the remote host key
SshHostKeyError,
/// We failed to read or parse the key file used for authentication
SshKeyFileError,
/// We failed to authenticate
SshAuthenticationError,
/// The server closed our connection
SshClosedByServerError,
/// The ssh-agent used for authenticating failed somehow
SshAgentError,
/// Something bad happened on the server
SshInternalError
};
} // namespace QSsh
Q_DECLARE_METATYPE(QSsh::SshError)
#endif // SSHERRORS_P_H

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHEXCEPTION_P_H
#define SSHEXCEPTION_P_H
#include "ssherrors.h"
@ -31,6 +37,8 @@
#include <QCoreApplication>
#include <QString>
#include <exception>
namespace QSsh {
namespace Internal {
@ -57,26 +65,31 @@ enum SshErrorCode {
#define SSH_SERVER_EXCEPTION(error, errorString) \
SshServerException((error), (errorString), SSH_TR(errorString))
struct SshServerException
struct SshServerException : public std::exception
{
SshServerException(SshErrorCode error, const QByteArray &errorStringServer,
const QString &errorStringUser)
: error(error), errorStringServer(errorStringServer),
errorStringUser(errorStringUser) {}
const char *what() const noexcept override { return errorStringServer.constData(); }
const SshErrorCode error;
const QByteArray errorStringServer;
const QString errorStringUser;
};
struct SshClientException
struct SshClientException : public std::exception
{
SshClientException(SshError error, const QString &errorString)
: error(error), errorString(errorString) {}
: error(error), errorString(errorString), errorStringPrintable(errorString.toLocal8Bit()) {}
const char *what() const noexcept override { return errorStringPrintable.constData(); }
const SshError error;
const QString errorString;
const QByteArray errorStringPrintable;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHEXCEPTION_P_H

View file

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
@ -9,20 +9,24 @@
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "sshhostkeydatabase.h"
#include "sshlogging_p.h"
@ -115,4 +119,9 @@ void SshHostKeyDatabase::insertHostKey(const QString &hostName, const QByteArray
d->hostKeys.insert(hostName, key);
}
QByteArray SshHostKeyDatabase::retrieveHostKey(const QString &hostName)
{
return d->hostKeys.value(hostName);
}
} // namespace QSsh

View file

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
@ -9,21 +9,26 @@
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#pragma once
#ifndef SSHHOSTKEYDATABASE_H
#define SSHHOSTKEYDATABASE_H
#include "ssh_global.h"
@ -36,6 +41,8 @@ QT_END_NAMESPACE
namespace QSsh {
class SshHostKeyDatabase;
/// Convenience typedef
typedef QSharedPointer<SshHostKeyDatabase> SshHostKeyDatabasePtr;
class QSSH_EXPORT SshHostKeyDatabase
@ -49,18 +56,20 @@ public:
KeyLookupMismatch
};
SshHostKeyDatabase();
~SshHostKeyDatabase();
bool load(const QString &filePath, QString *error = 0);
bool store(const QString &filePath, QString *error = 0) const;
bool load(const QString &filePath, QString *error = nullptr);
bool store(const QString &filePath, QString *error = nullptr) const;
KeyLookupResult matchHostKey(const QString &hostName, const QByteArray &key) const;
void insertHostKey(const QString &hostName, const QByteArray &key);
QByteArray retrieveHostKey(const QString &hostName);
private:
SshHostKeyDatabase();
class SshHostKeyDatabasePrivate;
SshHostKeyDatabasePrivate * const d;
};
} // namespace QSsh
#endif // Include guard.

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshincomingpacket_p.h"
@ -203,7 +208,8 @@ SshKeyExchangeReply SshIncomingPacket::extractKeyExchangeReply(const QByteArray
throw SshPacketParseException();
getHostKeySpecificReplyData(replyData, hostKeyAlgo, replyData.k_s.mid(k_sOffset));
if (kexAlgo == SshCapabilities::DiffieHellmanGroup1Sha1) {
if (kexAlgo == SshCapabilities::DiffieHellmanGroup1Sha1
|| kexAlgo == SshCapabilities::DiffieHellmanGroup14Sha1) {
replyData.f = SshPacketParser::asBigInt(m_data, &topLevelOffset);
} else {
QSSH_ASSERT_AND_RETURN_VALUE(kexAlgo.startsWith(SshCapabilities::EcdhKexNamePrefix),
@ -296,6 +302,23 @@ SshUserAuthInfoRequestPacket SshIncomingPacket::extractUserAuthInfoRequest() con
}
}
SshUserAuthPkOkPacket SshIncomingPacket::extractUserAuthPkOk() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_USERAUTH_PK_OK);
try {
SshUserAuthPkOkPacket msg;
quint32 offset = TypeOffset + 1;
msg.algoName= SshPacketParser::asString(m_data, &offset);
msg.keyBlob = SshPacketParser::asString(m_data, &offset);
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_USERAUTH_PK_OK.");
}
}
SshDebug SshIncomingPacket::extractDebug() const
{
Q_ASSERT(isComplete());
@ -346,29 +369,63 @@ SshUnimplemented SshIncomingPacket::extractUnimplemented() const
}
}
SshChannelOpen SshIncomingPacket::extractChannelOpen() const
SshChannelOpenGeneric SshIncomingPacket::extractChannelOpen() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN);
SshChannelOpen open;
try {
SshChannelOpenGeneric channelOpen;
quint32 offset = TypeOffset + 1;
QByteArray type = SshPacketParser::asString(m_data, &offset);
open.remoteChannel = SshPacketParser::asUint32(m_data, &offset);
open.remoteWindowSize = SshPacketParser::asUint32(m_data, &offset);
open.remoteMaxPacketSize = SshPacketParser::asUint32(m_data, &offset);
if (type == ForwardedTcpIpType) {
open.remoteAddress = SshPacketParser::asString(m_data, &offset);
open.remotePort = SshPacketParser::asUint32(m_data, &offset);
} else {
open.remotePort = 0;
}
channelOpen.channelType = SshPacketParser::asString(m_data, &offset);
channelOpen.commonData.remoteChannel = SshPacketParser::asUint32(m_data, &offset);
channelOpen.commonData.remoteWindowSize = SshPacketParser::asUint32(m_data, &offset);
channelOpen.commonData.remoteMaxPacketSize = SshPacketParser::asUint32(m_data, &offset);
channelOpen.typeSpecificData = m_data.mid(offset, length() - paddingLength() - offset
+ int(sizeof m_length));
return channelOpen;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid SSH_MSG_CHANNEL_OPEN packet.");
}
}
SshChannelOpenForwardedTcpIp SshIncomingPacket::extractChannelOpenForwardedTcpIp(
const SshChannelOpenGeneric &genericData)
{
try {
SshChannelOpenForwardedTcpIp specificData;
specificData.common = genericData.commonData;
quint32 offset = 0;
specificData.remoteAddress = SshPacketParser::asString(genericData.typeSpecificData,
&offset);
specificData.remotePort = SshPacketParser::asUint32(genericData.typeSpecificData, &offset);
specificData.originatorAddress = SshPacketParser::asString(genericData.typeSpecificData,
&offset);
specificData.originatorPort = SshPacketParser::asUint32(genericData.typeSpecificData,
&offset);
return specificData;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid SSH_MSG_CHANNEL_OPEN packet.");
}
}
SshChannelOpenX11 SshIncomingPacket::extractChannelOpenX11(const SshChannelOpenGeneric &genericData)
{
try {
SshChannelOpenX11 specificData;
specificData.common = genericData.commonData;
quint32 offset = 0;
specificData.originatorAddress = SshPacketParser::asString(genericData.typeSpecificData,
&offset);
specificData.originatorPort = SshPacketParser::asUint32(genericData.typeSpecificData,
&offset);
return specificData;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid SSH_MSG_CHANNEL_OPEN packet.");
}
return open;
}
SshChannelOpenFailure SshIncomingPacket::extractChannelOpenFailure() const

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHINCOMINGPACKET_P_H
#define SSHINCOMINGPACKET_P_H
#include "sshpacket_p.h"
@ -76,6 +82,12 @@ struct SshUserAuthBanner
QByteArray language;
};
struct SshUserAuthPkOkPacket
{
QByteArray algoName;
QByteArray keyBlob;
};
struct SshUserAuthInfoRequestPacket
{
QString name;
@ -102,13 +114,34 @@ struct SshRequestSuccess
quint32 bindPort;
};
struct SshChannelOpen
struct SshChannelOpenCommon
{
quint32 remoteChannel;
quint32 remoteWindowSize;
quint32 remoteMaxPacketSize;
};
struct SshChannelOpenGeneric
{
QByteArray channelType;
SshChannelOpenCommon commonData;
QByteArray typeSpecificData;
};
struct SshChannelOpenForwardedTcpIp
{
SshChannelOpenCommon common;
QByteArray remoteAddress;
quint32 remotePort;
QByteArray originatorAddress;
quint32 originatorPort;
};
struct SshChannelOpenX11
{
SshChannelOpenCommon common;
QByteArray originatorAddress;
quint32 originatorPort;
};
struct SshChannelOpenFailure
@ -176,11 +209,15 @@ public:
SshDisconnect extractDisconnect() const;
SshUserAuthBanner extractUserAuthBanner() const;
SshUserAuthInfoRequestPacket extractUserAuthInfoRequest() const;
SshUserAuthPkOkPacket extractUserAuthPkOk() const;
SshDebug extractDebug() const;
SshRequestSuccess extractRequestSuccess() const;
SshUnimplemented extractUnimplemented() const;
SshChannelOpen extractChannelOpen() const;
SshChannelOpenGeneric extractChannelOpen() const;
static SshChannelOpenForwardedTcpIp extractChannelOpenForwardedTcpIp(
const SshChannelOpenGeneric &genericData);
static SshChannelOpenX11 extractChannelOpenX11(const SshChannelOpenGeneric &genericData);
SshChannelOpenFailure extractChannelOpenFailure() const;
SshChannelOpenConfirmation extractChannelOpenConfirmation() const;
SshChannelWindowAdjust extractWindowAdjust() const;
@ -211,3 +248,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SSHINCOMINGPACKET_P_H

View file

@ -1,174 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sshkeycreationdialog.h"
#include "ui_sshkeycreationdialog.h"
#include "sshkeygenerator.h"
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QApplication>
#include <QMessageBox>
#include <QStandardPaths>
namespace QSsh {
SshKeyCreationDialog::SshKeyCreationDialog(QWidget *parent)
: QDialog(parent), m_keyGenerator(0), m_ui(new Ui::SshKeyCreationDialog)
{
m_ui->setupUi(this);
// Not using Utils::PathChooser::browseButtonLabel to avoid dependency
#ifdef Q_OS_MAC
m_ui->privateKeyFileButton->setText(tr("Choose..."));
#else
m_ui->privateKeyFileButton->setText(tr("Browse..."));
#endif
const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
+ QLatin1String("/.ssh/qtc_id");
setPrivateKeyFile(defaultPath);
connect(m_ui->rsa, &QRadioButton::toggled,
this, &SshKeyCreationDialog::keyTypeChanged);
connect(m_ui->dsa, &QRadioButton::toggled,
this, &SshKeyCreationDialog::keyTypeChanged);
connect(m_ui->privateKeyFileButton, &QPushButton::clicked,
this, &SshKeyCreationDialog::handleBrowseButtonClicked);
connect(m_ui->generateButton, &QPushButton::clicked,
this, &SshKeyCreationDialog::generateKeys);
keyTypeChanged();
}
SshKeyCreationDialog::~SshKeyCreationDialog()
{
delete m_keyGenerator;
delete m_ui;
}
void SshKeyCreationDialog::keyTypeChanged()
{
m_ui->comboBox->clear();
QStringList keySizes;
if (m_ui->rsa->isChecked())
keySizes << QLatin1String("1024") << QLatin1String("2048") << QLatin1String("4096");
else if (m_ui->ecdsa->isChecked())
keySizes << QLatin1String("256") << QLatin1String("384") << QLatin1String("521");
else if (m_ui->dsa->isChecked())
keySizes << QLatin1String("1024");
m_ui->comboBox->addItems(keySizes);
if (!keySizes.isEmpty())
m_ui->comboBox->setCurrentIndex(0);
m_ui->comboBox->setEnabled(!keySizes.isEmpty());
}
void SshKeyCreationDialog::generateKeys()
{
if (userForbidsOverwriting())
return;
const SshKeyGenerator::KeyType keyType = m_ui->rsa->isChecked()
? SshKeyGenerator::Rsa : m_ui->dsa->isChecked()
? SshKeyGenerator::Dsa : SshKeyGenerator::Ecdsa;
if (!m_keyGenerator)
m_keyGenerator = new SshKeyGenerator;
QApplication::setOverrideCursor(Qt::BusyCursor);
const bool success = m_keyGenerator->generateKeys(keyType, SshKeyGenerator::Mixed,
m_ui->comboBox->currentText().toUShort());
QApplication::restoreOverrideCursor();
if (success)
saveKeys();
else
QMessageBox::critical(this, tr("Key Generation Failed"), m_keyGenerator->error());
}
void SshKeyCreationDialog::handleBrowseButtonClicked()
{
const QString filePath = QFileDialog::getSaveFileName(this, tr("Choose Private Key File Name"));
if (!filePath.isEmpty())
setPrivateKeyFile(filePath);
}
void SshKeyCreationDialog::setPrivateKeyFile(const QString &filePath)
{
m_ui->privateKeyFileValueLabel->setText(filePath);
m_ui->generateButton->setEnabled(!privateKeyFilePath().isEmpty());
m_ui->publicKeyFileLabel->setText(filePath + QLatin1String(".pub"));
}
void SshKeyCreationDialog::saveKeys()
{
const QString parentDir = QFileInfo(privateKeyFilePath()).dir().path();
if (!QDir::root().mkpath(parentDir)) {
QMessageBox::critical(this, tr("Cannot Save Key File"),
tr("Failed to create directory: \"%1\".").arg(parentDir));
return;
}
QFile privateKeyFile(privateKeyFilePath());
if (!privateKeyFile.open(QIODevice::WriteOnly)
|| !privateKeyFile.write(m_keyGenerator->privateKey())) {
QMessageBox::critical(this, tr("Cannot Save Private Key File"),
tr("The private key file could not be saved: %1").arg(privateKeyFile.errorString()));
return;
}
QFile::setPermissions(privateKeyFilePath(), QFile::ReadOwner | QFile::WriteOwner);
QFile publicKeyFile(publicKeyFilePath());
if (!publicKeyFile.open(QIODevice::WriteOnly)
|| !publicKeyFile.write(m_keyGenerator->publicKey())) {
QMessageBox::critical(this, tr("Cannot Save Public Key File"),
tr("The public key file could not be saved: %1").arg(publicKeyFile.errorString()));
return;
}
accept();
}
bool SshKeyCreationDialog::userForbidsOverwriting()
{
if (!QFileInfo::exists(privateKeyFilePath()) && !QFileInfo::exists(publicKeyFilePath()))
return false;
const QMessageBox::StandardButton reply = QMessageBox::question(this, tr("File Exists"),
tr("There already is a file of that name. Do you want to overwrite it?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
return reply != QMessageBox::Yes;
}
QString SshKeyCreationDialog::privateKeyFilePath() const
{
return m_ui->privateKeyFileValueLabel->text();
}
QString SshKeyCreationDialog::publicKeyFilePath() const
{
return m_ui->publicKeyFileLabel->text();
}
} // namespace QSsh

View file

@ -1,264 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QSsh::SshKeyCreationDialog</class>
<widget class="QDialog" name="QSsh::SshKeyCreationDialog">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>380</width>
<height>231</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>SSH Key Configuration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Options</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="keyAlgo">
<property name="text">
<string>Key algorithm:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="rsa">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;RSA</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dsa">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;DSA</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="ecdsa">
<property name="text">
<string>ECDSA</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="keySize">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Key &amp;size:</string>
</property>
<property name="buddy">
<cstring>comboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QComboBox" name="comboBox">
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="privateKeyFileLabel">
<property name="text">
<string>Private key file:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="privateKeyFileValueLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="privateKeyFileButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Public key file:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="publicKeyFileLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="generateButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Generate And Save Key Pair</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Cancel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>closeButton</sender>
<signal>clicked()</signal>
<receiver>QSsh::SshKeyCreationDialog</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>195</x>
<y>184</y>
</hint>
<hint type="destinationlabel">
<x>381</x>
<y>107</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -1,40 +1,48 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshkeyexchange_p.h"
#include "ssh_global.h"
#include "sshbotanconversions_p.h"
#include "sshcapabilities_p.h"
#include "sshlogging_p.h"
#include "sshsendfacility_p.h"
#include "sshexception_p.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include <botan/botan.h>
#include <botan_all.h>
#ifdef CREATOR_SSH_DEBUG
#include <iostream>
#endif
#include <string>
using namespace Botan;
@ -94,22 +102,23 @@ bool SshKeyExchange::sendDhInitPacket(const SshIncomingPacket &serverKexInit)
qCDebug(sshLog, "First packet follows: %d", kexInitParams.firstKexPacketFollows);
m_kexAlgoName = SshCapabilities::findBestMatch(SshCapabilities::KeyExchangeMethods,
kexInitParams.keyAlgorithms.names);
kexInitParams.keyAlgorithms.names,
"KeyExchange");
m_serverHostKeyAlgo = SshCapabilities::findBestMatch(SshCapabilities::PublicKeyAlgorithms,
kexInitParams.serverHostKeyAlgorithms.names);
kexInitParams.serverHostKeyAlgorithms.names, "HostKey");
determineHashingAlgorithm(kexInitParams, true);
determineHashingAlgorithm(kexInitParams, false);
m_encryptionAlgo
= SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
kexInitParams.encryptionAlgorithmsClientToServer.names);
kexInitParams.encryptionAlgorithmsClientToServer.names, "Encryption");
m_decryptionAlgo
= SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
kexInitParams.encryptionAlgorithmsServerToClient.names);
kexInitParams.encryptionAlgorithmsServerToClient.names, "Decryption");
SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
kexInitParams.compressionAlgorithmsClientToServer.names);
kexInitParams.compressionAlgorithmsClientToServer.names, "Compression Client to Server");
SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
kexInitParams.compressionAlgorithmsServerToClient.names);
kexInitParams.compressionAlgorithmsServerToClient.names, "Compression Server to Client");
AutoSeeded_RNG rng;
if (m_kexAlgoName.startsWith(SshCapabilities::EcdhKexNamePrefix)) {
@ -147,36 +156,42 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
printData("Server payload", AbstractSshPacket::encodeString(m_serverKexInitPayload));
printData("K_S", reply.k_s);
AutoSeeded_RNG rng;
SecureVector<byte> encodedK;
if (m_dhKey) {
concatenatedData += AbstractSshPacket::encodeMpInt(m_dhKey->get_y());
concatenatedData += AbstractSshPacket::encodeMpInt(reply.f);
DH_KA_Operation dhOp(*m_dhKey);
SecureVector<byte> encodedF = BigInt::encode(reply.f);
encodedK = dhOp.agree(encodedF, encodedF.size());
std::unique_ptr<PK_Ops::Key_Agreement> dhOp = m_dhKey->create_key_agreement_op(rng, "Raw", "base");
std::vector<byte> encodedF = BigInt::encode(reply.f);
encodedK = dhOp->agree(0, encodedF.data(), encodedF.size(), nullptr, 0);
printData("y", AbstractSshPacket::encodeMpInt(m_dhKey->get_y()));
printData("f", AbstractSshPacket::encodeMpInt(reply.f));
m_dhKey.reset(nullptr);
m_dhKey.reset();
} else {
Q_ASSERT(m_ecdhKey);
concatenatedData // Q_C.
+= AbstractSshPacket::encodeString(convertByteArray(m_ecdhKey->public_value()));
concatenatedData += AbstractSshPacket::encodeString(reply.q_s);
ECDH_KA_Operation ecdhOp(*m_ecdhKey);
encodedK = ecdhOp.agree(convertByteArray(reply.q_s), reply.q_s.count());
m_ecdhKey.reset(nullptr);
std::unique_ptr<PK_Ops::Key_Agreement> ecdhOp = m_ecdhKey->create_key_agreement_op(rng, "Raw", "base");
encodedK = ecdhOp->agree(0, convertByteArray(reply.q_s), reply.q_s.count(), nullptr, 0);
m_ecdhKey.reset();
}
const BigInt k = BigInt::decode(encodedK);
// If we try to just use "BigInt::decode(encodedK)" clang fails to link
const BigInt k = BigInt::decode(encodedK.data(), encodedK.size());
m_k = AbstractSshPacket::encodeMpInt(k); // Roundtrip, as Botan encodes BigInts somewhat differently.
printData("K", m_k);
concatenatedData += m_k;
printData("Concatenated data", concatenatedData);
m_hash.reset(get_hash(botanHMacAlgoName(hashAlgoForKexAlgo())));
m_hash = HashFunction::create_or_throw(botanHMacAlgoName(hashAlgoForKexAlgo()));
const SecureVector<byte> &hashResult = m_hash->process(convertByteArray(concatenatedData),
concatenatedData.size());
m_h = convertByteArray(hashResult);
printData("H", m_h);
QScopedPointer<Public_Key> sigKey;
@ -193,8 +208,8 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
} else {
QSSH_ASSERT_AND_RETURN(m_serverHostKeyAlgo.startsWith(SshCapabilities::PubKeyEcdsaPrefix));
const EC_Group domain(SshCapabilities::oid(m_serverHostKeyAlgo));
const PointGFp point = OS2ECP(convertByteArray(reply.q), reply.q.count(),
domain.get_curve());
const PointGFp point = domain.OS2ECP(convertByteArray(reply.q), reply.q.count());
ECDSA_PublicKey * const ecdsaKey = new ECDSA_PublicKey(domain, point);
sigKey.reset(ecdsaKey);
}
@ -210,6 +225,8 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
checkHostKey(reply.k_s);
m_sendFacility.sendNewKeysPacket();
m_hostFingerprint = QByteArray::fromStdString(sigKey->fingerprint_public("SHA-256"));
}
QByteArray SshKeyExchange::hashAlgoForKexAlgo() const
@ -230,14 +247,16 @@ void SshKeyExchange::determineHashingAlgorithm(const SshKeyExchangeInit &kexInit
const QList<QByteArray> &serverCapabilities = serverToClient
? kexInit.macAlgorithmsServerToClient.names
: kexInit.macAlgorithmsClientToServer.names;
*algo = SshCapabilities::findBestMatch(SshCapabilities::MacAlgorithms, serverCapabilities);
*algo = SshCapabilities::findBestMatch(SshCapabilities::MacAlgorithms,
serverCapabilities,
"MacAlgorithms");
}
void SshKeyExchange::checkHostKey(const QByteArray &hostKey)
{
if (m_connParams.hostKeyCheckingMode == SshHostKeyCheckingNone) {
if (m_connParams.hostKeyDatabase)
m_connParams.hostKeyDatabase->insertHostKey(m_connParams.host, hostKey);
m_connParams.hostKeyDatabase->insertHostKey(m_connParams.host(), hostKey);
return;
}
@ -247,7 +266,7 @@ void SshKeyExchange::checkHostKey(const QByteArray &hostKey)
"if host key checking is enabled."));
}
switch (m_connParams.hostKeyDatabase->matchHostKey(m_connParams.host, hostKey)) {
switch (m_connParams.hostKeyDatabase->matchHostKey(m_connParams.host(), hostKey)) {
case SshHostKeyDatabase::KeyLookupMatch:
return; // Nothing to do.
case SshHostKeyDatabase::KeyLookupMismatch:
@ -259,14 +278,14 @@ void SshKeyExchange::checkHostKey(const QByteArray &hostKey)
throwHostKeyException();
break;
}
m_connParams.hostKeyDatabase->insertHostKey(m_connParams.host, hostKey);
m_connParams.hostKeyDatabase->insertHostKey(m_connParams.host(), hostKey);
}
void SshKeyExchange::throwHostKeyException()
{
throw SshServerException(SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, "Host key changed",
SSH_TR("Host key of machine \"%1\" has changed.")
.arg(m_connParams.host));
.arg(m_connParams.host()));
}
} // namespace Internal

View file

@ -1,35 +1,43 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHKEYEXCHANGE_P_H
#define SSHKEYEXCHANGE_P_H
#include "sshconnection.h"
#include <QByteArray>
#include <QScopedPointer>
#include <memory>
namespace Botan {
class DH_PrivateKey;
class ECDH_PrivateKey;
@ -49,6 +57,7 @@ public:
SshKeyExchange(const SshConnectionParameters &connParams, SshSendFacility &sendFacility);
~SshKeyExchange();
const QByteArray &hostKeyFingerprint() { return m_hostFingerprint; }
void sendKexInitPacket(const QByteArray &serverId);
// Returns true <=> the server sends a guessed package.
@ -59,7 +68,7 @@ public:
QByteArray k() const { return m_k; }
QByteArray h() const { return m_h; }
Botan::HashFunction *hash() const { return m_hash.data(); }
Botan::HashFunction *hash() const { return m_hash.get(); }
QByteArray encryptionAlgo() const { return m_encryptionAlgo; }
QByteArray decryptionAlgo() const { return m_decryptionAlgo; }
QByteArray hMacAlgoClientToServer() const { return m_c2sHMacAlgo; }
@ -84,10 +93,13 @@ private:
QByteArray m_decryptionAlgo;
QByteArray m_c2sHMacAlgo;
QByteArray m_s2cHMacAlgo;
QScopedPointer<Botan::HashFunction> m_hash;
std::unique_ptr<Botan::HashFunction> m_hash;
const SshConnectionParameters m_connParams;
SshSendFacility &m_sendFacility;
QByteArray m_hostFingerprint;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHKEYEXCHANGE_P_H

View file

@ -1,37 +1,42 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshkeygenerator.h"
#include "sshbotanconversions_p.h"
#include "sshcapabilities_p.h"
#include "ssh_global.h"
#include "sshinit_p.h"
#include "sshpacket_p.h"
#include "sshlogging_p.h"
#include <botan/botan.h>
#include <botan_all.h>
#include <QDateTime>
#include <QInputDialog>
@ -45,7 +50,6 @@ using namespace Internal;
SshKeyGenerator::SshKeyGenerator() : m_type(Rsa)
{
initSsh();
}
bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format, int keySize,
@ -84,7 +88,7 @@ bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format, int ke
}
return true;
} catch (const std::exception &e) {
m_error = tr("Error generating key: %1").arg(QString::fromLatin1(e.what()));
m_error = tr("Error generating key: %1").arg(QString::fromLocal8Bit(e.what()));
return false;
}
}
@ -116,8 +120,11 @@ void SshKeyGenerator::generatePkcs8KeyString(const KeyPtr &key, bool privateKey,
}
pipe.end_msg();
keyData->resize(static_cast<int>(pipe.remaining(pipe.message_count() - 1)));
pipe.read(convertByteArray(*keyData), keyData->size(),
size_t readSize = pipe.read(convertByteArray(*keyData), keyData->size(),
pipe.message_count() - 1);
if (readSize != size_t(keyData->size())) {
qCWarning(sshLog, "Didn't manage to read in all key data, only read %lu bytes", readSize);
}
}
void SshKeyGenerator::generateOpenSslKeyStrings(const KeyPtr &key)
@ -146,7 +153,7 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key)
}
case Ecdsa: {
const auto ecdsaKey = key.dynamicCast<ECDSA_PrivateKey>();
q = convertByteArray(EC2OSP(ecdsaKey->public_point(), PointGFp::UNCOMPRESSED));
q = convertByteArray(ecdsaKey->public_point().encode(PointGFp::UNCOMPRESSED));
keyId = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(
static_cast<int>(ecdsaKey->private_value().bytes()));
break;

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHKEYGENERATOR_H
#define SSHKEYGENERATOR_H
#include "ssh_global.h"
@ -73,3 +79,5 @@ private:
};
} // namespace QSsh
#endif // SSHKEYGENERATOR_H

View file

@ -1,28 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshkeypasswordretriever_p.h"
#include <QString>
@ -34,20 +38,17 @@
namespace QSsh {
namespace Internal {
std::string SshKeyPasswordRetriever::get_passphrase(const std::string &, const std::string &,
UI_Result &result) const
std::string SshKeyPasswordRetriever::get_passphrase()
{
const bool hasGui = dynamic_cast<QApplication *>(QApplication::instance());
if (hasGui) {
bool ok;
const QString &password = QInputDialog::getText(0,
const QString &password = QInputDialog::getText(nullptr,
QCoreApplication::translate("QSsh::Ssh", "Password Required"),
QCoreApplication::translate("QSsh::Ssh", "Please enter the password for your private key."),
QLineEdit::Password, QString(), &ok);
result = ok ? OK : CANCEL_ACTION;
return std::string(password.toLocal8Bit().data());
} else {
result = OK;
std::string password;
std::cout << "Please enter the password for your private key (set echo off beforehand!): " << std::flush;
std::cin >> password;

View file

@ -1,43 +1,47 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <botan/botan.h>
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#ifndef KEYPASSWORDRETRIEVER_H
#define KEYPASSWORDRETRIEVER_H
#include <string>
namespace QSsh {
namespace Internal {
class SshKeyPasswordRetriever : public Botan::User_Interface
class SshKeyPasswordRetriever
{
public:
std::string get_passphrase(const std::string &what, const std::string &source,
UI_Result &result) const;
static std::string get_passphrase();
};
} // namespace Internal
} // namespace QSsh
#endif // KEYPASSWORDRETRIEVER_H

View file

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
@ -9,17 +9,22 @@
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
@ -27,6 +32,6 @@
namespace QSsh {
namespace Internal {
Q_LOGGING_CATEGORY(sshLog, "qtc.ssh")
Q_LOGGING_CATEGORY(sshLog, "qtc.ssh", QtWarningMsg)
} // namespace Internal
} // namespace QSsh

View file

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
@ -9,21 +9,27 @@
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#pragma once
#ifndef SSHLOGGING_P_H
#define SSHLOGGING_P_H
#include <QLoggingCategory>
@ -32,3 +38,5 @@ namespace Internal {
Q_DECLARE_LOGGING_CATEGORY(sshLog)
} // namespace Internal
} // namespace QSsh
#endif // Include guard

View file

@ -1,33 +1,40 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshoutgoingpacket_p.h"
#include "sshagent_p.h"
#include "sshcapabilities_p.h"
#include "sshcryptofacility_p.h"
#include "sshlogging_p.h"
#include "sshpacketparser_p.h"
#include <QtEndian>
@ -117,17 +124,41 @@ void SshOutgoingPacket::generateUserAuthByPasswordRequestPacket(const QByteArray
}
void SshOutgoingPacket::generateUserAuthByPublicKeyRequestPacket(const QByteArray &user,
const QByteArray &service)
const QByteArray &service, const QByteArray &key, const QByteArray &signature)
{
init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
.appendString("publickey").appendBool(true)
.appendString(m_encrypter.authenticationAlgorithmName())
.appendString(m_encrypter.authenticationPublicKey());
const QByteArray &dataToSign = m_data.mid(PayloadOffset);
appendString(m_encrypter.authenticationKeySignature(dataToSign));
.appendString("publickey").appendBool(true);
if (!key.isEmpty()) {
appendString(SshPacketParser::asString(key, quint32(0)));
appendString(key);
appendString(signature);
} else {
appendString(m_encrypter.authenticationAlgorithmName());
appendString(m_encrypter.authenticationPublicKey());
const QByteArray &dataToSign = m_data.mid(PayloadOffset);
appendString(m_encrypter.authenticationKeySignature(dataToSign));
}
finalize();
}
void SshOutgoingPacket::generateQueryPublicKeyPacket(const QByteArray &user,
const QByteArray &service, const QByteArray &publicKey)
{
// Name extraction cannot fail, we already verified this when receiving the key
// from the agent.
const QByteArray algoName = SshPacketParser::asString(publicKey, quint32(0));
SshOutgoingPacket packetToSign(m_encrypter, m_seqNr);
packetToSign.init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
.appendString("publickey").appendBool(true).appendString(algoName)
.appendString(publicKey);
const QByteArray &dataToSign
= encodeString(m_encrypter.sessionId()) + packetToSign.m_data.mid(PayloadOffset);
SshAgent::storeDataToSign(publicKey, dataToSign, qHash(m_encrypter.sessionId()));
init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
.appendString("publickey").appendBool(false).appendString(algoName)
.appendString(publicKey).finalize();
}
void SshOutgoingPacket::generateUserAuthByKeyboardInteractiveRequestPacket(const QByteArray &user,
const QByteArray &service)
{
@ -199,6 +230,14 @@ void SshOutgoingPacket::generateEnvPacket(quint32 remoteChannel,
.appendBool(false).appendString(var).appendString(value).finalize();
}
void SshOutgoingPacket::generateX11ForwardingPacket(quint32 remoteChannel,
const QByteArray &protocol, const QByteArray &cookie, quint32 screenNumber)
{
init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel).appendString("x11-req")
.appendBool(false).appendBool(false).appendString(protocol)
.appendString(cookie).appendInt(screenNumber).finalize();
}
void SshOutgoingPacket::generatePtyRequestPacket(quint32 remoteChannel,
const SshPseudoTerminal &terminal)
{

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHOUTGOINGPACKET_P_H
#define SSHOUTGOINGPACKET_P_H
#include "sshpacket_p.h"
@ -53,7 +59,9 @@ public:
void generateUserAuthByPasswordRequestPacket(const QByteArray &user,
const QByteArray &service, const QByteArray &pwd);
void generateUserAuthByPublicKeyRequestPacket(const QByteArray &user,
const QByteArray &service);
const QByteArray &service, const QByteArray &key, const QByteArray &signature);
void generateQueryPublicKeyPacket(const QByteArray &user, const QByteArray &service,
const QByteArray &publicKey);
void generateUserAuthByKeyboardInteractiveRequestPacket(const QByteArray &user,
const QByteArray &service);
void generateUserAuthInfoResponsePacket(const QStringList &responses);
@ -69,6 +77,8 @@ public:
void generateCancelTcpIpForwardPacket(const QByteArray &bindAddress, quint32 bindPort);
void generateEnvPacket(quint32 remoteChannel, const QByteArray &var,
const QByteArray &value);
void generateX11ForwardingPacket(quint32 remoteChannel, const QByteArray &protocol,
const QByteArray &cookie, quint32 screenNumber);
void generatePtyRequestPacket(quint32 remoteChannel,
const SshPseudoTerminal &terminal);
void generateExecPacket(quint32 remoteChannel, const QByteArray &command);
@ -111,3 +121,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SSHOUTGOINGPACKET_P_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshpacket_p.h"

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHPACKET_P_H
#define SSHPACKET_P_H
#include "sshexception_p.h"
@ -145,3 +151,5 @@ protected:
} // namespace Internal
} // namespace QSsh
#endif // SSHPACKET_P_H

View file

@ -1,31 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshpacketparser_p.h"
#include <cctype>
#include <QtEndian>
namespace QSsh {
namespace Internal {
@ -63,10 +69,7 @@ quint32 SshPacketParser::asUint32(const QByteArray &data, quint32 offset)
{
if (size(data) < offset + 4)
throw SshPacketParseException();
const quint32 value = ((data.at(offset) & 0xff) << 24)
+ ((data.at(offset + 1) & 0xff) << 16)
+ ((data.at(offset + 2) & 0xff) << 8) + (data.at(offset + 3) & 0xff);
return value;
return qFromBigEndian<quint32>(data.constData() + offset);
}
quint32 SshPacketParser::asUint32(const QByteArray &data, quint32 *offset)
@ -80,15 +83,7 @@ quint64 SshPacketParser::asUint64(const QByteArray &data, quint32 offset)
{
if (size(data) < offset + 8)
throw SshPacketParseException();
const quint64 value = (static_cast<quint64>(data.at(offset) & 0xff) << 56)
+ (static_cast<quint64>(data.at(offset + 1) & 0xff) << 48)
+ (static_cast<quint64>(data.at(offset + 2) & 0xff) << 40)
+ (static_cast<quint64>(data.at(offset + 3) & 0xff) << 32)
+ ((data.at(offset + 4) & 0xff) << 24)
+ ((data.at(offset + 5) & 0xff) << 16)
+ ((data.at(offset + 6) & 0xff) << 8)
+ (data.at(offset + 7) & 0xff);
return value;
return qFromBigEndian<quint64>(data.constData() + offset);
}
quint64 SshPacketParser::asUint64(const QByteArray &data, quint32 *offset)
@ -98,6 +93,11 @@ quint64 SshPacketParser::asUint64(const QByteArray &data, quint32 *offset)
return val;
}
QByteArray SshPacketParser::asString(const QByteArray &data, quint32 offset)
{
return asString(data, &offset);
}
QByteArray SshPacketParser::asString(const QByteArray &data, quint32 *offset)
{
const quint32 length = asUint32(data, offset);

View file

@ -1,31 +1,37 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHPACKETPARSER_P_H
#define SSHPACKETPARSER_P_H
#include <botan/botan.h>
#include <botan_all.h>
#include <QByteArray>
#include <QList>
@ -62,6 +68,7 @@ public:
static quint64 asUint64(const QByteArray &data, quint32 *offset);
static quint32 asUint32(const QByteArray &data, quint32 offset);
static quint32 asUint32(const QByteArray &data, quint32 *offset);
static QByteArray asString(const QByteArray &data, quint32 offset);
static QByteArray asString(const QByteArray &data, quint32 *offset);
static QString asUserString(const QByteArray &data, quint32 *offset);
static SshNameList asNameList(const QByteArray &data, quint32 *offset);
@ -72,3 +79,5 @@ public:
} // namespace Internal
} // namespace QSsh
#endif // SSHPACKETPARSER_P_H

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHPSEUDOTERMINAL_H
#define SSHPSEUDOTERMINAL_H
#include "ssh_global.h"
@ -108,3 +114,5 @@ class QSSH_EXPORT SshPseudoTerminal
};
} // namespace QSsh
#endif // SSHPSEUDOTERMINAL_H

View file

@ -1,57 +1,49 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshremoteprocess.h"
#include "sshremoteprocess_p.h"
#include "sshlogging_p.h"
#include "ssh_global.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include "sshsendfacility_p.h"
#include "sshx11displayinfo_p.h"
#include <botan/botan.h>
#include <botan_all.h>
#include <QTimer>
#include <cstring>
#include <cstdlib>
/*!
\class QSsh::SshRemoteProcess
\brief The SshRemoteProcess class implements an SSH channel for running a
remote process.
Objects are created via SshConnection::createRemoteProcess.
The process is started via the start() member function.
If the process needs a pseudo terminal, you can request one
via requestTerminal() before calling start().
Note that this class does not support QIODevice's waitFor*() functions, i.e. it has
no synchronous mode.
*/
namespace QSsh {
const struct {
@ -83,7 +75,7 @@ SshRemoteProcess::SshRemoteProcess(quint32 channelId, Internal::SshSendFacility
SshRemoteProcess::~SshRemoteProcess()
{
QSSH_ASSERT(d->channelState() != Internal::AbstractSshChannel::SessionEstablished);
close();
SshRemoteProcess::close();
delete d;
}
@ -188,6 +180,12 @@ void SshRemoteProcess::requestTerminal(const SshPseudoTerminal &terminal)
d->m_terminal = terminal;
}
void SshRemoteProcess::requestX11Forwarding(const QString &displayName)
{
QSSH_ASSERT_AND_RETURN(d->channelState() == Internal::SshRemoteProcessPrivate::Inactive);
d->m_x11DisplayName = displayName;
}
void SshRemoteProcess::start()
{
if (d->channelState() == Internal::SshRemoteProcessPrivate::Inactive) {
@ -201,7 +199,7 @@ void SshRemoteProcess::sendSignal(Signal signal)
{
try {
if (isRunning()) {
const char *signalString = 0;
const char *signalString = nullptr;
for (size_t i = 0; i < sizeof signalMap/sizeof *signalMap && !signalString; ++i) {
if (signalMap[i].signalEnum == signal)
signalString = signalMap[i].signalString;
@ -210,7 +208,7 @@ void SshRemoteProcess::sendSignal(Signal signal)
d->m_sendFacility.sendChannelSignalPacket(d->remoteChannel(), signalString);
}
} catch (const std::exception &e) {
setErrorString(QString::fromLatin1(e.what()));
setErrorString(QString::fromLocal8Bit(e.what()));
d->closeChannel();
}
}
@ -229,6 +227,14 @@ SshRemoteProcess::Signal SshRemoteProcess::exitSignal() const
namespace Internal {
void SshRemoteProcessPrivate::failToStart(const QString &reason)
{
if (m_procState != NotYetStarted)
return;
m_proc->setErrorString(reason);
setProcState(StartFailed);
}
SshRemoteProcessPrivate::SshRemoteProcessPrivate(const QByteArray &command,
quint32 channelId, SshSendFacility &sendFacility, SshRemoteProcess *proc)
: AbstractSshChannel(channelId, sendFacility),
@ -288,26 +294,41 @@ void SshRemoteProcessPrivate::closeHook()
void SshRemoteProcessPrivate::handleOpenSuccessInternal()
{
foreach (const EnvVar &envVar, m_env) {
m_sendFacility.sendEnvPacket(remoteChannel(), envVar.first,
envVar.second);
}
if (m_x11DisplayName.isEmpty())
startProcess(X11DisplayInfo());
else
emit x11ForwardingRequested(m_x11DisplayName);
}
if (m_useTerminal)
m_sendFacility.sendPtyRequestPacket(remoteChannel(), m_terminal);
void SshRemoteProcessPrivate::startProcess(const X11DisplayInfo &displayInfo)
{
if (m_procState != NotYetStarted)
return;
if (m_isShell)
m_sendFacility.sendShellPacket(remoteChannel());
else
m_sendFacility.sendExecPacket(remoteChannel(), m_command);
setProcState(ExecRequested);
m_timeoutTimer.start(ReplyTimeout);
foreach (const EnvVar &envVar, m_env) {
m_sendFacility.sendEnvPacket(remoteChannel(), envVar.first,
envVar.second);
}
if (!m_x11DisplayName.isEmpty()) {
m_sendFacility.sendX11ForwardingPacket(remoteChannel(), displayInfo.protocol,
displayInfo.randomCookie.toHex(), 0);
}
if (m_useTerminal)
m_sendFacility.sendPtyRequestPacket(remoteChannel(), m_terminal);
if (m_isShell)
m_sendFacility.sendShellPacket(remoteChannel());
else
m_sendFacility.sendExecPacket(remoteChannel(), m_command);
setProcState(ExecRequested);
m_timeoutTimer.start(ReplyTimeout);
}
void SshRemoteProcessPrivate::handleOpenFailureInternal(const QString &reason)
{
setProcState(StartFailed);
m_proc->setErrorString(reason);
failToStart(reason);
}
void SshRemoteProcessPrivate::handleChannelSuccess()

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHREMOTECOMMAND_H
#define SSHREMOTECOMMAND_H
#include "ssh_global.h"
@ -42,6 +48,19 @@ class SshRemoteProcessPrivate;
class SshSendFacility;
} // namespace Internal
/*!
\class QSsh::SshRemoteProcess
\brief This class implements an SSH channel for running a remote process.
Objects are created via SshConnection::createRemoteProcess.
The process is started via the start() member function.
If the process needs a pseudo terminal, you can request one
via requestTerminal() before calling start().
Note that this class does not support QIODevice's waitFor*() functions, i.e. it has
no synchronous mode.
*/
// TODO: ProcessChannel
class QSSH_EXPORT SshRemoteProcess : public QIODevice
{
@ -78,6 +97,7 @@ public:
void clearEnvironment();
void requestTerminal(const SshPseudoTerminal &terminal);
void requestX11Forwarding(const QString &displayName);
void start();
bool isRunning() const;
@ -119,3 +139,5 @@ private:
};
} // namespace QSsh
#endif // SSHREMOTECOMMAND_H

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHREMOTEPROCESS_P_H
#define SSHREMOTEPROCESS_P_H
#include "sshpseudoterminal.h"
@ -38,6 +44,7 @@ class SshRemoteProcess;
namespace Internal {
class SshSendFacility;
class X11DisplayInfo;
class SshRemoteProcessPrivate : public AbstractSshChannel
{
@ -48,12 +55,16 @@ public:
NotYetStarted, ExecRequested, StartFailed, Running, Exited
};
void failToStart(const QString &reason);
void startProcess(const X11DisplayInfo &displayInfo);
signals:
void started();
void readyRead();
void readyReadStandardOutput();
void readyReadStandardError();
void closed(int exitStatus);
void x11ForwardingRequested(const QString &display);
private:
SshRemoteProcessPrivate(const QByteArray &command, quint32 channelId,
@ -93,6 +104,8 @@ private:
bool m_useTerminal;
SshPseudoTerminal m_terminal;
QString m_x11DisplayName;
QByteArray m_stdout;
QByteArray m_stderr;
@ -101,3 +114,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SSHREMOTEPROCESS_P_H

View file

@ -1,41 +1,38 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshremoteprocessrunner.h"
#include "sshconnectionmanager.h"
#include "sshpseudoterminal.h"
/*!
\class QSsh::SshRemoteProcessRunner
\brief The SshRemoteProcessRunner class is a convenience class for
running a remote process over an SSH connection.
*/
namespace QSsh {
namespace Internal {
namespace {
@ -206,14 +203,14 @@ void SshRemoteProcessRunner::setState(int newState)
d->m_state = static_cast<State>(newState);
if (d->m_state == Inactive) {
if (d->m_process) {
disconnect(d->m_process.data(), 0, this, 0);
disconnect(d->m_process.data(), nullptr, this, nullptr);
d->m_process->close();
d->m_process.clear();
}
if (d->m_connection) {
disconnect(d->m_connection, 0, this, 0);
disconnect(d->m_connection, nullptr, this, nullptr);
QSsh::releaseConnection(d->m_connection);
d->m_connection = 0;
d->m_connection = nullptr;
}
}
}

View file

@ -1,42 +1,56 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHREMOTEPROCESSRUNNER_H
#define SSHREMOTEPROCESSRUNNER_H
#include "sshconnection.h"
#include "sshremoteprocess.h"
namespace QSsh {
namespace Internal { class SshRemoteProcessRunnerPrivate; }
namespace Internal {
class SshRemoteProcessRunnerPrivate;
} // namespace Internal
/*!
\class QSsh::SshRemoteProcessRunner
\brief Convenience class for running a remote process over an SSH connection.
*/
class QSSH_EXPORT SshRemoteProcessRunner : public QObject
{
Q_OBJECT
public:
SshRemoteProcessRunner(QObject *parent = 0);
SshRemoteProcessRunner(QObject *parent = nullptr);
~SshRemoteProcessRunner();
void run(const QByteArray &command, const SshConnectionParameters &sshParams);
@ -80,3 +94,5 @@ private:
};
} // namespace QSsh
#endif // SSHREMOTEPROCESSRUNNER_H

View file

@ -1,27 +1,32 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#include "sshsendfacility_p.h"
@ -118,9 +123,16 @@ void SshSendFacility::sendUserAuthByPasswordRequestPacket(const QByteArray &user
}
void SshSendFacility::sendUserAuthByPublicKeyRequestPacket(const QByteArray &user,
const QByteArray &service)
const QByteArray &service, const QByteArray &key, const QByteArray &signature)
{
m_outgoingPacket.generateUserAuthByPublicKeyRequestPacket(user, service);
m_outgoingPacket.generateUserAuthByPublicKeyRequestPacket(user, service, key, signature);
sendPacket();
}
void SshSendFacility::sendQueryPublicKeyPacket(const QByteArray &user, const QByteArray &service,
const QByteArray &publicKey)
{
m_outgoingPacket.generateQueryPublicKeyPacket(user, service, publicKey);
sendPacket();
}
@ -198,6 +210,13 @@ void SshSendFacility::sendEnvPacket(quint32 remoteChannel,
sendPacket();
}
void SshSendFacility::sendX11ForwardingPacket(quint32 remoteChannel, const QByteArray &protocol,
const QByteArray &cookie, quint32 screenNumber)
{
m_outgoingPacket.generateX11ForwardingPacket(remoteChannel, protocol, cookie, screenNumber);
sendPacket();
}
void SshSendFacility::sendExecPacket(quint32 remoteChannel,
const QByteArray &command)
{

View file

@ -1,29 +1,35 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSHCONNECTIONOUTSTATE_P_H
#define SSHCONNECTIONOUTSTATE_P_H
#include "sshcryptofacility_p.h"
#include "sshoutgoingpacket_p.h"
@ -49,6 +55,8 @@ public:
void recreateKeys(const SshKeyExchange &keyExchange);
void createAuthenticationKey(const QByteArray &privKeyFileContents);
QByteArray sessionId() const { return m_encrypter.sessionId(); }
QByteArray sendKeyExchangeInitPacket();
void sendKeyDhInitPacket(const Botan::BigInt &e);
void sendKeyEcdhInitPacket(const QByteArray &clientQ);
@ -60,7 +68,9 @@ public:
void sendUserAuthByPasswordRequestPacket(const QByteArray &user,
const QByteArray &service, const QByteArray &pwd);
void sendUserAuthByPublicKeyRequestPacket(const QByteArray &user,
const QByteArray &service);
const QByteArray &service, const QByteArray &key, const QByteArray &signature);
void sendQueryPublicKeyPacket(const QByteArray &user, const QByteArray &service,
const QByteArray &publicKey);
void sendUserAuthByKeyboardInteractiveRequestPacket(const QByteArray &user,
const QByteArray &service);
void sendUserAuthInfoResponsePacket(const QStringList &responses);
@ -78,6 +88,8 @@ public:
const SshPseudoTerminal &terminal);
void sendEnvPacket(quint32 remoteChannel, const QByteArray &var,
const QByteArray &value);
void sendX11ForwardingPacket(quint32 remoteChannel, const QByteArray &protocol,
const QByteArray &cookie, quint32 screenNumber);
void sendExecPacket(quint32 remoteChannel, const QByteArray &command);
void sendShellPacket(quint32 remoteChannel);
void sendSftpPacket(quint32 remoteChannel);
@ -93,6 +105,8 @@ public:
const QByteArray &reasonString);
quint32 nextClientSeqNr() const { return m_clientSeqNr; }
bool encrypterIsValid() const { return m_encrypter.isValid(); }
private:
void sendPacket();
@ -104,3 +118,5 @@ private:
} // namespace Internal
} // namespace QSsh
#endif // SSHCONNECTIONOUTSTATE_P_H

Some files were not shown because too many files have changed in this diff Show more