Compare commits

...

516 Commits

Author SHA1 Message Date
vityazaychek
34ddeb2563 Merge pull request #246 from tcoreal/nextcloud-from-dev
Nextcloud from dev
2023-05-25 13:41:32 +02:00
Evgenii Muravev
1674a66a3c Removed redundant comments 2023-05-25 00:54:31 +02:00
Viacheslav Sergeev
7a6905f6bf install docker-compose under the separate condition 2023-05-24 19:37:40 +02:00
Viacheslav Sergeev
345cf6cf49 install docker-compose together with docker 2023-05-24 19:37:40 +02:00
Viacheslav Sergeev
5f3dbf0bdd forward container configuration, and allow to override $NEXTCLOUD_PORT 2023-05-24 19:37:40 +02:00
Viacheslav Sergeev
5c167e426d Added working nextcloud installation 2023-05-24 19:37:40 +02:00
Igor Bronshtein
6513ecfa99 Fix Nextcloud logic in UI
Now the port value from UI should be assigned to the attribute NextcloudLogic object.
2023-05-24 19:37:22 +02:00
Viacheslav Sergeev
0099e642f3 changes from previous fork (vityazaychek/amnezia-client) 2023-05-24 19:33:48 +02:00
Mykola Baibuz
780efc2477 OpenVPN over Cloak for Android and iOS (#158)
OpenVPN over Cloak for Android and iOS
2023-05-23 23:50:36 +01:00
pokamest
7f02fe4157 Merge pull request #244 from amnezia-vpn/bugfix/ios_import_configs
Import configs for iOS
2023-05-23 08:10:46 -07:00
pokamest
f722576bf2 Merge pull request #241 from amnezia-vpn/bugfix/cloak_for_desktops_fix
Fixes for Cloak proto
2023-05-23 08:00:15 -07:00
pokamest
7fecc2cf4c Merge pull request #242 from i-ky/badge-link
Make build status badge into a link
2023-05-23 07:54:02 -07:00
pokamest
3519e070b4 Merge pull request #243 from i-ky/linguist
Mark client/3rd/ as vendored code
2023-05-23 07:53:17 -07:00
i-ky
25d7e121c9 Mark client/3rd/ as vendored code 2023-05-22 14:21:02 +03:00
i-ky
882077f0aa Make build status badge into a link 2023-05-22 13:30:03 +03:00
pokamest
b5b69ff369 Fixes for Cloak proto 2023-05-20 18:44:19 +01:00
i-ky
f0ad76fff6 Gitpod integration (#240)
Add Gitpod configuration
2023-05-20 15:55:19 +01:00
amnezia-developer
e651ea7614 Add Qt Multimedia to project (#236)
Add Qt Multimedia to iOS cmake project
2023-05-17 20:38:28 +01:00
pokamest
230f44f4e6 Import configs for iOS [WIP] 2023-05-15 17:57:35 -07:00
Nethius
19c42490e3 feature/versioning-for-desktop (#181)
Project refactoring and cleanup
2023-05-16 01:34:06 +01:00
Mykola Baibuz
8a8d38a30f Prevent ipv6 leak (#224)
Prevent ipv6 leak for OpenVPN
2023-04-25 16:34:17 +01:00
pokamest
6429ff0603 Merge pull request #228 from amnezia-vpn/bugfix/openvpn-crl-verify
bugfix/openvpn-crl-verify
2023-04-21 12:43:35 +01:00
vladimir.kuznetsov
f5057dfac4 removed crl-verify from client config
- specified full path to crl in server config
- added crl generation when setting up a container
2023-04-21 07:44:35 +03:00
pokamest
00d61def0b Merge pull request #226 from amnezia-vpn/bugfix/sftp-files-permissions
bugfix/sftp-files-permissions
2023-04-19 16:19:47 +01:00
vladimir.kuznetsov
f5a26c7116 set the value S_IRWXU for windows, so that when copying via sftp, the necessary permissions for the file are set 2023-04-19 17:58:03 +03:00
pokamest
54fba99bed Merge pull request #225 from amnezia-vpn/bugfix/tcp-port-busy-check
in the port busy check, for tcp now only LISTEN ports are checked
2023-04-19 14:09:49 +01:00
vladimir.kuznetsov
7216a8b923 in the port busy check, for tcp now only LISTEN ports are checked 2023-04-19 06:39:50 +03:00
pokamest
97e322ba22 Merge pull request #223 from amnezia-vpn/bugfix/tcp-port-busy-check
in the port busy check, for tcp only the local port is now checked
2023-04-18 18:26:59 +01:00
vladimir.kuznetsov
fc603f11ce in the port busy check, for tcp only the local port is now checked 2023-04-18 20:00:40 +03:00
pokamest
10bca290c3 Merge pull request #221 from amnezia-vpn/bugfix/check-sudo-for-root
skipping sudo check for root user
2023-04-18 11:54:29 +01:00
vladimir.kuznetsov
3dabaeb2c9 skipping sudo check for root user 2023-04-18 05:48:37 +03:00
pokamest
cf74b879c6 Merge pull request #219 from amnezia-vpn/change/client-management-update-page
change/client-management-update-page
2023-04-16 14:41:28 +01:00
vladimir.kuznetsov
0ae2a1f177 now, when onUpdateAllPages is called, the ClientInfoLogic and ClientManagementLogic pages will not be updated
- moved the Client Management button to the Advanced Settings page
-
2023-04-16 07:32:32 +03:00
pokamest
af29637163 Merge branch 'dev' 2023-04-11 18:00:54 +01:00
Josh Soref
7351fe9633 Spelling (#214)
Spelling fixed
2023-04-11 14:50:44 +01:00
pokamest
1a6b4a1188 Merge pull request #213 from amnezia-vpn/chore/qtssh-gitmodules
removed qtssh from gitmodules
2023-04-11 02:00:34 +01:00
vladimir.kuznetsov
8751dd3797 removed qtssh from gitmodules 2023-04-09 05:47:27 +03:00
pokamest
9a6df25280 Merge pull request #149 from amnezia-vpn/feature/qt6-client-management-panel
feature/qt6-client-management-panel
2023-04-08 19:33:09 +01:00
vladimir.kuznetsov
ada8912a1f Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/qt6-client-management-panel 2023-04-08 19:03:10 +03:00
pokamest
de4245025c Merge pull request #189 from amnezia-vpn/feature/check-user-in-sudo
feature/check-user-in-sudo
2023-04-08 16:38:00 +01:00
vladimir.kuznetsov
f620f4a92e Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/check-user-in-sudo 2023-04-08 17:12:23 +03:00
pokamest
2ca85c7829 Merge pull request #212 from bakhtiyork/feature/qt6-libssh-support
CI/CD iOS build fix
2023-04-07 17:23:31 +01:00
bakhtiyork
8374404b0f iOS - cmake: disabling testing and programs 2023-04-07 11:21:44 +05:00
pokamest
c453c6c294 Merge pull request #139 from amnezia-vpn/feature/qt6-libssh-support
feature/qt6-libssh-support
2023-04-06 20:09:03 +01:00
pokamest
a5e5c3d941 Merge pull request #210 from amnezia-vpn/dev
Pre-release 3.0.4
2023-04-06 20:05:51 +01:00
pokamest
c242a08653 Merge pull request #193 from bakhtiyork/feature/qt6-libssh-support
iOS - libssh with mbedtls build
2023-04-06 18:04:25 +01:00
bakhtiyork
f931603203 Disabling symbol versioning for iOS 2023-04-06 20:33:12 +05:00
bakhtiyork
ef03a3d9d4 FindMbedTLS.cmake - adding mbedtls targets export 2023-04-06 05:59:42 +05:00
vladimir.kuznetsov
ccfc9f2ad2 added error handling for key authentication 2023-04-05 09:45:03 +03:00
vladimir.kuznetsov
b3456ee96c fixed variable name in addAlreadyInstalledContainersGui() function 2023-04-05 06:20:10 +03:00
vladimir.kuznetsov
05cd4ac14b Merge branch 'feature/qt6-libssh-support' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-04-05 06:08:15 +03:00
vladimir.kuznetsov
ba2ecf9789 fixed cleanup of private/public keys after use 2023-04-05 06:07:36 +03:00
pokamest
020e6b1cb3 Merge branch 'dev' into feature/qt6-libssh-support 2023-04-05 03:40:55 +01:00
pokamest
2a7365730b getOpenFileName fix 2023-04-05 03:39:05 +01:00
pokamest
ad77d74f4b Merge branch 'dev' into feature/qt6-libssh-support 2023-04-05 03:26:08 +01:00
pokamest
ef8668dce4 Merge pull request #205 from amnezia-vpn/fix/build_desktop_on_apple_silicon
Fix to build Amnezia desktop app on Apple Silicon
2023-04-05 01:51:31 +01:00
pokamest
3fb34e28a4 Merge pull request #207 from amnezia-vpn/bugfix/add-server-with-same-credentials
bugfix/add-server-with-same-credentials
2023-04-05 01:50:11 +01:00
pokamest
871214f907 Merge pull request #206 from amnezia-vpn/bugfix/server-busy-default-port
bugfix/server-busy-default-port
2023-04-05 01:48:20 +01:00
pokamest
7e717754a3 getOpenFileName fix for Android 2023-04-05 01:43:42 +01:00
vladimir.kuznetsov
6e67946ae2 Removed the ability to add multiple servers with the same connection credentials via the "Add server" button 2023-04-04 19:13:39 +03:00
vladimir.kuznetsov
48d673c853 fixed getting default port and default transport protocol in isServerPortBusy function 2023-04-04 18:20:19 +03:00
Dmitriy Karpushin
a9bb6f8099 Fix to build at least x86_64 version of Amnezia desktop app on Apple Silicon 2023-04-04 17:10:58 +03:00
vladimir.kuznetsov
f8ef69b88a removed setPassphraseCallback() function from ServerController and libssh::Client 2023-04-04 13:32:37 +03:00
vladimir.kuznetsov
a005ed2a84 now an instance of the serverController class is created at the place of use 2023-04-04 10:22:25 +03:00
vladimir.kuznetsov
1aa859b10d moved passphraseCallback and passphraseDialog to startPage
- made some methods of the servercontroller class private
- returned a call to the checkSshConnection() function
2023-04-04 07:09:30 +03:00
vladimir.kuznetsov
4aba34c18b Merge remote-tracking branch 'remotes/origin/dev' into feature/qt6-libssh-support 2023-04-03 17:48:55 +03:00
vladimir.kuznetsov
5e099f522e added private key export without password to client config 2023-04-03 17:27:55 +03:00
pokamest
15c33014e7 Merge pull request #198 from amnezia-vpn/bugfix/qssh-too-many-open-connections
bugfix/qssh-too-many-open-connections
2023-04-02 13:43:30 +01:00
vladimir.kuznetsov
af5b9172ef removed unused disconnectFromHost() from ServerController 2023-04-02 15:19:59 +03:00
bakhtiyork
fe9e813c79 Custom cmake module path 2023-04-02 17:19:21 +05:00
vladimir.kuznetsov
51d7cdfd31 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into bugfix/qssh-too-many-open-connections 2023-04-02 14:48:26 +03:00
vladimir.kuznetsov
f3aef67be6 Added a form for entering a passphrase for a private ssh key and the corresponding logic for processing a private key 2023-04-02 09:09:20 +03:00
pokamest
449af8060a Merge pull request #204 from amnezia-vpn/fix/android_config_import
Android config import
2023-03-29 22:16:16 +01:00
pokamest
fa19f1f5a0 Merge pull request #200 from amnezia-vpn/bugfix/empty-server-list-settings-availability
bugfix/empty-server-list-settings-availability
2023-03-29 15:17:25 +02:00
Dmitriy Karpushin
9e461ef6e1 Fixed import from external applications 2023-03-29 16:16:54 +03:00
pokamest
1ba301ed16 Merge pull request #201 from amnezia-vpn/bugfix/reset-container-settings-after-adding-new-one
bugfix/reset-container-settings-after-adding-new-one
2023-03-29 15:16:34 +02:00
pokamest
7e663b05d5 Merge pull request #202 from amnezia-vpn/fix/android_various_fixes
Fix/android various fixes
2023-03-29 15:15:17 +02:00
Dmitriy Karpushin
2225a735ca Fixed typo 2023-03-29 12:01:18 +03:00
Dmitriy Karpushin
90c8fbb495 Update Room to fix build on Apple M1 2023-03-29 09:53:18 +03:00
vladimir.kuznetsov
2b14efd3f8 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into bugfix/qssh-too-many-open-connections 2023-03-29 09:44:28 +03:00
vladimir.kuznetsov
3261c36f97 changed the existsAnyServer value to properly display locked settings 2023-03-29 09:44:06 +03:00
vladimir.kuznetsov
c48d65525a set m_installCredentials when visiting the ServerContainers page 2023-03-29 09:44:00 +03:00
vladimir.kuznetsov
5fa6e755b2 changed the existsAnyServer value to properly display locked settings 2023-03-29 09:39:56 +03:00
vladimir.kuznetsov
8bbc0b9e1a set m_installCredentials when visiting the ServerContainers page 2023-03-29 09:38:00 +03:00
Dmitriy Karpushin
3a5317f16a Implementation of "migration manager" to fix placement of config files issue appeared after moving from Qt 5 to Qt 6 2023-03-29 09:31:24 +03:00
Dmitriy Karpushin
c0bb06bf49 Fix of copying to clipboard 2023-03-29 09:31:12 +03:00
Dmitriy Karpushin
8d45af2034 Files now saving with the file picker, not with the sharing mechanism 2023-03-29 09:31:02 +03:00
Dmitriy Karpushin
5f85bf62f5 Missing def check 2023-03-29 09:30:52 +03:00
Dmitriy Karpushin
8fa409d6c1 Restoration of bandwidth meter after closing of GUI 2023-03-29 09:30:45 +03:00
Dmitriy Karpushin
7167c2f20d Fix of "Connect" button state after restoring of an app 2023-03-29 09:29:55 +03:00
Dmitriy Karpushin
20846c8eff * correct behavior of back button on Android
* removing of annoying debug logs on Android
2023-03-29 09:29:06 +03:00
pokamest
1b44a01efd Merge pull request #195 from cyBerta/focus
Camera focus when reading QR
2023-03-28 15:21:54 +02:00
pokamest
c4104dcd33 Merge pull request #196 from cyBerta/android_dev_onboarding
Android dev onboarding documentation
2023-03-28 15:20:53 +02:00
vladimir.kuznetsov
c319c3f520 changed the way to get QSsh::SshConnection, now all resources are cleaned up after use, but the disconnectFromHost function becomes useless 2023-03-27 08:17:41 +03:00
cyberta
85025695df add a section about how to get started for Android developers 2023-03-26 13:59:12 +02:00
vladimir.kuznetsov
f6ca22ecdd Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-03-26 11:52:22 +03:00
cyberta
8d9594ba36 add auto-focus to CameraActivity 2023-03-25 23:56:55 +01:00
pokamest
fe7c66cf1d Merge pull request #194 from amnezia-vpn/bugfix/clear-server-from-amnezia
bugfix/clear-server-from-amnezia
2023-03-25 13:33:23 +00:00
vladimir.kuznetsov
b5aa940701 added removal of stopped containers 2023-03-25 15:50:12 +03:00
bakhtiyork
698dfb67d1 iOS - libssh with mbedtls build 2023-03-24 11:41:27 +05:00
pokamest
38f2f1a3e4 Merge pull request #179 from amnezia-vpn/feature/linux-wireguard-implementation
feature/linux-wireguard-implementation
2023-03-21 23:49:39 +00:00
pokamest
b98c6ca5c5 Merge pull request #192 from amnezia-vpn/bugfix/check-server-port-on-dns-container
bugfix/check-server-port-on-dns-container
2023-03-21 23:08:03 +00:00
vladimir.kuznetsov
5641874811 added skip port busy check for DNS container.
- added script execution error check when checking ports busy
2023-03-20 17:29:23 +03:00
pokamest
1dd34035c9 Merge pull request #190 from amnezia-vpn/bugfix/empty-port-when-check-server-ports
bugfix/empty-port-when-check-server-ports
2023-03-20 12:50:08 +00:00
vladimir.kuznetsov
6bf170e273 Merge branch 'bugfix/empty-port-when-check-server-ports' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-03-20 08:53:00 +03:00
vladimir.kuznetsov
084ac9b916 added a default port if it is not in the config when scanning the server for busy ports 2023-03-20 08:50:57 +03:00
vladimir.kuznetsov
cebf061f85 Merge branch 'feature/qt6-libssh-support' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-03-20 05:47:37 +03:00
vladimir.kuznetsov
5641db0026 uncommented static link for qtkeychain 2023-03-20 05:45:53 +03:00
vladimir.kuznetsov
a42ec8eddb Merge branch 'feature/qt6-libssh-support' of github.com:amnezia-vpn/desktop-client into feature/check-user-in-sudo 2023-03-19 18:04:55 +03:00
vladimir.kuznetsov
ea9917dacc added a script to check the user in the sudo group
- move isServerDpkgBusy to separate script
2023-03-19 17:26:43 +03:00
vladimir.kuznetsov
6272ae842c Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-03-19 17:23:18 +03:00
vladimir.kuznetsov
b000eda126 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-client-management-panel 2023-03-19 17:15:13 +03:00
vladimir.kuznetsov
9962bac50b changed using cp to QFile to copy wireguard config 2023-03-19 17:05:48 +03:00
vladimir.kuznetsov
f0c3f1b9ba Merge branch 'feature/linux-wireguard-implementation' of github.com:amnezia-vpn/desktop-client into feature/linux-wireguard-implementation 2023-03-19 15:32:07 +03:00
vladimir.kuznetsov
ec8eeef428 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/linux-wireguard-implementation 2023-03-19 15:06:17 +03:00
pokamest
7eb1a4b489 Fixed certutil path on Windows 2023-03-19 11:58:22 +00:00
pokamest
23b23f0e38 Merge branch 'dev' into feature/linux-wireguard-implementation 2023-03-17 16:18:56 +00:00
pokamest
cba78190a8 iOS build fix 2023-03-16 11:43:18 -07:00
pokamest
e097a49186 Merge pull request #184 from amnezia-vpn/bugfix/fake-web-site-label-wizard
bugfix/fake-web-site-label-wizard
2023-03-16 16:57:29 +00:00
pokamest
e895c784c7 Merge pull request #183 from amnezia-vpn/bugfix/installed-container-button
bugfix/installed-container-button
2023-03-16 16:56:30 +00:00
vladimir.kuznetsov
7e1bcf84f0 fixed saving site from "fake web site" field when configuring openvpn over cloak via wizard 2023-03-16 18:59:06 +03:00
vladimir.kuznetsov
a92f1b82d0 fixed a bug with incorrect port detection when clicking the "scan installed containers" button 2023-03-16 16:47:26 +03:00
vladimir.kuznetsov
433e6901c6 fixed a bug when existing containers were overwritten in the GUI when clicking the "scan installed containers" button 2023-03-16 16:46:29 +03:00
pokamest
e16d835727 CentOS docker autostart fix 2023-03-16 12:35:01 +00:00
pokamest
a5cf2d37d4 Merge pull request #180 from amnezia-vpn/fix/target_sdk_31
Support of targetSdk 31 with its behaviour changes
2023-03-06 12:02:15 +00:00
Dmitriy Karpushin
4bd6fbd445 Support of targetSdk 31 with its behaviour changes 2023-03-06 12:11:37 +03:00
vladimir.kuznetsov
8f18933713 moved the function of checking the availability of wireguard config to ipc client 2023-03-02 17:46:16 +03:00
vladimir.kuznetsov
caad670dbf added wireguard connection implementation for Linux 2023-03-02 10:19:57 +03:00
vladimir.kuznetsov
2d30f86cc6 removed unused qtssh folder 2023-02-28 06:15:01 +03:00
pokamest
1dd79d9e31 Merge pull request #169 from amnezia-vpn/feature/container-existence-on-container-setup
feature/container-existence-on-container-setup
2023-02-27 22:27:10 +00:00
vladimir.kuznetsov
4171afe275 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-client-management-panel 2023-02-27 19:59:01 +03:00
vladimir.kuznetsov
a287192649 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-02-27 19:53:53 +03:00
vladimir.kuznetsov
f2e9631af4 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/container-existence-on-container-setup 2023-02-27 19:42:47 +03:00
pokamest
c756ab70ae Merge pull request #168 from amnezia-vpn/feature/port-availability-on-container-setup
feature/port-availability-on-container-setup
2023-02-27 03:26:57 +00:00
pokamest
2e57fe0dfd Merge pull request #177 from amnezia-vpn/feature/android_qr_code_scanner
Qr-code scanner for Android
2023-02-27 00:23:33 +00:00
vladimir.kuznetsov
be39d28be7 renamed selectedServerIndex for android 2023-02-25 18:48:10 +03:00
vladimir.kuznetsov
23a292b8ff Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/container-existence-on-container-setup 2023-02-25 18:22:08 +03:00
vladimir.kuznetsov
cdbb247780 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/port-availability-on-container-setup 2023-02-25 18:21:23 +03:00
vladimir.kuznetsov
69d4f0ce10 removed ContainerProps::containerTypeToString 2023-02-25 18:17:25 +03:00
vladimir.kuznetsov
2580475f67 added a button to scan the server for already installed containers
- refactoring of old code, redundant sections of code removed
2023-02-25 17:59:22 +03:00
pokamest
138789149c Merge branch 'dev' into feature/qt6-libssh-support 2023-02-23 18:46:43 +00:00
pokamest
1be66659d3 Merge pull request #178 from amnezia-vpn/bugfix/linux-missing-lib
bugfix/linux-missing-lib
2023-02-23 18:11:48 +00:00
vladimir.kuznetsov
6d3ba0ae72 added installation of libxkbcommon-x11-0 package for linux runner 2023-02-23 17:32:32 +03:00
vladimir.kuznetsov
04f61677d7 static link for qtkeychain 2023-02-23 17:28:19 +03:00
Dmitriy Karpushin
0096e65fe6 Increased build tools version 2023-02-22 14:48:38 +03:00
Dmitriy Karpushin
b870306c5d Support of multiple-code config 2023-02-22 14:22:03 +03:00
vladimir.kuznetsov
480b2181f0 made error output in the same style
- some code style refactoring
2023-02-22 10:01:43 +03:00
vladimir.kuznetsov
ddc3fe7807 Added the advanced settings page
- added a button to scan the server for installed containers
- added a check on the presence of installed containers before configuring the server, if the containers are already installed, then we will add them to the GUI
- added new control element - PopupWarning.qml
2023-02-20 09:46:50 +03:00
Dmitriy Karpushin
a86e8659f7 CameraActivity with Google ML KIT for decoding QR codes 2023-02-17 16:38:44 +03:00
pokamest
ae10dd639b Merge branch 'dev' into feature/qt6-libssh-support 2023-02-17 01:47:25 +00:00
Shahzain Ali
a0141624b9 Wg fix (#172)
Build fix for iOS
2023-02-15 15:41:18 +00:00
vladimir.kuznetsov
dc137620eb Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/port-availability-on-container-setup 2023-02-14 18:03:19 +03:00
vladimir.kuznetsov
e9b92b216a added a check for port availability when installing up a container
- added wireguard service copying to debug build folder
2023-02-14 18:02:51 +03:00
Nethius
24bf057d17 Merge pull request #174 from amnezia-vpn/fix/qt6_libssh_andorid_build
Fixed libssh android build
2023-02-13 18:13:34 +03:00
Dmitriy Karpushin
b68c6b6807 Little refactoring 2023-02-13 10:42:47 +03:00
pokamest
34a268624b Merge pull request #166 from amnezia-vpn/bugfix/wrong-fields-type-shadowsocks-config
bugfix/wrong-fields-type-shadowsocks-config
2023-02-10 20:22:42 +00:00
Dmitriy Karpushin
cdd527f3ac little fix 2023-02-10 13:57:15 +03:00
pokamest
1f048a6d04 Merge branch 'dev' into bugfix/wrong-fields-type-shadowsocks-config 2023-02-09 13:10:26 +00:00
pokamest
58cf10ffb2 Merge pull request #173 from amnezia-vpn/feature/deploy-unpacked-binaries
feature/added-deploy-binaries-that-are-not-packed-into-the-installer
2023-02-09 13:08:37 +00:00
pokamest
1ef14e129f Update deploy.yml 2023-02-09 11:15:50 +00:00
Dmitriy Karpushin
7c4030aaef fix macos build 2023-02-08 19:09:24 +03:00
Dmitriy Karpushin
c1bf0f8799 [WIP] dynamic linking 2023-02-08 16:06:18 +03:00
vladimir.kuznetsov
4b0a4aa5d2 removed unused code 2023-02-08 16:06:18 +03:00
vladimir.kuznetsov
115be88e5d added check for nullptr in sshclient 2023-02-08 16:06:18 +03:00
vladimir.kuznetsov
268bd8f1a6 added deploy binaries that are not packed into the installer 2023-02-08 09:44:52 +03:00
pokamest
1d9ff17380 Merge pull request #170 from amnezia-vpn/bugfix/cmake-version
bugfix/cmake-version
2023-02-07 17:05:55 +00:00
vladimir.kuznetsov
0fa0d72300 increased required version of cmake for LINUX variable to work properly 2023-02-07 19:45:42 +03:00
pokamest
677d166b1e Merge pull request #164 from amnezia-vpn/feature/cloak-and-ss-in-linux-bundle
feature/cloak-and-ss-in-linux-bundle
2023-02-07 16:27:04 +00:00
vladimir.kuznetsov
b5778a9cb5 if the container already exists, then add it to the list of containers in the client 2023-02-07 10:39:18 +03:00
vladimir.kuznetsov
b2fd94d20e added a check for the existence of the container before installing it 2023-02-06 19:19:49 +03:00
vladimir.kuznetsov
16969bc39b added conversion of the local_port and server_port fields from string to number when saving the shadowsocks config 2023-02-06 08:39:56 +03:00
Dmitriy Karpushin
3943314142 Fix of android build 2023-02-03 19:07:09 +03:00
vladimir.kuznetsov
f7ee532add Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/cloak-and-ss-in-linux-bundle 2023-02-02 13:08:23 +03:00
pokamest
2fdab4c196 Merge pull request #165 from amnezia-vpn/bugfix/cloak-transport-protocol
bugfix/cloak-transport-protocol
2023-02-02 09:17:00 +00:00
vladimir.kuznetsov
e6a95370c1 removed unused code 2023-02-02 08:36:50 +03:00
vladimir.kuznetsov
92907bced3 hardcoded tcp for the openvpn-cloak container 2023-02-02 08:09:07 +03:00
Dmitriy Karpushin
ca30b8b62a Correct path for openssl static lib 2023-02-01 17:16:45 +03:00
vladimir.kuznetsov
da9ac6ff25 added check for nullptr in sshclient 2023-02-01 09:56:55 +03:00
Dmitriy Karpushin
475de5250e New HEAD of qtkeychain (qt6 support) 2023-01-31 18:02:04 +03:00
Dmitriy Karpushin
7a9860ac29 OpenSSL for android build 2023-01-31 17:12:52 +03:00
pokamest
32ca02bcc7 Crash fix on VPN connection 2023-01-31 01:38:49 +00:00
pokamest
ddefb99e5e Merge branch 'dev' into feature/qt6-libssh-support 2023-01-31 00:53:24 +00:00
pokamest
ca4d6e0b2f Android cmake build fix 2023-01-31 00:47:01 +00:00
pokamest
c3fc3a3132 Merge pull request #163 from amnezia-vpn/feature/confirm-on-clear-and-delete-server
feature/confirm-on-clear-and-delete-server
2023-01-30 20:45:35 +00:00
pokamest
78b8a1c36f Merge pull request #162 from amnezia-vpn/bugfix/cloak-transport-protocol
bugfix/cloak-transport-protocol
2023-01-30 20:43:15 +00:00
pokamest
638c3492d6 Merge pull request #159 from amnezia-vpn/bugfix/linux-uninstall
bugfix/linux-uninstall
2023-01-30 20:37:46 +00:00
vladimir.kuznetsov
4c1699935c added binaries for cloak and shadowsocks to Linux bundle 2023-01-30 12:41:51 +03:00
vladimir.kuznetsov
25829451c8 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-client-management-panel 2023-01-29 09:52:12 +03:00
vladimir.kuznetsov
74fbce8b96 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2023-01-29 09:43:03 +03:00
vladimir.kuznetsov
542039df01 Changed notification text for "Forget this server" action 2023-01-29 09:01:48 +03:00
vladimir.kuznetsov
d652ecff21 For the openvpn-cloak container, the choice of the transport protocol in the openvpn settings is blocked 2023-01-29 08:39:31 +03:00
vladimir.kuznetsov
00c4cf300a fixed the width of the buttons in popupWithQuestion 2023-01-27 19:56:39 +03:00
vladimir.kuznetsov
da47054497 changed element type to confirm container deletion from MessageDialog to PopupWithQuestion
- fixed "back" button availability for readonly servers
2023-01-27 18:37:08 +03:00
vladimir.kuznetsov
051a2a3ef2 Added popup to confirm actions "Clear server from Amnesia software" and "Forget this server" 2023-01-27 10:25:14 +03:00
vladimir.kuznetsov
ee609f3e8f fixed warning with QFutureWatcher
- renamed readWireguardConfiguration function to match what it does
2023-01-24 09:43:45 +03:00
vladimir.kuznetsov
eb66354c76 fixed path to maintenancetool in linux
- added x11 to runningOnLinux() function
2023-01-22 08:26:29 +03:00
vladimir.kuznetsov
c7fb7e58cf Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into bugfix/linux-uninstall 2023-01-21 10:35:29 +03:00
vladimir.kuznetsov
c2b02a45a2 fixed path to linux install folderfixed path to installed application in linux 2023-01-21 10:35:01 +03:00
pokamest
e7ed532545 Disable fastline for iOS while it not fixed 2023-01-19 21:08:57 +00:00
pokamest
2a031320c2 Merge pull request #156 from amnezia-vpn/bugfix/wrong-artifacts-size
added qtshadertools to all targets
2023-01-19 20:59:00 +00:00
vladimir.kuznetsov
d0379fdede added qtshadertools to all targets 2023-01-19 18:36:54 +03:00
vladimir.kuznetsov
45016b76e7 moved crl-verify crl.pem to openvpn config templates 2023-01-19 17:49:17 +03:00
pokamest
ee8cd8ef26 Merge pull request #118 from amnezia-vpn/qt_migration
Migration to Qt6
2023-01-19 13:09:00 +00:00
pokamest
18d89e9cad Merge pull request #152 from amnezia-vpn/feature/android_qt6_moving
Moving to Qt 6 and cmake on Android client
2023-01-19 12:51:02 +00:00
pokamest
623c8ca6b0 Merge pull request #155 from amnezia-vpn/feature/android_bandwidth_counter
Fix of bandwidth counter for Android
2023-01-19 12:38:55 +00:00
Dmitriy Karpushin
39736e865e Merge branch 'feature/android_qt6_moving' into feature/android_bandwidth_counter
# Conflicts:
#	client/platforms/android/android_controller.cpp
#	client/platforms/android/android_controller.h
2023-01-19 14:09:12 +03:00
vladimir.kuznetsov
8ea80a616e Merge branch 'qt_migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-client-management-panel 2023-01-18 20:06:01 +03:00
vladimir.kuznetsov
c5df7f9bb7 added diagrams describing the process of obtaining information about clients 2023-01-18 19:55:12 +03:00
Dmitriy Karpushin
92374966fb Removing of unnecessary command 2023-01-18 16:12:30 +03:00
Dmitriy Karpushin
6bebfb861c Little cleanup 2023-01-18 15:54:19 +03:00
Dmitriy Karpushin
30ae13b245 Fix of signing code 2023-01-18 15:38:06 +03:00
pokamest
891f990e35 Merge pull request #154 from amnezia-vpn/dev
Release 2.1.2
2023-01-18 12:22:18 +00:00
Dmitriy Karpushin
2118327ae0 Fixes in path of build 2023-01-18 14:47:11 +03:00
Dmitriy Karpushin
6aed2902a7 Fixes in path of build 2023-01-18 14:37:58 +03:00
Dmitriy Karpushin
e149e32ce1 Changing the set of highlights 2023-01-18 11:36:16 +03:00
Dmitriy Karpushin
41f2af8c4e Some highlights were added 2023-01-18 11:27:01 +03:00
Dmitriy Karpushin
016f808345 Removing of unnecessary command 2023-01-18 11:11:27 +03:00
Dmitriy Karpushin
bc69524654 Changing of path of keystore location 2023-01-18 11:06:58 +03:00
Dmitriy Karpushin
3c6280c419 Changing of path of keystore location 2023-01-18 10:54:24 +03:00
pokamest
9d01a52a4a Merge pull request #145 from amnezia-vpn/feature/qt6-server-busy-notification
feature/qt6-server-busy-notification
2023-01-18 00:43:13 +00:00
pokamest
a8273a8fdc Merge pull request #153 from amnezia-vpn/bugfix/some-ui-small-fixes
bugfix/some-ui-small-fixes
2023-01-18 00:41:11 +00:00
vladimir.kuznetsov
d6d3bf6943 moved certificate content acquisition from ClientManagementLogic to ClientInfoLogic 2023-01-17 21:04:15 +03:00
vladimir.kuznetsov
f6e8346841 moved getClientsList and setClientsList from serverController 2023-01-17 18:41:36 +03:00
vladimir.kuznetsov
b9717e9894 removed unused code 2023-01-17 17:11:45 +03:00
Dmitriy Karpushin
6b3209e6ee Changing of the way of keystore fetching 2023-01-17 16:59:34 +03:00
Dmitriy Karpushin
0a6da5ead1 Platform version fix 2023-01-17 16:23:34 +03:00
Dmitriy Karpushin
53441148b8 Revert of Gradle upgrade 2023-01-17 16:12:42 +03:00
Dmitriy Karpushin
732d018819 Revert "Shadowsocks manifest fix"
This reverts commit e261a8ba21.
2023-01-17 16:09:06 +03:00
Dmitriy Karpushin
e261a8ba21 Shadowsocks manifest fix 2023-01-17 15:53:54 +03:00
Dmitriy Karpushin
c3c87bff74 Fix of GitHub Actions build 2023-01-17 15:34:37 +03:00
Dmitriy Karpushin
c3f423aad5 Little cleanup 2023-01-17 15:34:37 +03:00
pokamest
580975fda1 Merge branch 'qt_migration' into feature/qt6-server-busy-notification 2023-01-16 18:13:07 +00:00
pokamest
9f114a1dad Tiny fix [no ci] 2023-01-16 18:12:30 +00:00
pokamest
0ae93d0657 Merge pull request #144 from amnezia-vpn/refactoring/logging
refactoring/logging
2023-01-16 17:29:24 +00:00
vladimir.kuznetsov
3a210c5bab added wireguard key revocation 2023-01-16 20:24:37 +03:00
pokamest
44d2627e2a Tiny fix [no ci] 2023-01-16 17:11:00 +00:00
pokamest
6e882760f1 Merge branch 'qt_migration' into refactoring/logging 2023-01-16 16:10:39 +00:00
pokamest
ff79ffd1c8 Android tag deploy fix 2023-01-16 15:10:57 +00:00
vladimir.kuznetsov
3175b0c4ff Changed the indentation of the "Installed Protocols and Services" heading on the "Server Containers" page 2023-01-16 16:20:12 +03:00
Dmitry Karpushin
21779395ef Merge branch 'qt_migration' into feature/android_qt6_moving 2023-01-16 14:58:01 +03:00
Dmitriy Karpushin
32cbb698ee Support of apk signing for tag-deploy workflow 2023-01-16 14:30:08 +03:00
vladimir.kuznetsov
3f99c52349 change Flickable to FlickableType for ClientManagement and ClientInfo pages 2023-01-16 12:37:14 +03:00
vladimir.kuznetsov
19a41b2792 swapped "Clear client cached profile" and "Clear server from Amnesia software" buttons 2023-01-15 18:47:16 +03:00
vladimir.kuznetsov
599910daea added openvpn certificate revocation 2023-01-15 18:09:05 +03:00
vladimir.kuznetsov
bee42ea2fb fixed double call onEditingFinished when pressing Enter 2023-01-14 18:30:08 +03:00
vladimir.kuznetsov
221ea5ebb0 Merge branch 'qt_migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-server-busy-notification 2023-01-13 16:59:03 +03:00
vladimir.kuznetsov
f24df9fb05 Merge branch 'qt_migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-client-management-panel 2023-01-12 20:28:13 +03:00
vladimir.kuznetsov
ce2a122d51 added busy indicator when saving a list of clients, on the client info panel 2023-01-12 20:20:24 +03:00
Dmitriy Karpushin
e8242aec85 Android build script fix 2023-01-12 15:36:31 +03:00
Dmitriy Karpushin
6ed9dcbe93 Workflow build script fix 2023-01-12 15:19:39 +03:00
Dmitriy Karpushin
58371e6e43 New trigger for a workflow 2023-01-12 15:12:55 +03:00
Dmitriy Karpushin
2d8957489e Trigger alternative syntax 2023-01-12 14:55:11 +03:00
Dmitriy Karpushin
1fd0794bfb Workflow file formatting fix 2023-01-12 14:30:25 +03:00
Dmitriy Karpushin
58da60985f Error fix 2023-01-12 14:21:14 +03:00
Dmitriy Karpushin
6b6a3cd38e [WIP] Android release workflow test 2023-01-12 14:16:05 +03:00
pokamest
4b1df16ecf Merge pull request #148 from amnezia-vpn/feature/github-actions-artifacts
feature/github-actions-artifacts
2023-01-12 01:22:41 +00:00
vladimir.kuznetsov
24ea686e4d added busy indicator when loading a list of clients, on the client management panel 2023-01-11 21:36:18 +03:00
vladimir.kuznetsov
a7030cdcb9 added saving the list of clients for wireguard
- added error handling when getting/saving a list of clients
2023-01-11 20:36:47 +03:00
vladimir.kuznetsov
8c137ecc52 added page to display WireGuard client information 2023-01-10 16:21:45 +03:00
Dmitriy Karpushin
20e44aa891 Re-enabled multi-abi build 2023-01-10 13:19:19 +03:00
vladimir.kuznetsov
118bb53c03 fixed path to linux installer 2023-01-09 16:41:24 +03:00
Dmitriy Karpushin
7c3be9f0b0 Update of NDK version 2023-01-09 14:21:10 +03:00
Dmitriy Karpushin
d1990a4263 Adopted GitHub Actions build config for Qt6 2023-01-09 13:46:45 +03:00
vladimir.kuznetsov
396422ee3a increased storage time for artifacts up to 3 days 2023-01-09 12:44:36 +03:00
vladimir.kuznetsov
f735b401df added deploy artifacts to github actions, artifact lifetime 1 day 2023-01-09 12:41:04 +03:00
vladimir.kuznetsov
a42beb86c0 added client management panel
- added classes for displaying the client management panel
- added class for displaying the client info
- added page to display a list of clients
- added page to display OpenVpn client information
- added diagram with OpenVpn certificate revocation process
2023-01-09 12:38:01 +03:00
pokamest
85020270d5 MacOS deploy fix 2023-01-08 17:21:51 -08:00
pokamest
b1b9044021 Merge branch 'qt_migration' into refactoring/logging 2023-01-08 23:17:11 +00:00
pokamest
8da30b216f Cleanup 2023-01-08 23:10:46 +00:00
pokamest
167d3caa5d Merge branch 'dev' into qt_migration 2023-01-08 23:00:13 +00:00
pokamest
3259e6f0e8 Merge pull request #128 from amnezia-vpn/feature/ovpn-config-import
added import of configs in openvpn and wireguard formats
2023-01-08 22:26:39 +00:00
pokamest
64526c5232 Various ui fixes 2023-01-08 21:24:06 +00:00
pokamest
d9630afafd Merge branch 'dev' into feature/ovpn-config-import 2023-01-08 19:36:00 +00:00
pokamest
c8c6e62aa0 Merge pull request #141 from amnezia-vpn/add-scrollbar-on-flickables
Show Scrollbars whenever the scroll is not obvious
2023-01-08 12:32:55 +00:00
pokamest
7f561c30b3 Buttons margins 2023-01-08 12:32:07 +00:00
pokamest
1d8f342417 QML refactoring 2023-01-07 13:40:35 +00:00
vladimir.kuznetsov
6ec090ea0d added a "Cancel" button to interrupt the server configuration process when it is found that it is busy installing other software 2023-01-02 17:32:27 +03:00
vladimir.kuznetsov
08a8eadb49 added display of a notification that the server is busy installing third-party software
- refactoring doInstallAction functions
2023-01-01 22:08:39 +03:00
Dmitriy Karpushin
3e2835bef6 Rolling back GitHub Actions config 2022-12-29 15:04:42 +03:00
vladimir.kuznetsov
686fc754b2 renamed log class in service project to logger 2022-12-28 17:56:31 +03:00
Dmitriy Karpushin
ea17124d6d Fix of build type for GitHub Actions 2022-12-28 16:35:25 +03:00
Dmitriy Karpushin
4000041308 Fix of build type 2022-12-28 15:55:03 +03:00
Dmitriy Karpushin
1a50ed0316 Increased java version on runner 2022-12-28 14:45:45 +03:00
Dmitriy Karpushin
42038cd6e7 Fixed filenames 2022-12-28 14:26:44 +03:00
Dmitriy Karpushin
44c5b41cc7 Little fix 2022-12-28 13:57:41 +03:00
Dmitriy Karpushin
da7bd91514 Little fix 2022-12-28 13:52:14 +03:00
Dmitriy Karpushin
0206623c6f Correct way to set up QT_HOST_PATH variable 2022-12-28 13:42:29 +03:00
vladimir.kuznetsov
3b2948d4dd renamed debug class to logger 2022-12-28 13:41:45 +03:00
Dmitriy Karpushin
918aeb670e Added QT_HOST_PATH variable 2022-12-28 13:37:56 +03:00
Dmitriy Karpushin
fd9fec48a2 Replacing of qmake on cmake for GitHub Actions 2022-12-28 13:10:34 +03:00
vladimir.kuznetsov
77e51b40b8 removed unused logger 2022-12-28 13:09:33 +03:00
vladimir.kuznetsov
195663c6e3 Added activation and deactivation of logging without restarting the application 2022-12-28 06:52:02 +03:00
vladimir.kuznetsov
ce4ca5c4d5 Added display of a notification about the inclusion of logging on the main screen 2022-12-28 06:50:46 +03:00
Dmitriy Karpushin
3e276c4111 GitHub Actions fix #2 2022-12-27 20:06:11 +03:00
Dmitriy Karpushin
41a4dc2fa2 GitHub Actions fix 2022-12-27 20:00:45 +03:00
Dmitriy Karpushin
7851047421 multi-abi support 2022-12-27 17:54:14 +03:00
Dmitriy Karpushin
a30e478cbd Fix of cmake build 2022-12-27 17:14:44 +03:00
Dmitriy Karpushin
ad4b3dfad1 [WIP] cmake build for android 2022-12-27 15:37:58 +03:00
Dmitriy Karpushin
ad7fc937a9 Added missing files 2022-12-27 11:10:01 +03:00
vladimir.kuznetsov
fd905ef308 added margin for scrollbars for almost all flickable elements 2022-12-26 19:07:05 +03:00
pokamest
3f257af7a9 Merge pull request #131 from amnezia-vpn/qmake-to-cmake-migration
Qmake to cmake migration
2022-12-26 14:52:40 +00:00
vladimir.kuznetsov
030bb8fe76 Merge branch 'qt_migration' of github.com:amnezia-vpn/desktop-client into qmake-to-cmake-migration 2022-12-26 17:29:52 +03:00
pokamest
131601d9d2 Merge pull request #142 from amnezia-vpn/qt-migration-cleanup
Qt migration cleanup
2022-12-26 14:16:03 +00:00
vladimir.kuznetsov
64317ffef5 fixed deploy service additional data for debug target 2022-12-26 17:15:45 +03:00
vladimir.kuznetsov
911e65af55 Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-26 17:08:27 +03:00
Dmitriy Karpushin
82165eaf37 1) Fixed theme
2) Fixed VPN connection
2022-12-26 14:00:45 +03:00
vladimir.kuznetsov
4a75f2ebca Moved ssh lib wrapper from SshSession to SshClient 2022-12-26 12:43:51 +03:00
vladimir.kuznetsov
be39b3be8c implementation of sending commands via ssh_channel_request_exec() 2022-12-26 10:12:42 +03:00
vladimir.kuznetsov
50e8aff8fa added ssh_channel_close() in ShhSession 2022-12-25 15:46:56 +03:00
pokamest
804a790392 FlickableType added 2022-12-24 16:41:53 +00:00
vladimir.kuznetsov
d04566a6c4 fix for macos build 2022-12-24 18:21:08 +03:00
Dmitriy Karpushin
6c614a4b3c Moving to Qt6:
1) removing of deprecated classes
2) update of IPC mechanism
2022-12-23 17:32:20 +03:00
vladimir.kuznetsov
3277717a7f Added error handling
Added write to channel in callbacks
2022-12-23 14:50:48 +03:00
vladimir.kuznetsov
f9b2829396 removed linking with botan and qssh 2022-12-23 10:13:06 +03:00
vladimir.kuznetsov
81cf108471 moved and formatted code for sftp to sshSession class 2022-12-22 19:55:30 +03:00
vladimir.kuznetsov
5075fe358e added callbacks for output from a remote host 2022-12-21 08:13:06 +03:00
vladimir.kuznetsov
c8085a368f added class to open ssh connection using libssh and write data to ssh channel 2022-12-20 13:43:46 +03:00
Shahzain Ali
8191c25dd7 Delete amnezia-ios-certificates 2022-12-20 00:37:30 +05:00
Shahzain Ali
dc4b2bd52e added submodule 2022-12-20 00:22:12 +05:00
Shahzain Ali
ca60afbcee Update deploy.yml 2022-12-19 17:06:47 +05:00
Shahzain Ali
374b74b710 Update deploy.yml 2022-12-19 17:03:33 +05:00
Shahzain Ali
ae0d3d78cd Testflight upload test 2022-12-19 17:02:25 +05:00
vladimir.kuznetsov
f9f197afd0 removed unused code 2022-12-18 19:36:19 +03:00
vladimir.kuznetsov
93c43ecbc3 removed unused qzxing folder 2022-12-18 18:27:20 +03:00
vladimir.kuznetsov
1fd1b0388b removed unused code 2022-12-18 18:27:08 +03:00
vladimir.kuznetsov
833364a94e added SortFilterProxyModel submodule 2022-12-18 18:11:41 +03:00
vladimir.kuznetsov
893c105bf2 removed SortFilterProxyModel sources 2022-12-18 18:07:32 +03:00
vladimir.kuznetsov
e481bd4ec5 added deploy artifacts to github actions, artifact lifetime 1 day 2022-12-18 09:45:26 +03:00
vladimir.kuznetsov
b0489aa61b Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-18 09:17:35 +03:00
vladimir.kuznetsov
376bc29e95 set OPENSSL_SSL_LIBRARY for ios 2022-12-17 22:18:14 +03:00
vladimir.kuznetsov
bd22e330a7 set OPENSSL_CRYPTO_LIBRARY for ios
- removed linking with brew openssl for ios
2022-12-17 22:02:38 +03:00
vladimir.kuznetsov
9ce7114f8c added variables for OpenSSL 2022-12-17 21:48:45 +03:00
vladimir.kuznetsov
1303da1c20 openedsl linking method changed 2022-12-17 21:34:59 +03:00
vladimir.kuznetsov
c6bb33fa84 added display of "pure" config if it was imported in native format
- changed the method of passing the isThirdPartyConfig parameter to page logic
- removed adding hostname to the server name when importing configs in native format
- fixed display of the "$proto settings" button when clicking on the protocol on the "Installed services" page
2022-12-17 21:00:48 +03:00
vladimir.kuznetsov
22939a6707 Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into feature/ovpn-config-import 2022-12-17 17:27:26 +03:00
Hamza ARBI
9222877306 Show Scrollbars whenever the scroll is not obvious 2022-12-17 12:06:19 +01:00
Shahzain Ali
5d8264e854 Update launch.png 2022-12-16 18:48:14 +05:00
pokamest
77124e098c Merge branch 'qt_migration' into qmake-to-cmake-migration 2022-12-16 04:45:43 -08:00
pokamest
bd0a70d024 Merge pull request #140 from amnezia-vpn/bugfix/drawer-clickability
Bugfix/drawer-clickability
2022-12-16 13:43:49 +01:00
Shahzain Ali
914700712e OpenSSL finding issue fixed. 2022-12-16 15:27:06 +05:00
vladimir.kuznetsov
80d792915a fixed clickability of "drawer" elements
- added Qt.PointingHandCursor to SelectContainer drawer
- fixed some warnings
2022-12-15 21:16:59 +03:00
Dmitriy Karpushin
54dc363231 iOS fix + Android connection status restoration fix 2022-12-15 18:46:15 +03:00
pokamest
36c436af50 gitignore fix 2022-12-15 11:26:25 +01:00
Shahzain Ali
73eb9259e2 Update CMakeLists.txt 2022-12-15 14:26:45 +05:00
pokamest
951d915326 libssh init 2022-12-14 21:50:52 +01:00
vladimir.kuznetsov
14c25480ce changed working directory to call openvpn.sh 2022-12-14 22:26:06 +03:00
vladimir.kuznetsov
77d87f8c50 set working directory to call openvpn.sh 2022-12-14 21:55:51 +03:00
vladimir.kuznetsov
ab389d4817 for osxtools and networkextension/CMakeLists.txt CMAKE_CURRENT_SOURCE_DIR changed to CLIENT_ROOT_DIR 2022-12-14 21:29:33 +03:00
vladimir.kuznetsov
58b9e0cd7c for osxtools and networkextension/CMakeLists.txt CMAKE_CURRENT_LIST_DIR changed to CMAKE_CURRENT_SOURCE_DIR 2022-12-14 21:16:24 +03:00
vladimir.kuznetsov
ed2f5af204 Removed "cd client" for ios, also changed CMAKE_SOURCE_DIR to CMAKE_CURRENT_LIST_DIR.
Removed duplicate deployment files for macos
2022-12-14 20:58:49 +03:00
vladimir.kuznetsov
5b2f1f8969 processing of 3rdparty libraries moved to a separate cmake file 2022-12-14 20:32:13 +03:00
vladimir.kuznetsov
a2122cb7d7 moved changes from .pro file 2022-12-14 19:55:14 +03:00
vladimir.kuznetsov
d680702b15 change path to cmake folder 2022-12-14 19:17:58 +03:00
vladimir.kuznetsov
d15de499dc Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into qmake-to-cmake-migration 2022-12-14 19:16:38 +03:00
vladimir.kuznetsov
bd382e3cc7 moved the cmake folder to client root folder 2022-12-14 19:16:12 +03:00
Dmitriy Karpushin
d417fa58ab OpenVPN bandwidth counter for Android 2022-12-14 18:52:19 +03:00
Shahzain Ali
ca9cb997b5 Fixed openVPN issue.
Now OpenVPN moved to main target and fixed search path issue, becuase I face below error while archiving. Invalid Bundle. The bundle at 'AmneziaVPN.app/PlugIns/AmneziaVPNNetworkExtension.appex' contains disallowed nested bundles.
2022-12-14 17:28:16 +05:00
Shahzain Ali
ebd920f3b2 Setting target membership on Media.xcassets 2022-12-14 16:56:20 +05:00
vladimir.kuznetsov
a611ddea2d removed environment OPENSSL_ROOT_DIR variable 2022-12-13 23:52:43 +03:00
vladimir.kuznetsov
75614e0bbb set environment OPENSSL_ROOT_DIR variable 2022-12-13 23:39:58 +03:00
vladimir.kuznetsov
dafef6463a added:
- set PKG_CONFIG_PATH for openssl
- use find_package for precompiled openssl

removed:
- set CMAKE_PREFIX_PATH for openssl
- renaming ios openssl libs after copying to bin dir
2022-12-13 21:39:02 +03:00
vladimir.kuznetsov
61d502eea4 removed find_package for openssl 2022-12-13 20:49:46 +03:00
vladimir.kuznetsov
71aa525dfd set CMAKE_PREFIX_PATH for openssl 2022-12-13 20:36:12 +03:00
vladimir.kuznetsov
c0e3875dfd renaming ios openssl libs after copying to bin dir 2022-12-13 20:23:17 +03:00
pokamest
9c188e0acd Merge branch 'qt_migration' into qmake-to-cmake-migration 2022-12-13 15:34:38 +01:00
pokamest
1de143362c Merge branch 'dev' into qt_migration 2022-12-13 15:09:05 +01:00
vladimir.kuznetsov
7e37b6c151 removed CMAKE_PREFIX_PATH for openssl 2022-12-12 22:22:08 +03:00
vladimir.kuznetsov
0fa84a8b84 set CMAKE_PREFIX_PATH for openssl 2022-12-12 21:39:27 +03:00
vladimir.kuznetsov
236ae57d01 use find_package for precompiled openssl 2022-12-12 20:50:23 +03:00
pokamest
7345f464a5 Merge pull request #138 from amnezia-vpn/feature/android_config_export_import
Export/import of configuration files on Android
2022-12-12 16:48:23 +01:00
pokamest
3c45f2abe2 Merge branch 'dev' into feature/ovpn-config-import 2022-12-12 14:42:12 +01:00
pokamest
9c5e1faf46 Build fixes 2022-12-12 14:41:54 +01:00
pokamest
ce02d3a829 Merge branch 'dev' into feature/ovpn-config-import 2022-12-12 14:01:57 +01:00
pokamest
1b80c59e65 Merge pull request #137 from amnezia-vpn/bugfix/config-without-containers-import
bugfix: import config without containers
2022-12-12 13:30:28 +01:00
Hamza ARBI
f20f528a11 Server selection always in range (#130)
* Server selection stays always in the list's range
* Removed the usage of QZxing module from PageQrDecoder page
* Fixed null spelling on qml instead of nil
2022-12-12 13:28:03 +01:00
dartsyms
814b66c04a Various fixes for iOS (#126)
* Readme update, solution for wireguard make in M1 machines,
* import file and restore enabled.
* xcode_patcher.rb fixed, Now no need to add openVPN framewrok in Embed frameworks manually.
* Now xcode_patcher.rb will add OpenVPN Framework to Embed Frameworks in main target, instead of Network extension.
* Update iosvpnprotocol.swift
* Protocol wasn't detected because it is working on localized description of tunnel, fixed cases.
* Code cleanup
* Speed issue fixed for wireguard.
* GetDeviceIp and bytes(speed of OpenVPN) fixed.
*Device IP method wasn't working as expected, so I replaced. and for speed in OpenVPN we need to handle message seperately for bytes.
*QR progress added with progressbar and text.
2022-12-12 13:16:12 +01:00
vladimir.kuznetsov
00ad2e7a80 added path to openssl libs for ios 2022-12-11 18:25:44 +03:00
vladimir.kuznetsov
8f7e5e491f fixed macos openssl lib types 2022-12-11 17:59:18 +03:00
vladimir.kuznetsov
19101176a7 added link_libraries() for zlib 2022-12-11 17:22:59 +03:00
vladimir.kuznetsov
0bc383fec2 Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-11 17:09:26 +03:00
vladimir.kuznetsov
4df918d6a5 added qtshadertools to actions and cmake
- cleaned up CMakeLists in client project
2022-12-11 10:26:31 +03:00
Shahzain Ali
d3cbd8cdae Update deploy.yml 2022-12-11 04:21:28 +05:00
Shahzain Ali
0fa5dc225c Reverting shadertools in cmake. 2022-12-11 04:19:24 +05:00
Shahzain Ali
b14f14c45a Update CMakeLists.txt 2022-12-11 04:09:45 +05:00
Shahzain Ali
0851f4fdd4 Added Qt6ShaderTools in cmake 2022-12-11 04:01:15 +05:00
Shahzain Ali
807b3370e7 Adding qtshadertools module in qt installation 2022-12-11 03:42:46 +05:00
Shahzain Ali
a0f114e15c Fixing openvpn 2022-12-11 03:22:59 +05:00
vladimir.kuznetsov
1401fcd97d disabled some libssh options 2022-12-10 20:15:05 +03:00
vladimir.kuznetsov
efcd291e65 Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-10 19:07:00 +03:00
vladimir.kuznetsov
f98792714e set working directory to call openvpn.sh 2022-12-10 18:46:17 +03:00
vladimir.kuznetsov
5649f85b58 set QT_HOST_PATH for ios target 2022-12-10 18:09:41 +03:00
vladimir.kuznetsov
cfaba932e0 changeGed libz lib name for linux target 2022-12-10 18:00:50 +03:00
vladimir.kuznetsov
b1db4e8a7a Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-10 17:58:57 +03:00
vladimir.kuznetsov
ab9c11e038 set ios root dir as CMAKE_PREFIX_PATH 2022-12-09 18:12:39 +03:00
vladimir.kuznetsov
4d621dcbfe set CMAKE_PREFIX_PATH in CMakeLists file 2022-12-09 17:44:57 +03:00
vladimir.kuznetsov
a45537cbf3 added DCMAKE_PREFIX_PATH to IOS target 2022-12-09 17:30:46 +03:00
vladimir.kuznetsov
2d3ac286ac skip section with openssl copy for linux 2022-12-09 16:18:02 +03:00
vladimir.kuznetsov
4e96b5d4a6 added libz lib name for linux target 2022-12-09 15:57:31 +03:00
Shahzain Ali
9294324732 fixing host path 2022-12-09 04:24:16 +05:00
Shahzain Ali
b92422594b Merge branch 'qmake-to-cmake-migration' of https://github.com/amnezia-vpn/desktop-client into qmake-to-cmake-migration 2022-12-09 04:13:37 +05:00
Shahzain Ali
ea2637b1b4 Setting QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON 2022-12-09 04:13:14 +05:00
Shahzain Ali
c97b4859c1 Update deploy.yml 2022-12-09 04:05:25 +05:00
Shahzain Ali
7a2f42de30 Update deploy.yml 2022-12-09 03:58:36 +05:00
Shahzain Ali
99f5f78fc7 Update deploy.yml 2022-12-09 03:48:12 +05:00
Shahzain Ali
668f0ca675 Update deploy.yml 2022-12-09 03:47:09 +05:00
Shahzain Ali
6a89a51ea6 added QT_TOOL_CHAIN for ios cmake 2022-12-09 03:38:29 +05:00
Shahzain Ali
df6b0f3945 Update deploy.yml 2022-12-09 03:11:31 +05:00
Shahzain Ali
65cf243373 Update deploy.yml 2022-12-09 03:10:26 +05:00
Shahzain Ali
2ef7813219 Update deploy.yml 2022-12-09 03:06:16 +05:00
Shahzain Ali
216efd74bf Update deploy.yml 2022-12-09 03:04:43 +05:00
Shahzain Ali
b9d027a44a Update deploy.yml 2022-12-09 03:03:17 +05:00
Shahzain Ali
9097dd9645 actions for ios using cmake 2022-12-09 02:59:35 +05:00
Shahzain Ali
d784e26913 MacOS issue fixed. 2022-12-09 02:33:46 +05:00
vladimir.kuznetsov
cb69298385 Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support 2022-12-08 21:41:33 +03:00
vladimir.kuznetsov
a8fc42a17e added copying OpenSSL libraries, for windows and macos, to the folder with binaries, because we have the wrong folder structure with the OpenSSL library 2022-12-08 21:40:51 +03:00
Shahzain Ali
005008814a icon added in cmake. 2022-12-08 21:34:55 +05:00
Shahzain Ali
ad3bbaedb3 getting openvpn.sh script message. 2022-12-08 18:22:07 +05:00
Dmitriy Karpushin
cad0dabe42 Export/import of configuration filed on Android 2022-12-08 11:51:28 +03:00
Shahzain Ali
48fa3c8aec Update CMakeLists.txt 2022-12-07 20:36:22 +05:00
Shahzain Ali
fb585cbac0 OpenVPN integrated successfully 2022-12-07 20:35:43 +05:00
Shahzain Ali
dd1adda1a6 postbuild command fix. 2022-12-07 00:19:02 +05:00
vladimir.kuznetsov
3742583508 added zlib to submodules. Added build and link zlib, libssh in CMakeLists.txt 2022-12-06 18:17:10 +03:00
Shahzain Ali
3c6cd623af version issues fixed 2022-12-06 19:18:38 +05:00
Shahzain Ali
70c6e69b36 updatinf info.plist for .vpn type. 2022-12-06 03:09:45 +05:00
Shahzain Ali
943e58d32a Wireguard working. 2022-12-06 02:47:46 +05:00
Shahzain Ali
5237058016 Added launcher 2022-12-06 02:18:45 +05:00
Shahzain Ali
b87c5f8a51 iOS building successfully
Need to remove postbuild commands most probably from osxtools.cmake
2022-12-06 00:42:48 +05:00
Shahzain Ali
43e7a03af4 Some fixes.
Now team is preselected in signing.
2022-12-05 20:47:12 +05:00
pokamest
19fce4975d Merge branch 'dev' into feature/ovpn-config-import 2022-12-04 22:04:51 +01:00
pokamest
a9217810e7 Remove travis builds and tiny refactoring 2022-12-04 21:54:22 +01:00
Mykola Baibuz
a87610c856 Use libssh for server setup script
That gives some advantages in supported key types.
2022-12-04 01:43:53 +03:00
vladimir.kuznetsov
0ec0cb1b19 feature: added libssh submodule 2022-12-04 01:43:34 +03:00
vladimir.kuznetsov
9b1678a06c Merge branch 'dev' of github.com:amnezia-vpn/desktop-client into bugfix/config-without-containers-import 2022-12-03 15:26:32 +03:00
vladimir.kuznetsov
0da63062d7 bugfix: fixed transition to the "Installed services" page when importing a config that does not have installed containers 2022-12-03 15:23:52 +03:00
Shahzain Ali
c8dd12eb20 Some more progress in cmake
Still have errors, currently not using apple-compile.sh building completely using cmake.
2022-12-02 22:26:10 +05:00
Shahzain Ali
008592f13b Architecture change not needed for ios build
CMAKE_OSX_ARCHITECTURES not needed for ios, it is setting x86_64 for all targets in ios.
2022-12-02 15:07:05 +05:00
vladimir.kuznetsov
56b9972053 build script for macos now uses cmake 2022-12-01 20:26:00 +03:00
vladimir.kuznetsov
1335c94bbc added include directory for botan ios 2022-12-01 20:24:04 +03:00
vladimir.kuznetsov
21a6ab369e Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into qmake-to-cmake-migration 2022-12-01 20:11:56 +03:00
vladimir.kuznetsov
2a80117d42 Merge remote-tracking branch 'remotes/origin/qt6-github-actions' into qmake-to-cmake-migration 2022-12-01 20:05:36 +03:00
Shahzain Ali
e65d312503 Merge branch 'qmake-to-cmake-migration' of https://github.com/amnezia-vpn/desktop-client into qmake-to-cmake-migration 2022-12-01 20:40:00 +05:00
Shahzain Ali
5fc34e643c Adding network extenstionn, fixing cmake.
Botan cmake changes, cmake APPLE/IOS fixes, wireguard added, Currently removed openvpn implementation, once wireguard is stable then will add openVPN framework.
Current progress is it is generating xcode project using
mkdir build-ios
/Users/shahzainali/Qt/6.4.1/ios/bin/qt-cmake . -B build-ios -GXcode
Need to select team only for Network extension only. select AmneizaVPN to run.
current issue is related to Botan.
2022-12-01 20:26:45 +05:00
pokamest
3463a84903 Merge branch 'qt_migration' into qmake-to-cmake-migration 2022-11-30 15:02:55 +01:00
pokamest
48dc532de6 Merge branch 'dev' into qt_migration 2022-11-30 14:26:44 +01:00
Shahzain Ali
20cb62483f Moved all libraries to LIBS variable 2022-11-30 15:36:25 +05:00
pokamest
dcb5828313 GitHub actions (#133)
GitHub actions
2022-11-30 01:51:18 +01:00
pokamest
74860256b9 Merge pull request #136 from amnezia-vpn/bugfix/notarize-app-macos
fixed options parsing for enable macos NOTARIZE_APP
2022-11-30 01:21:19 +01:00
vladimir.kuznetsov
97457f17c1 fixed options parsing for enable macos NOTARIZE_APP 2022-11-29 22:11:02 +03:00
Shahzain Ali
de9167cae6 Frameworks, libcrypto, libssl and some properties added for iOS. 2022-11-29 18:00:59 +05:00
vladimir.kuznetsov
2e5171c205 added matrix for all android arch 2022-11-29 00:55:32 +03:00
Shahzain Ali
a0b5491178 Merge branch 'qt_migration' into qmake-to-cmake-migration 2022-11-28 19:23:28 +05:00
vladimir.kuznetsov
fc8ef8678b Merge remote-tracking branch 'remotes/origin/qt_migration' into qmake-to-cmake-migration 2022-11-28 14:50:20 +03:00
Shahzain Ali
2dc1f2ea5b Setting minimum version to 13
QT 6.4 required minimum ios 13
https://doc.qt.io/qt-6/supported-platforms.html
2022-11-28 15:56:48 +05:00
Shahzain Ali
7999527582 Update README.md 2022-11-28 15:44:55 +05:00
Shahzain Ali
14be6506ee Qt5 to QT6 fixes. 2022-11-28 15:36:33 +05:00
vladimir.kuznetsov
c85ad470ba qt version in github actions changed to 6.4.1 2022-11-27 12:08:48 +03:00
vladimir.kuznetsov
8b6afcc5ec removed unused qzxing folder 2022-11-27 01:35:13 +03:00
vladimir.kuznetsov
813dced6df added qt6 modules installation to github actions 2022-11-27 01:30:36 +03:00
vladimir.kuznetsov
0a39866045 for github actions added step to build android application 2022-11-27 01:21:42 +03:00
vladimir.kuznetsov
48734689d8 for github actions added step to build macos and linux application 2022-11-27 01:21:41 +03:00
vladimir.kuznetsov
dfe927dcbd for github actions added step to build ios application 2022-11-27 01:21:41 +03:00
vladimir.kuznetsov
ca158def31 temporarily turned off the deployment of artifacts 2022-11-27 01:21:41 +03:00
vladimir.kuznetsov
409386336d for github actions added steps to build x32/x64 windows application 2022-11-27 01:21:41 +03:00
vladimir.kuznetsov
eeed6c3474 chore/revert link to dev qtkeychain submodule 2022-11-27 01:21:40 +03:00
pokamest
3296cd6c39 GH actions 12 2022-11-27 01:21:40 +03:00
pokamest
60e25d9c67 GH actions 11 2022-11-27 01:21:40 +03:00
pokamest
ec65e2025e GH actions 10 2022-11-27 01:21:39 +03:00
pokamest
f09020c3bc GH actions 9 2022-11-27 01:21:39 +03:00
pokamest
91baaed96d GH actions 8 2022-11-27 01:21:39 +03:00
pokamest
64de64ce33 GH actions 7 2022-11-27 01:21:38 +03:00
pokamest
b685e7008e GH actions 6 2022-11-27 01:21:38 +03:00
pokamest
375b3d776c GH actions 5 2022-11-27 01:21:38 +03:00
pokamest
c1fddd7164 GH actions 4 2022-11-27 01:21:37 +03:00
pokamest
3af9bf9e12 GH actions 3 2022-11-27 01:21:37 +03:00
pokamest
9ef5d0c144 GH actions 3 2022-11-27 01:21:37 +03:00
pokamest
3d1b37dc85 gh actions 2 2022-11-27 01:21:36 +03:00
pokamest
80ce8347f6 GH actions 1 2022-11-27 01:21:36 +03:00
vladimir.kuznetsov
3eb7e1392d feature/added cmake support for linux 2022-11-20 21:25:15 +03:00
vladimir.kuznetsov
ac78a44d74 fixed padding in build script 2022-11-18 17:06:52 +03:00
vladimir.kuznetsov
87fed9fde3 fixed connection with qssh 2022-11-18 16:42:22 +03:00
vladimir.kuznetsov
2564430046 build script now uses cmake, also:
- fixed linking qt6keychain and SortFilterProxyModel
- added translations
2022-11-15 23:31:55 +03:00
vladimir.kuznetsov
663861dc09 for debug target added deploy files required to run the application on Windows, also:
- added deploy additional files for android
- fixed include android libraries
2022-11-15 14:16:36 +03:00
vladimir.kuznetsov
2d6a12101e in CMakeLists source files are common for all platforms, now added via FILE(GLOB) 2022-11-14 22:22:38 +03:00
vladimir.kuznetsov
e40110fa4c added platform specific commands to cmake files 2022-11-12 23:52:15 +03:00
vladimir.kuznetsov
6ac162f3cd added cmake files for client project 2022-11-09 23:54:30 +03:00
vladimir.kuznetsov
aea1d16e31 added files for linux and mac to CMakeLists for server and wireguard-service projects 2022-11-08 21:32:17 +03:00
vladimir.kuznetsov
16e26ef215 added CMakeLists for server and wireguard-service projects 2022-11-07 23:59:09 +03:00
vladimir.kuznetsov
7270e701d4 hostname is now added to the server name for imported openvpn and wireguard configs 2022-11-05 19:40:51 +03:00
pokamest
c8010d4d52 Merge pull request #125 from amnezia-vpn/qt_migration-settings-btn
Added Settings button on Start Page
2022-11-05 16:42:24 +03:00
vladimir.kuznetsov
6941b7463e added display of wireguard configs, such a config will be displayed as raw text 2022-11-04 23:31:39 +03:00
vladimir.kuznetsov
99a6cd82b2 added import of configs in wireguard format 2022-11-03 23:39:58 +03:00
vladimir.kuznetsov
1a44307664 added protocol_defs for new config keywords 2022-11-01 23:24:58 +03:00
vladimir.kuznetsov
53d7a92a0d added import of configs in .ovpn format
- on the "OpenVPN Settings" page, such a config will be displayed as raw text
2022-11-01 23:12:42 +03:00
Hamza ARBI
4ba1f47423 Disable Servers settings item when no server has been set
Fix the logic of *Add Server* to comeback to start page instead of push when no server is set
2022-10-30 22:53:45 +01:00
Hamza ARBI
c38e47b726 Update SvgImageType icon color when the item is disabled 2022-10-30 02:06:51 +01:00
Hamza ARBI
e6a4d79b86 Add settings button on PageStart
Disable some items when no Server has been set
2022-10-30 02:06:20 +01:00
pokamest
b62d0697be Merge pull request #123 from amnezia-vpn/openvpn_addditional_configs
OpenVPN additional config
2022-10-26 17:02:13 +03:00
vladimir.kuznetsov
f90ebbbb4e added inclusion of an additional client/server config when generating configs from templates
- fixed name in additional server config field
2022-10-26 14:06:03 +03:00
Hamza ARBI
ab39802512 Using Basic theme in first place 2022-10-24 14:05:28 +01:00
Hamza ARBI
84da67adda Using Basic style in the first place 2022-10-24 13:56:12 +01:00
Hamza ARBI
cfff3c6d97 Used Universal Theme to fix QtQuick Controls 2022-10-24 13:50:41 +01:00
Hamza ARBI
cc3d9e0d2d Fix all QML headers and change the deprecated QML components
* QZXing : Error while integrating it
2022-10-20 20:09:17 +01:00
pokamest
442e7eb015 Merge branch 'dev' into qt_migration 2022-10-15 19:46:26 +03:00
pokamest
59248b7c2e Merge pull request #114 from outspace/dev
Set security screen for Android app
2022-09-23 23:41:42 +03:00
Mykola Baibuz
f2d7a45b74 Set security screen for Android app
This will guarantee that even apps running with root privileges are unable to directly capture information displayed by the app on the screen.
2022-09-23 22:03:28 +03:00
pokamest
c79b6147ea Merge pull request #113 from outspace/dev
Add auth protection for ssh key export (Android)
2022-09-22 21:15:35 +03:00
Mykola Baibuz
d93be76505 Add auth protection for ssh key export
We use a builtin keyguard for ssh key export protection on Android.

This protection works only if some protection is set on the phone.

https://developer.android.com/reference/android/app/KeyguardManager#isDeviceSecure()
2022-09-19 12:32:06 +03:00
pokamest
5fff65db5a Tiny fixes 2022-09-19 00:44:00 +03:00
pokamest
53e240add7 Android manifest fix 2022-09-12 14:57:00 +03:00
pokamest
9cfc65eeda Version bump 2022-09-11 00:24:43 +03:00
pokamest
7d09d41a7d Merge pull request #108 from amnezia-vpn/dev
Release 2.1.0
2022-09-02 14:08:31 +03:00
pokamest
ac74510d47 Some fixes for Qt6 Android 2022-08-31 15:18:33 +03:00
pokamest
33ec69d33a Merge pull request #102 from omortie/qt_migration
migrated the codebase to Qt6 and fixed some compatibility issues
2022-08-31 13:53:55 +03:00
Mortie
8c20a67cfa migrated the codebase to Qt6 and fixed some compatibility issues
* used a Qt6 ported version of SortFilterProxyModel
* used an updated Qt6 compatible version of QXZing
* added a flag to windows linker to avoid WinMain problem of MSVCRTD
* renamed utils.cpp to utilities.cpp for avoiding confusion with the same file name in SortFilterProxyModel
2022-08-29 12:21:09 +04:30
pokamest
050d987d3b Merge branch 'dev' into qt_migration 2022-08-20 17:27:57 +03:00
pokamest
4b7a8c6d6e Start Qt6 migration 2022-08-10 14:00:04 +03:00
624 changed files with 13593 additions and 1516731 deletions

1
.gitattributes vendored
View File

@@ -2,3 +2,4 @@ deploy/data/windows/x64/tap/windows_7/OemVista.inf eol=crlf
deploy/data/windows/x64/tap/windows_10/OemVista.inf eol=crlf
deploy/data/windows/x32/tap/windows_7/OemVista.inf eol=crlf
deploy/data/windows/x32/tap/windows_10/OemVista.inf eol=crlf
client/3rd/* linguist-vendored

329
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,329 @@
name: 'Deploy workflow'
on: [push]
jobs:
Build-Linux-Ubuntu:
name: 'Build-Linux-Ubuntu'
runs-on: ubuntu-latest
env:
QT_VERSION: 6.5.0
QIF_VERSION: 4.5
steps:
- name: 'Install Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'desktop'
arch: 'gcc_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
- name: 'Get sources'
uses: actions/checkout@v3
with:
submodules: 'true'
fetch-depth: 10
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Build project'
run: |
sudo apt-get install libxkbcommon-x11-0
export QT_BIN_DIR=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64/bin
export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin
bash deploy/build_linux.sh
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_Linux_installer
path: deploy/AmneziaVPN_Linux_Installer
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_Linux_unpacked
path: deploy/AppDir
retention-days: 7
# ------------------------------------------------------
Build-Windows:
name: Build-Windows
runs-on: windows-latest
env:
QT_VERSION: 6.5.0
QIF_VERSION: 4.5
BUILD_ARCH: 64
steps:
- name: 'Get sources'
uses: actions/checkout@v3
with:
submodules: 'true'
fetch-depth: 10
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Install Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'windows'
target: 'desktop'
arch: 'win64_msvc2019_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
- name: 'Setup mvsc'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: 'x64'
- name: 'Build project'
shell: cmd
run: |
set BUILD_ARCH=${{ env.BUILD_ARCH }}
set QT_BIN_DIR="${{ runner.temp }}\\Qt\\${{ env.QT_VERSION }}\\msvc2019_64\\bin"
set QIF_BIN_DIR="${{ runner.temp }}\\Qt\\Tools\\QtInstallerFramework\\${{ env.QIF_VERSION }}\\bin"
call deploy\\build_windows.bat
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_Windows_installer
path: AmneziaVPN_x${{ env.BUILD_ARCH }}.exe
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_Windows_unpacked
path: deploy\\build_${{ env.BUILD_ARCH }}\\client\\Release
retention-days: 7
# ------------------------------------------------------
Build-IOS:
name: 'Build-IOS'
runs-on: macos-latest
env:
QT_VERSION: 6.5.0
steps:
- name: 'Setup xcode'
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '13.4'
- name: 'Install desktop Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'mac'
target: 'desktop'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia'
arch: 'clang_64'
dir: ${{ runner.temp }}
set-env: 'true'
- name: 'Install iOS Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'mac'
target: 'ios'
modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install go'
uses: actions/setup-go@v3
- name: 'Setup gomobile'
run: |
export PATH=$PATH:~/go/bin
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
- name: 'Get sources'
uses: actions/checkout@v3
with:
submodules: 'true'
fetch-depth: 10
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Build project'
run: |
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/ios/bin"
export QT_MACOS_ROOT_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos"
export QT_IOS_BIN=$QT_BIN_DIR
export PATH=$PATH:~/go/bin
mkdir build-ios
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR
# - name: iOS Build/Release With Multiple Targets Action
# uses: kumarsunil0007/build-ios-action@latest
# with:
# project-path: build-ios/AmneziaVPN.xcodeproj
# p12-base64: ~/amnezia-vpn/amnezia-ios-certificates/certs/distribution/443886Q5PL.p12
# mobileprovision-base64: ~/amnezia-vpn/amnezia-ios-certificates/testprofilez.mobileprovision
# code-signing-identity: 'iOS Distribution'
# team-id: 'X7UJ388FXK'
# configuration: Release
# ------------------------------------------------------
Build-MacOS:
name: 'Build-MacOS'
runs-on: macos-latest
env:
QT_VERSION: 6.5.0
QIF_VERSION: 4.5
steps:
- name: 'Setup xcode'
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '13.4'
- name: 'Install Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'mac'
target: 'desktop'
arch: 'clang_64'
modules: 'qtremoteobjects qt5compat qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
- name: 'Get sources'
uses: actions/checkout@v3
with:
submodules: 'true'
fetch-depth: 10
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Build project'
run: |
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
export QIF_BIN_DIR="${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin"
bash deploy/build_macos.sh
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_MacOS_installer
path: AmneziaVPN.dmg
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
with:
name: AmneziaVPN_MacOS_unpacked
path: deploy/build/client/AmneziaVPN.app
retention-days: 7
# ------------------------------------------------------
Build-Android:
name: 'Build-Android'
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
arch: ['android_x86_64', 'android_x86'] #, 'android_armv7', 'android_arm64_v8a']
env:
QT_VERSION: 6.5.0
steps:
- name: 'Install desktop Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'desktop'
arch: 'gcc_64'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install android Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: ${{ matrix.arch }}
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install GO'
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: 'Get sources'
uses: actions/checkout@v3
with:
submodules: 'true'
fetch-depth: 10
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Setup Java'
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: 'Build project'
run: |
export QT_HOST_PATH="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64"
export NDK_VERSION=23c
export ANDROID_NDK_PLATFORM=android-23
export ANDROID_NDK_HOME=${{ runner.temp }}/android-ndk-r${NDK_VERSION}
export ANDROID_NDK_ROOT=$ANDROID_NDK_HOME
export ANDROID_CURRENT_ARCH=${{ matrix.arch }}
if [ ! -f $ANDROID_NDK_ROOT/ndk-build ]; then
wget https://dl.google.com/android/repository/android-ndk-r${NDK_VERSION}-linux.zip -qO ${{ runner.temp }}/ndk.zip &&
unzip -q -d ${{ runner.temp }} ${{ runner.temp }}/ndk.zip ;
fi
export QT_BIN_DIR=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/${{ matrix.arch }}/bin
bash deploy/build_android.sh

142
.github/workflows/tag-deploy.yml vendored Normal file
View File

@@ -0,0 +1,142 @@
name: 'Release deploy workflow'
on:
workflow_dispatch:
# push:
# tags:
# - **
jobs:
Build-Android-Release:
name: 'Build-Android-Release'
runs-on: ubuntu-latest
env:
QT_VERSION: 6.4.1
QIF_VERSION: 4.5
steps:
- name: 'Install desktop Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'desktop'
arch: 'gcc_64'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install android Qt x86_64'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_x86_64'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install android Qt x86'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_x86'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install android Qt arm_v7'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_armv7'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Install android Qt arm_v8'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_arm64_v8a'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
- name: 'Get sources'
uses: actions/checkout@v3
with:
path: main
submodules: 'true'
fetch-depth: 10
- name: 'Preparations before keystore fetching'
run: |
mkdir keystore
- name: 'Getting keystore'
uses: actions/checkout@v3
with:
repository: amnezia-vpn/amnezia-android-certificates
ssh-key: ${{ secrets.ANDROID_CERTS_SSH_PRIVATE_KEY }}
path: keystore
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: 'Setup Java'
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: 'Build project'
run: |
export QT_HOST_PATH="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64"
export NDK_VERSION=23c
export ANDROID_NDK_PLATFORM=android-23
export ANDROID_NDK_HOME=${{ runner.temp }}/android-ndk-r${NDK_VERSION}
export ANDROID_NDK_ROOT=$ANDROID_NDK_HOME
if [ ! -f $ANDROID_NDK_ROOT/ndk-build ]; then
wget https://dl.google.com/android/repository/android-ndk-r${NDK_VERSION}-linux.zip -qO ${{ runner.temp }}/ndk.zip &&
unzip -q -d ${{ runner.temp }} ${{ runner.temp }}/ndk.zip ;
fi
export QT_BIN_DIR=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/android_arm64_v8a/bin
cd main
bash deploy/build_android.sh
- name: 'Signing APK'
run: |
pwd
ANDROID_BUILD_TOOLS_VERSION=30.0.3
${ANDROID_HOME}/build-tools/${ANDROID_BUILD_TOOLS_VERSION}/zipalign -f -v 4 AmneziaVPN-release-unsigned.apk AmneziaVPN-release-aligned.apk
${ANDROID_HOME}/build-tools/${ANDROID_BUILD_TOOLS_VERSION}/apksigner sign --out AmneziaVPN-release-signed.apk --ks keystore/debug.keystore --ks-key-alias ${{ secrets.DEBUG_ANDROID_KEYSTORE_KEY_ALIAS }} --ks-pass pass:${{secrets.DEBUG_ANDROID_KEYSTOTE_KEY_PASS }} AmneziaVPN-release-aligned.apk
- name: 'Upload'
uses: actions/upload-artifact@v3
with:
name: Release APK
path: ${{ runner.temp }}/main/AmneziaVPN-release-signed.apk

5
.gitignore vendored
View File

@@ -23,6 +23,7 @@ qrc_*.cpp
ui_*.h
Makefile*
*build-*
compile_commands.json
# fastlane
client/fastlane/report.xml
@@ -125,3 +126,7 @@ captures/
# Android Profiling
*.hprof
client/3rd/ShadowSocks/ss_ios.xcconfig
# UML generated pics
out/

41
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "3rd/QtSsh"]
path = 3rd/QtSsh
url = https://github.com/amnezia-vpn/QtSsh.git
[submodule "client/3rd/wireguard-tools"]
path = client/3rd/wireguard-tools
url = https://github.com/WireGuard/wireguard-tools/
@@ -9,7 +6,7 @@
url = https://github.com/WireGuard/wireguard-apple
[submodule "client/3rd/OpenVPNAdapter"]
path = client/3rd/OpenVPNAdapter
url = https://github.com/ss-abramchuk/OpenVPNAdapter.git
url = https://github.com/amnezia-vpn/OpenVPNAdapter.git
[submodule "client/3rd/ShadowPath"]
path = client/3rd/ShadowPath
url = https://github.com/qman9501/ShadowPath
@@ -25,3 +22,39 @@
[submodule "client/3rd/qtkeychain"]
path = client/3rd/qtkeychain
url = https://github.com/frankosterfeld/qtkeychain.git
[submodule "client/3rd/libssh"]
path = client/3rd/libssh
url = https://git.libssh.org/projects/libssh.git/
[submodule "client/3rd/zlib"]
path = client/3rd/zlib
url = https://github.com/madler/zlib.git
[submodule "client/3rd/SortFilterProxyModel"]
path = client/3rd/SortFilterProxyModel
url = https://github.com/mitchcurtis/SortFilterProxyModel.git
[submodule "client/android/cpp/openvpn3"]
path = client/android/cpp/openvpn3
url = https://github.com/amnezia-vpn/openvpn3.git
[submodule "client/android/cpp/asio"]
path = client/android/cpp/asio
url = https://github.com/chriskohlhoff/asio
[submodule "client/android/cpp/lz4"]
path = client/android/cpp/lz4
url = https://github.com/lz4/lz4.git
[submodule "client/android/cpp/mbedtls"]
path = client/android/cpp/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
[submodule "client/android/cpp/openvpn"]
path = client/android/cpp/openvpn
url = https://github.com/schwabe/openvpn.git
[submodule "client/android/cpp/openssl"]
path = client/android/cpp/openssl
url = https://github.com/schwabe/platform_external_openssl.git
[submodule "client/android/cpp/cloak"]
path = client/android/cpp/cloak
url = https://github.com/amnezia-vpn/Cloak
[submodule "client/android/cpp/lzo"]
path = client/android/cpp/lzo
url = https://github.com/amnezia-vpn/lzo.git
[submodule "client/3rd/mbedtls"]
path = client/3rd/mbedtls
url = https://github.com/Mbed-TLS/mbedtls.git

47
.gitpod.Dockerfile vendored Normal file
View File

@@ -0,0 +1,47 @@
FROM gitpod/workspace-full-vnc
USER gitpod
RUN sudo apt-get -q update \
&& sudo apt-get install -yq \
build-essential \
libgl1-mesa-dev \
libgstreamer-gl1.0-0 \
libpulse-dev \
libsecret-1-dev \
libxcb-glx0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-keysyms1 \
libxcb-randr0 \
libxcb-render-util0 \
libxcb-render0 \
libxcb-shape0 \
libxcb-shm0 \
libxcb-sync1 \
libxcb-util1 \
libxcb-xfixes0 \
libxcb-xinerama0 \
libxcb1 \
libxkbcommon-dev \
libxkbcommon-x11-0 \
libxcb-xkb-dev \
p7zip-full \
&& sudo rm -rf /var/lib/apt/lists/*
RUN sudo pip3 install aqtinstall
ARG QT_VERSION=6.4.1
ARG QT_ARCH=gcc_64
ARG QT_DIR=/opt/qt
RUN sudo aqt install-qt --outputdir ${QT_DIR} linux desktop ${QT_VERSION} ${QT_ARCH} --modules \
qtremoteobjects \
qt5compat \
qtshadertools
ENV QT_BIN_DIR=${QT_DIR}/${QT_VERSION}/${QT_ARCH}/bin
ARG QIF_VERSION=4.5
ARG QIF_DIR=/opt/qif
RUN sudo aqt install-tool --outputdir ${QIF_DIR} linux desktop tools_ifw
ENV QIF_BIN_DIR=${QIF_DIR}/Tools/QtInstallerFramework/${QIF_VERSION}/bin

8
.gitpod.yml Normal file
View File

@@ -0,0 +1,8 @@
tasks:
- init: >-
deploy/build_linux.sh
image:
file: .gitpod.Dockerfile
vscode:
extensions:
- llvm-vs-code-extensions.vscode-clangd

View File

@@ -1,342 +0,0 @@
branches:
only:
- master
- dev
- /\d+\.\d+/
jobs:
include:
- name: MacOS
os: osx
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt mac desktop $QT_VERSION clang_64 -m all -O $HOME/Qt && \
python3 -m aqt install-tool mac desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- bash deploy/build_macos.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.dmg"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
# ------------------------------------------------------
- name: Windows_x64
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2019_64\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=64
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
aqt install-qt windows desktop $QT_VERSION win64_msvc2019_64 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
- choco install ccache
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN_x64.exe"
on:
tags: true
branch: master
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Windows_x32
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2019\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=32
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
aqt install-qt windows desktop $QT_VERSION win32_msvc2019 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
- choco install ccache
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\"" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN_x32.exe"
on:
tags: true
branch: master
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Linux
os: linux
language: cpp
dist: focal
addons:
apt:
packages:
- p7zip
- p7zip-full
- python3
- python3-pip
- libgl-dev
- mesa-common-dev
- libpulse-dev
- libxcb-*
- libxkbcommon-x11-0
env:
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/gcc_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
python3 -m pip install --user $(whoami) --upgrade pip && \
export PATH=$HOME/.local/bin:$PATH && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux desktop $QT_VERSION gcc_64 -m all -O $HOME/Qt && \
python3 -m aqt install-tool linux desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- bash deploy/build_linux.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.bundle"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
# ------------------------------------------------------
- name: Android
os: linux
language: cpp
dist: focal
env:
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/android/bin
- ANDROID_API_VERSION=android-21
- ANDROID_HOME=$HOME/sdk
- ANDROID_SDK_ROOT=$ANDROID_HOME
- LOCAL_ANDROID_HOME=$ANDROID_HOME
- LOCAL_ANDROID_SDK_ROOT=$ANDROID_HOME
- NDK_VERSION=21d
- ANDROID_NDK_PLATFORM=android-21
- ANDROID_NDK_HOME=$HOME/android-ndk-r${NDK_VERSION}
- ANDROID_NDK_ROOT=$ANDROID_NDK_HOME
- ANDROID_NDK_HOST=linux-x86_64
- LOCAL_ANDROID_NDK_HOME=$ANDROID_NDK_HOME
- LOCAL_ANDROID_NDK_HOST_PLATFORM=$ANDROID_NDK_HOST
- JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
- TERM=dumb
addons:
apt:
packages:
- p7zip
- python3
- python3-pip
- openjdk-8-jdk
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux android $QT_VERSION -m all -O $HOME/Qt ; \
fi
- |
if [ ! -f $ANDROID_SDK_ROOT/tools/bin/sdkmanager ]; then \
echo "Download Android SDK" && \
wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip -qO $HOME/sdk.zip > /dev/null && \
unzip -q -d $ANDROID_SDK_ROOT $HOME/sdk.zip && \
echo "Download tools" && \
yes | $ANDROID_SDK_ROOT/tools/bin/sdkmanager --licenses > /dev/null 2>&1 && \
$ANDROID_SDK_ROOT/tools/bin/sdkmanager --install "cmdline-tools;latest" "platform-tools" "platforms;android-30" "build-tools;30.0.2" > /dev/null 2>&1 || exit 1 ; \
fi
- |
if [ ! -f $ANDROID_NDK_ROOT/ndk-build ]; then \
wget https://dl.google.com/android/repository/android-ndk-r${NDK_VERSION}-linux-x86_64.zip -qO $HOME/ndk.zip &&
unzip -q -d $HOME $HOME/ndk.zip ; \
fi
script:
- bash deploy/build_android.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.aab"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
- $ANDROID_NDK_HOME
- $ANDROID_SDK_ROOT
# ------------------------------------------------------
- name: iOS
os: osx
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:~/go/bin:$PATH
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/ios/bin
- QT_IOS_BIN=$QT_BIN_DIR
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt mac ios $QT_VERSION -m all -O $HOME/Qt ; \
fi
- brew install golang
- go install golang.org/x/mobile/cmd/gomobile@latest
- gomobile init
script:
- bash deploy/build_ios.sh
after_script:
- ccache --show-stats
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
before_cache:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi
# Cache only .git files under "/usr/local/Homebrew" so "brew update" does not take 5min every build
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then find /usr/local/Homebrew \! -regex ".+\.git.+" -delete; fi

View File

@@ -1,6 +0,0 @@
TEMPLATE = subdirs
SUBDIRS = client
!ios:!android {
SUBDIRS += service
}

26
CMakeLists.txt Normal file
View File

@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 3.0.7.2
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
set(RELEASE_DATE "2023-05-15")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
if(ANDROID)
set(QT_ANDROID_BUILD_ALL_ABIS ON)
endif()
if(APPLE AND NOT IOS)
set(CMAKE_OSX_ARCHITECTURES "x86_64")
endif()
add_subdirectory(client)
if(NOT IOS AND NOT ANDROID)
add_subdirectory(service)
include(${CMAKE_SOURCE_DIR}/deploy/installer/config.cmake)
endif()

View File

@@ -1,16 +1,16 @@
# Amnezia VPN
## _The best client for self-hosted VPN_
[![Build Status](https://travis-ci.com/amnezia-vpn/desktop-client.svg?branch=master)](https://travis-ci.com/amnezia-vpn/desktop-client)
[![Build Status](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml/badge.svg?branch=dev)](https://github.com/amnezia-vpn/amnezia-client/actions/workflows/deploy.yml?query=branch:dev)
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
Amnezia is a VPN client with the key feature of deploying your own VPN server on you virtual server.
## Features
- Very easy to use - enter your ip address, ssh login and password, and Amnezia client will automatically install VPN docker containers to your server and connect to VPN.
- OpenVPN and OpenVPN over ShadowSocks protocols support.
- Custom VPN routing mode support - add any sites to client to enable VPN only for them.
- Windows and MacOS support.
- Unsecure sharing connection profile for family use.
- OpenVPN, ShadowSocks, WireGuard, IKEv2 protocols support.
- Split tunneling support - add any sites to client to enable VPN only for them (only for desktops)
- Windows, MacOS, Linux, Android, iOS releases.
## Tech
@@ -20,7 +20,7 @@ AmneziaVPN uses a number of open source projects to work:
- [OpenVPN](https://openvpn.net/)
- [ShadowSocks](https://shadowsocks.org/)
- [Qt](https://www.qt.io/)
- [QtSsh](https://github.com/jaredtao/QtSsh) - forked form Qt Creator
- [LibSsh](https://libssh.org) - forked form Qt Creator
- and more...
## Checking out the source code
@@ -36,39 +36,35 @@ git submodule update --init
Want to contribute? Welcome!
### Building sources and deployment
Easiest way to build your own executables - is to fork project and configure [Travis CI](https://travis-ci.com/)
Or you can build sources manually using Qt Creator. Qt >= 14.2 supported.
Look to the `build_macos.sh` and `build_windows.bat` scripts in `deploy` folder for details.
Look deploy folder for build scripts.
### How to build iOS app from source code on MacOS
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed,
at least version 12 or higher.
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher.
2. We use `qmake` to generate the XCode project and then we "patch" it to add
extra components such as the wireguard, the browser bridge and so on. We patch
the XCode project using [xcodeproj](https://github.com/CocoaPods/Xcodeproj). To
install it:
```bash
gem install xcodeproj # probably you want to run this command with `sudo`
```
3. You also need to install go >= v1.16. If you don't have it done already,
2. We use QT to generate the XCode project. we need QT version 6.4. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html)
3. Install cmake is require. We recommend cmake version 3.25. You can install cmake in [here](https://cmake.org/download/)
4. You also need to install go >= v1.16. If you don't have it done already,
download go from the [official website](https://golang.org/dl/) or use Homebrew.
Latest version is recommended.
4. Navigate inside client folder and generate the XCode project using our script:
Latest version is recommended. Install gomobile
```bash
cd client
./scripts/apple_compile.sh ios
export PATH=$PATH:~/go/bin
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
```
If you have more than one version of Qt installed, you'll most likely get
a "`qmake` cannot be found in your `$PATH`" error. In this case run this script
using QT\IOS\_BIN env to set the path for the Qt5 macos build bin folder.
For example, the path could look like this:
5. Build project
```bash
QT_IOS_BIN="/Users/username/Qt/5.15.2/ios/bin" ./scripts/apple_compile.sh ios
export QT_BIN_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/ios/bin"
export QT_IOS_BIN=$QT_BIN_DIR
export PATH=$PATH:~/go/bin
mkdir build-ios
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_BIN_DIR
```
Replace PATH-TO-QT-FOLDER and QT-VERSION to your environment
If you get `gomobile: command not found` make sure to set PATH to the location
of the bin folder where gomobile was installed. Usually, it's in `GOPATH`.
@@ -76,7 +72,7 @@ of the bin folder where gomobile was installed. Usually, it's in `GOPATH`.
export PATH=$(PATH):/path/to/GOPATH/bin
```
5. Xcode should automatically open. You can then run/test/archive/ship the app.
5. Open XCode project. You can then run/test/archive/ship the app.
If build fails with the following error
```
@@ -87,10 +83,40 @@ Error 1
Add a user defined variable to both AmneziaVPN and WireGuardNetworkExtension targets' build settings with
key `PATH` and value `${PATH}/path/to/bin/folder/with/go/executable`, e.g. `${PATH}:/usr/local/go/bin`.
if above error still persists on you M1 Mac, then most probably you need to install arch based cmake
```
arch -arm64 brew install cmake
```
Build might fail with "source files not found" error the first time you try it, because modern XCode build system compiles
dependencies in parallel, and some dependencies end up being built after the ones that
require them. In this case simply restart the build.
## How to build the Android app
_tested on Mac OS_
The Android app has the following requirements:
* JDK 11
* Android platform SDK 33
* cmake 3.25.0
After you have installed QT, QT Creator and Android Studio installed, you need to configure QT Creator correctly. Click in the top menu bar on `QT Creator` -> `Preferences` -> `Devices` and select the tab `Android`.
* set path to jdk 11
* set path to Android SDK ($ANDROID_HOME)
In case you get errors regarding missing SDK or 'sdkmanager not running', you cannot fix them by correcting the paths and you have some spare GBs on your disk, you can let QT Creator install all requirements by choosing an empty folder for `Android SDK location` and click on `Set Up SDK`. Be aware: This will install a second Android SDK and NDK on your machine!
Double check that the right cmake version is configured: Click on `QT Creator` -> `Preferences` and click on the side menu on `Kits`. Under the center content view's `Kits` tab you'll find an entry `CMake Tool`. If the default selected CMake version is lower than 3.25.0, install on your system CMake >= 3.25.0 and choose `System CMake at <path>` from the drop down list. If this entry is missing, you either have not installed CMake yet or QT Creator hasn't found the path to it. In that case click in the preferences window on the side menu item `CMake`, then on the tab `Tools`in the center content view and finally on the Button `Add` to set the path to your installed CMake.
Please make sure that you have selected Android Platform SDK 33 for your project: click in the main view's side menu on on `Projects`, on the left you'll see a section `Build & Run` showing different Android build targets. You can select any of them, Amnezia VPN's project setup is designed in a way that always all Android targets will be build. Click on the targets submenu item `Build` and scroll in the center content view to `Build Steps`. Click on `Details` at the end of the headline `Build Android APK` (The `Details` button might be hidden in case QT Creator Window is not running in full screen!). Here we are: choose `android-33` as `Android Build platform SDK`.
That's it you should be ready to compile the project from QT Creator!
### Development flow
After you've hit the build button, QT-Creator copies the whole project to a folder in the repositories parent directory. The folder should look something like `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>`.
If you want to develop Amnezia VPNs Android components written in Kotlin, such as components using system APIs, you need to import the generated project in Android Studio with `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>/client/android-build` as the projects root directory. While you should be able to compile the generated project from Android Studio, you cannot work directly in the repository's Android project. So whenever you are confident with your work in the generated project, you'll need to copy and paste the affected files to the corresponding path in the repositories Android project so that you can add and commit your changes!
You may face compiling issues in QT Creator after you've worked in Android Studio on the generated project. Just do a `./gradlew clean` in the generated project's root directory (`<path>/client/android-build/.`) and you should be good to continue.
## License
GPL v.3

View File

@@ -0,0 +1,20 @@
include_directories(${CMAKE_CURRENT_LIST_DIR})
set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/include/QAead.h
${CMAKE_CURRENT_LIST_DIR}/include/QBlockCipher.h
${CMAKE_CURRENT_LIST_DIR}/include/QCryptoError.h
${CMAKE_CURRENT_LIST_DIR}/include/QRsa.h
${CMAKE_CURRENT_LIST_DIR}/include/QSimpleCrypto_global.h
${CMAKE_CURRENT_LIST_DIR}/include/QX509.h
${CMAKE_CURRENT_LIST_DIR}/include/QX509Store.h
)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/sources/QAead.cpp
${CMAKE_CURRENT_LIST_DIR}/sources/QBlockCipher.cpp
${CMAKE_CURRENT_LIST_DIR}/sources/QCryptoError.cpp
${CMAKE_CURRENT_LIST_DIR}/sources/QRsa.cpp
${CMAKE_CURRENT_LIST_DIR}/sources/QX509.cpp
${CMAKE_CURRENT_LIST_DIR}/sources/QX509Store.cpp
)

View File

@@ -1,50 +0,0 @@
# User settings
*.user
macOSPackage/
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
qrc_*.cpp
ui_*.h
Makefile*
*build-*
# QtCreator
*.autosave
# QtCtreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCtreator CMake
CMakeLists.txt.user*
# MACOS files
.DS_Store
._.DS_Store
._*
# tmp files
*.*~
# Certificates
*.p12

View File

@@ -1,3 +0,0 @@
load(qt_build_config)
MODULE_VERSION = 4.3.1

View File

@@ -1 +0,0 @@
load(qt_parts)

View File

@@ -1,46 +0,0 @@
# QSsh
this project is base on Qt-creator-open-source-4.3.1
project is at
`http://code.qt.io/cgit/qt-creator/qt-creator.git/`
you can download code zip at
`http://download.qt.io/official_releases/qtcreator/4.3/4.3.1/`
## Getting Started
> * For linux user, if your Qt is installed through package manager tools such "apt-get", make sure that you have installed the Qt5 develop package *qtbase5-private-dev*
### Usage(1): Use QtSsh as Qt5's addon module
#### Building the module
> **Note**: Perl is needed in this step.
* Download the source code.
* Put the source code in any directory you like
* Go to top directory of the project in a terminal and run
```
qmake
make
make install
```
The library, the header files, and others will be installed to your system.
#### Import the module
` QT += ssh`
#### Include Headerfile
` #include<QtSsh/sshconnection.h>`
#### Close qtc.ssh log
` QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false")`

View File

@@ -1,2 +0,0 @@
TEMPLATE = subdirs
SUBDIRS = gitlab

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/">
<file>Qml/Main.qml</file>
</qresource>
</RCC>

View File

@@ -1,51 +0,0 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
import Ssh 1.0
Item {
width: 1024
height: 768
TextField {
id: input
x: 104
y: 44
width: 482
height: 40
implicitWidth: 200
selectByMouse: true
text: "https://www.zhihu.com"
}
function get(url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log(xhr.responseXML, xhr.responseText.toString())
} else if (xhr.readyState === XMLHttpRequest) {
}
}
xhr.open('GET', url)
xhr.send()
}
Button {
x: 627
y: 44
text: "get"
onClicked: {
get(input.text)
}
}
Button {
id: button
x: 104
y: 170
text: qsTr("Ssh")
onClicked: ssh.connectToHost()
}
Ssh {
id: ssh
}
}

View File

@@ -1,17 +0,0 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include "Ssh.hpp"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<Ssh> ("Ssh", 1, 0, "Ssh");
QQuickView view;
view.setSource(QUrl("qrc:/Qml/Main.qml"));
view.show();
return app.exec();
}

View File

@@ -1,61 +0,0 @@
#include "Ssh.hpp"
#include <QDir>
#include <QDebug>
#include <QLoggingCategory>
Ssh::Ssh(QObject *parent) : QObject(parent) {
//关掉qtc.ssh中的各种打印信息
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
mParams.host="ftb.autoio.org";
mParams.userName = "ftb";
mParams.port = 11122;
mParams.privateKeyFile = QDir::homePath() + QStringLiteral("/.ssh/id_rsa");
mParams.timeout = 5;
mParams.authenticationType = SshConnectionParameters::AuthenticationTypePublicKey;
mParams.options = SshIgnoreDefaultProxy;
mParams.hostKeyCheckingMode = SshHostKeyCheckingNone;
mConnections = std::make_shared<SshConnection>(mParams);
connect(mConnections.get(), &SshConnection::error, [&](QSsh::SshError){
qWarning() << "Error: " << mConnections->errorString();
});
connect(mConnections.get(), &SshConnection::connected, [&](){
qWarning() << "Connected";
create();
});
connect(mConnections.get(), &SshConnection::disconnected, [](){
qWarning() << "Disconnected";
});
connect(mConnections.get(), &SshConnection::dataAvailable, [](const QString &message){
qWarning() << "Message: " << message;
});
}
void Ssh::connectToHost() {
mConnections->connectToHost();
}
void Ssh::create() {
mRemoteProcess = mConnections->createRemoteProcess(QString::fromLatin1("/bin/ls -a").toUtf8());
if (!mRemoteProcess) {
qWarning() << QLatin1String("Error: UnmRemoteProcess SSH connection creates remote process.");
return;
}
connect(mRemoteProcess.data(), &SshRemoteProcess::started, [&](){
qWarning() << "started";
});
connect(mRemoteProcess.data(), &SshRemoteProcess::readyReadStandardOutput, [&](){
qWarning() << "StandardOutput";
qWarning() << QString::fromLatin1(mRemoteProcess->readAllStandardOutput()).split('\n');
});
connect(mRemoteProcess.data(), &SshRemoteProcess::readyReadStandardError, [&](){
qWarning() << "StandardError" << mRemoteProcess->readAllStandardError();
});
connect(mRemoteProcess.data(), &SshRemoteProcess::closed, [&](int exitStatus){
qWarning() << "Exit" << exitStatus;
});
mRemoteProcess->start();
}

View File

@@ -1,26 +0,0 @@
#pragma once
#include <memory>
#include <cstdlib>
#include <functional>
#include <QObject>
#include <QtSsh/sshconnection.h>
#include <QtSsh/sshremoteprocess.h>
using namespace QSsh;
class Ssh : public QObject {
Q_OBJECT
public:
explicit Ssh(QObject *parent = nullptr);
Q_INVOKABLE void connectToHost();
void create();
private:
SshConnectionParameters mParams;
std::shared_ptr<SshConnection> mConnections;
QSharedPointer<SshRemoteProcess> mRemoteProcess;
};

View File

@@ -1,29 +0,0 @@
QT += quick network ssh
CONFIG += c++11
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
#DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += Src/Main.cpp \
Src/Ssh.cpp
RESOURCES += Qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
HEADERS += \
Src/Ssh.hpp

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,72 +0,0 @@
INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD
CONFIG += c++17
INCLUDEPATH += $$PWD/include/external
win32 {
QMAKE_CXXFLAGS += -bigobj
LIBS += \
-lcrypt32 \
!contains(QMAKE_TARGET.arch, x86_64) {
INCLUDEPATH += $$PWD/windows/x86
HEADERS += $$PWD/windows/x86/botan_all.h
SOURCES += $$PWD/windows/x86/botan_all.cpp
}
else {
INCLUDEPATH += $$PWD/windows/x86_64
HEADERS += $$PWD/windows/x86_64/botan_all.h
SOURCES += $$PWD/windows/x86_64/botan_all.cpp
}
}
macx:!ios {
INCLUDEPATH += $$PWD/macos
HEADERS += $$PWD/macos/botan_all.h
SOURCES += $$PWD/macos/botan_all.cpp
}
linux-g++ {
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) {
INCLUDEPATH += $$PWD/android/$${abi}
HEADERS += $$PWD/android/$${abi}/botan_all.h
SOURCES += $$PWD/android/$${abi}/botan_all.cpp
}
}
}
ios: {
CONFIG(iphoneos, iphoneos|iphonesimulator) {
contains(QT_ARCH, arm64) {
INCLUDEPATH += $$PWD/ios/iphone
HEADERS += $$PWD/ios/iphone/botan_all.h
SOURCES += $$PWD/ios/iphone/botan_all.cpp
} else {
message("Building for iOS/ARM v7 (32-bit) architecture")
ARCH_TAG = "ios_armv7"
}
}
CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
INCLUDEPATH += $$PWD/ios/iphone
HEADERS += $$PWD/ios/iphone/botan_all.h
SOURCES += $$PWD/ios/iphone/botan_all.cpp
}
# CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
# INCLUDEPATH += $$PWD/ios/simulator
# HEADERS += $$PWD/ios/simulator/botan_all.h
# SOURCES += $$PWD/ios/simulator/botan_all.cpp
# }
}

View File

@@ -1,264 +0,0 @@
/*
* 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

@@ -1,938 +0,0 @@
/*
* 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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

View File

@@ -1,200 +0,0 @@
/****************************************************************************
**
** 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,73 +0,0 @@
/****************************************************************************
**
** 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.
**
****************************************************************************/
#pragma once
#include <QByteArray>
#include <QList>
#include <botan_all.h>
#include <memory>
namespace Botan {
class Private_Key;
class RandomNumberGenerator;
}
namespace QSsh {
namespace Internal {
class OpenSshKeyFileReader
{
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

@@ -1,97 +0,0 @@
QT += gui network widgets
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
#!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 \
$$PWD/sshoutgoingpacket.cpp \
$$PWD/sshkeygenerator.cpp \
$$PWD/sshkeyexchange.cpp \
$$PWD/sshincomingpacket.cpp \
$$PWD/sshcryptofacility.cpp \
$$PWD/sshconnection.cpp \
$$PWD/sshchannelmanager.cpp \
$$PWD/sshchannel.cpp \
$$PWD/sshcapabilities.cpp \
$$PWD/sftppacket.cpp \
$$PWD/sftpoutgoingpacket.cpp \
$$PWD/sftpoperation.cpp \
$$PWD/sftpincomingpacket.cpp \
$$PWD/sftpdefs.cpp \
$$PWD/sftpchannel.cpp \
$$PWD/sshremoteprocessrunner.cpp \
$$PWD/sshconnectionmanager.cpp \
$$PWD/sshkeypasswordretriever.cpp \
$$PWD/sftpfilesystemmodel.cpp \
$$PWD/sshdirecttcpiptunnel.cpp \
$$PWD/sshhostkeydatabase.cpp \
$$PWD/sshlogging.cpp \
$$PWD/sshtcpipforwardserver.cpp \
$$PWD/sshtcpiptunnel.cpp \
$$PWD/sshforwardedtcpiptunnel.cpp \
$$PWD/sshagent.cpp \
$$PWD/sshx11channel.cpp \
$$PWD/sshx11inforetriever.cpp \
$$PWD/opensshkeyfilereader.cpp \
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/sshkeyexchange_p.h \
$$PWD/sshincomingpacket_p.h \
$$PWD/sshexception_p.h \
$$PWD/sshcryptofacility_p.h \
$$PWD/sshconnection_p.h \
$$PWD/sshchannelmanager_p.h \
$$PWD/sshchannel_p.h \
$$PWD/sshcapabilities_p.h \
$$PWD/sshbotanconversions_p.h \
$$PWD/sftppacket_p.h \
$$PWD/sftpoutgoingpacket_p.h \
$$PWD/sftpoperation_p.h \
$$PWD/sftpincomingpacket_p.h \
$$PWD/sftpchannel_p.h \
$$PWD/sshkeypasswordretriever_p.h \
$$PWD/sshdirecttcpiptunnel_p.h \
$$PWD/sshlogging_p.h \
$$PWD/sshtcpipforwardserver_p.h \
$$PWD/sshtcpiptunnel_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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,263 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTCHANNEL_H
#define SFTCHANNEL_H
#include "sftpdefs.h"
#include "ssh_global.h"
#include <QByteArray>
#include <QObject>
#include <QSharedPointer>
#include <QString>
namespace QSsh {
namespace Internal {
class SftpChannelPrivate;
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
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 means it finished successfully
void finished(QSsh::SftpJobId job, const SftpError errorType = SftpError::NoError, const QString &error = QString());
/*!
* 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);
Internal::SftpChannelPrivate *d;
};
} // namespace QSsh
#endif // SFTPCHANNEL_H

View File

@@ -1,135 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTCHANNEL_P_H
#define SFTCHANNEL_P_H
#include "sftpdefs.h"
#include "sftpincomingpacket_p.h"
#include "sftpoperation_p.h"
#include "sftpoutgoingpacket_p.h"
#include "sshchannel_p.h"
#include <QByteArray>
#include <QMap>
namespace QSsh {
class SftpChannel;
namespace Internal {
class SftpChannelPrivate : public AbstractSshChannel
{
Q_OBJECT
friend class QSsh::SftpChannel;
public:
enum SftpState { Inactive, SubsystemRequested, InitSent, Initialized };
signals:
void initialized();
void channelError(const QString &reason);
void closed();
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;
SftpChannelPrivate(quint32 channelId, SshSendFacility &sendFacility,
SftpChannel *sftp);
SftpJobId createJob(const AbstractSftpOperation::Ptr &job);
virtual void handleChannelSuccess();
virtual void handleChannelFailure();
virtual void handleOpenSuccessInternal();
virtual void handleOpenFailureInternal(const QString &reason);
virtual void handleChannelDataInternal(const QByteArray &data);
virtual void handleChannelExtendedDataInternal(quint32 type,
const QByteArray &data);
virtual void handleExitStatus(const SshChannelExitStatus &exitStatus);
virtual void handleExitSignal(const SshChannelExitSignal &signal);
virtual void closeHook();
void handleCurrentPacket();
void handleServerVersion();
void handleHandle();
void handleStatus();
void handleName();
void handleReadData();
void handleAttrs();
void handleDownloadDir(SftpListDir::Ptr op, const QList<SftpFileInfo> & fileInfoList);
void handleStatusGeneric(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleMkdirStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleLsStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handleGetStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
void handlePutStatus(JobMap::Iterator it,
const SftpStatusResponse &response);
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(JobMap::Iterator it);
void sendReadRequest(const SftpDownload::Ptr &job, quint32 requestId);
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);
void attributesToFileInfo(const SftpFileAttributes &attributes, SftpFileInfo &fileInfo) const;
JobMap::Iterator lookupJob(SftpJobId id);
JobMap m_jobs;
SftpOutgoingPacket m_outgoingPacket;
SftpIncomingPacket m_incomingPacket;
QByteArray m_incomingData;
SftpJobId m_nextJobId;
SftpState m_sftpState;
SftpChannel *m_sftp;
};
} // namespace Internal
} // namespace QSsh
#endif // SFTPCHANNEL_P_H

View File

@@ -1,33 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
namespace QSsh { const SftpJobId SftpInvalidJob = 0; }

View File

@@ -1,119 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 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 {
/*! 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;
/// 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,401 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshconnection.h"
#include "sshconnectionmanager.h"
#include <QFileInfo>
#include <QHash>
#include <QIcon>
#include <QList>
#include <QString>
namespace QSsh {
namespace Internal {
namespace {
class SftpDirNode;
class SftpFileNode
{
public:
SftpFileNode() : parent(nullptr) { }
virtual ~SftpFileNode() { }
QString path;
SftpFileInfo fileInfo;
SftpDirNode *parent;
};
class SftpDirNode : public SftpFileNode
{
public:
SftpDirNode() : lsState(LsNotYetCalled) { }
~SftpDirNode() { qDeleteAll(children); }
enum { LsNotYetCalled, LsRunning, LsFinished } lsState;
QList<SftpFileNode *> children;
};
typedef QHash<SftpJobId, SftpDirNode *> DirNodeHash;
SftpFileNode *indexToFileNode(const QModelIndex &index)
{
return static_cast<SftpFileNode *>(index.internalPointer());
}
SftpDirNode *indexToDirNode(const QModelIndex &index)
{
SftpFileNode * const fileNode = indexToFileNode(index);
QSSH_ASSERT(fileNode);
return dynamic_cast<SftpDirNode *>(fileNode);
}
} // anonymous namespace
class SftpFileSystemModelPrivate
{
public:
SshConnection *sshConnection;
SftpChannel::Ptr sftpChannel;
QString rootDirectory;
SftpFileNode *rootNode;
SftpJobId statJobId;
DirNodeHash lsOps;
QList<SftpJobId> externalJobs;
};
} // namespace Internal
using namespace Internal;
SftpFileSystemModel::SftpFileSystemModel(QObject *parent)
: QAbstractItemModel(parent), d(new SftpFileSystemModelPrivate)
{
d->sshConnection = nullptr;
d->rootDirectory = QLatin1Char('/');
d->rootNode = nullptr;
d->statJobId = SftpInvalidJob;
}
SftpFileSystemModel::~SftpFileSystemModel()
{
shutDown();
delete d;
}
void SftpFileSystemModel::setSshConnection(const SshConnectionParameters &sshParams)
{
QSSH_ASSERT_AND_RETURN(!d->sshConnection);
d->sshConnection = QSsh::acquireConnection(sshParams);
connect(d->sshConnection, &SshConnection::error,
this, &SftpFileSystemModel::handleSshConnectionFailure);
if (d->sshConnection->state() == SshConnection::Connected) {
handleSshConnectionEstablished();
return;
}
connect(d->sshConnection, &SshConnection::connected,
this, &SftpFileSystemModel::handleSshConnectionEstablished);
if (d->sshConnection->state() == SshConnection::Unconnected)
d->sshConnection->connectToHost();
}
void SftpFileSystemModel::setRootDirectory(const QString &path)
{
beginResetModel();
d->rootDirectory = path;
delete d->rootNode;
d->rootNode = nullptr;
d->lsOps.clear();
d->statJobId = SftpInvalidJob;
endResetModel();
statRootDirectory();
}
QString SftpFileSystemModel::rootDirectory() const
{
return d->rootDirectory;
}
SftpJobId SftpFileSystemModel::downloadFile(const QModelIndex &index, const QString &targetFilePath)
{
QSSH_ASSERT_AND_RETURN_VALUE(d->rootNode, SftpInvalidJob);
const SftpFileNode * const fileNode = indexToFileNode(index);
QSSH_ASSERT_AND_RETURN_VALUE(fileNode, SftpInvalidJob);
QSSH_ASSERT_AND_RETURN_VALUE(fileNode->fileInfo.type == FileTypeRegular, SftpInvalidJob);
const SftpJobId jobId = d->sftpChannel->downloadFile(fileNode->path, targetFilePath,
SftpOverwriteExisting);
if (jobId != SftpInvalidJob)
d->externalJobs << jobId;
return jobId;
}
int SftpFileSystemModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 2; // type + name
}
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(QStringLiteral(":/ssh/images/unknownfile.png"));
case FileTypeDirectory:
return QIcon(QStringLiteral(":/ssh/images/dir.png"));
case FileTypeUnknown:
return QIcon(QStringLiteral(":/ssh/images/help.png")); // Shows a question mark.
}
}
if (index.column() == 1) {
if (role == Qt::DisplayRole)
return node->fileInfo.name;
if (role == PathRole)
return node->path;
}
return QVariant();
}
Qt::ItemFlags SftpFileSystemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
QVariant SftpFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Horizontal)
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
if (section == 0)
return tr("File Type");
if (section == 1)
return tr("File Name");
return QVariant();
}
QModelIndex SftpFileSystemModel::index(int row, int column, const QModelIndex &parent) const
{
if (row < 0 || row >= rowCount(parent) || column < 0 || column >= columnCount(parent))
return QModelIndex();
if (!d->rootNode)
return QModelIndex();
if (!parent.isValid())
return createIndex(row, column, d->rootNode);
const SftpDirNode * const parentNode = indexToDirNode(parent);
QSSH_ASSERT_AND_RETURN_VALUE(parentNode, QModelIndex());
QSSH_ASSERT_AND_RETURN_VALUE(row < parentNode->children.count(), QModelIndex());
SftpFileNode * const childNode = parentNode->children.at(row);
return createIndex(row, column, childNode);
}
QModelIndex SftpFileSystemModel::parent(const QModelIndex &child) const
{
if (!child.isValid()) // Don't assert on this, since the model tester tries it.
return QModelIndex();
const SftpFileNode * const childNode = indexToFileNode(child);
QSSH_ASSERT_AND_RETURN_VALUE(childNode, QModelIndex());
if (childNode == d->rootNode)
return QModelIndex();
SftpDirNode * const parentNode = childNode->parent;
if (parentNode == d->rootNode)
return createIndex(0, 0, d->rootNode);
const SftpDirNode * const grandParentNode = parentNode->parent;
QSSH_ASSERT_AND_RETURN_VALUE(grandParentNode, QModelIndex());
return createIndex(grandParentNode->children.indexOf(parentNode), 0, parentNode);
}
int SftpFileSystemModel::rowCount(const QModelIndex &parent) const
{
if (!d->rootNode)
return 1; // fake it until we make it, otherwise QTreeView isn't happy
if (!parent.isValid())
return 1;
if (parent.column() != 0)
return 0;
SftpDirNode * const dirNode = indexToDirNode(parent);
if (!dirNode)
return 0;
if (dirNode->lsState != SftpDirNode::LsNotYetCalled)
return dirNode->children.count();
d->lsOps.insert(d->sftpChannel->listDirectory(dirNode->path), dirNode);
dirNode->lsState = SftpDirNode::LsRunning;
return 0;
}
void SftpFileSystemModel::statRootDirectory()
{
if (!d->sftpChannel) {
return;
}
d->statJobId = d->sftpChannel->statFile(d->rootDirectory);
}
void SftpFileSystemModel::shutDown()
{
if (d->sftpChannel) {
disconnect(d->sftpChannel.data(), nullptr, this, nullptr);
d->sftpChannel->closeChannel();
d->sftpChannel.clear();
}
if (d->sshConnection) {
disconnect(d->sshConnection, nullptr, this, nullptr);
QSsh::releaseConnection(d->sshConnection);
d->sshConnection = nullptr;
}
delete d->rootNode;
d->rootNode = nullptr;
}
void SftpFileSystemModel::handleSshConnectionFailure()
{
emit connectionError(d->sshConnection->errorString());
beginResetModel();
shutDown();
endResetModel();
}
void SftpFileSystemModel::handleSftpChannelInitialized()
{
connect(d->sftpChannel.data(),
&SftpChannel::fileInfoAvailable,
this, &SftpFileSystemModel::handleFileInfo);
connect(d->sftpChannel.data(), &SftpChannel::finished,
this, &SftpFileSystemModel::handleSftpJobFinished);
statRootDirectory();
}
void SftpFileSystemModel::handleSshConnectionEstablished()
{
d->sftpChannel = d->sshConnection->createSftpChannel();
connect(d->sftpChannel.data(), &SftpChannel::initialized,
this, &SftpFileSystemModel::handleSftpChannelInitialized);
connect(d->sftpChannel.data(), &SftpChannel::channelError,
this, &SftpFileSystemModel::handleSftpChannelError);
d->sftpChannel->initialize();
}
void SftpFileSystemModel::handleSftpChannelError(const QString &reason)
{
emit connectionError(reason);
beginResetModel();
shutDown();
endResetModel();
}
void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QList<SftpFileInfo> &fileInfoList)
{
if (jobId == d->statJobId) {
QSSH_ASSERT_AND_RETURN(!d->rootNode);
beginInsertRows(QModelIndex(), 0, 0);
d->rootNode = new SftpDirNode;
d->rootNode->path = d->rootDirectory;
d->rootNode->fileInfo = fileInfoList.first();
d->rootNode->fileInfo.name = d->rootDirectory == QLatin1String("/")
? d->rootDirectory : QFileInfo(d->rootDirectory).fileName();
endInsertRows();
return;
}
SftpDirNode * const parentNode = d->lsOps.value(jobId);
QSSH_ASSERT_AND_RETURN(parentNode);
QList<SftpFileInfo> filteredList;
foreach (const SftpFileInfo &fi, fileInfoList) {
if (fi.name != QLatin1String(".") && fi.name != QLatin1String(".."))
filteredList << fi;
}
if (filteredList.isEmpty())
return;
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;
if (fileInfo.type == FileTypeDirectory)
childNode = new SftpDirNode;
else
childNode = new SftpFileNode;
childNode->path = parentNode->path;
if (!childNode->path.endsWith(QLatin1Char('/')))
childNode->path += QLatin1Char('/');
childNode->path += fileInfo.name;
childNode->fileInfo = fileInfo;
childNode->parent = parentNode;
parentNode->children << childNode;
}
endInsertRows();
}
void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const SftpError error, const QString &errorMessage)
{
Q_UNUSED(error);
if (jobId == d->statJobId) {
d->statJobId = SftpInvalidJob;
if (!errorMessage.isEmpty())
emit sftpOperationFailed(tr("Error getting \"stat\" info about \"%1\": %2")
.arg(rootDirectory(), errorMessage));
return;
}
DirNodeHash::Iterator it = d->lsOps.find(jobId);
if (it != d->lsOps.end()) {
QSSH_ASSERT(it.value()->lsState == SftpDirNode::LsRunning);
it.value()->lsState = SftpDirNode::LsFinished;
if (!errorMessage.isEmpty())
emit sftpOperationFailed(tr("Error listing contents of directory \"%1\": %2")
.arg(it.value()->path, errorMessage));
d->lsOps.erase(it);
return;
}
const int jobIndex = d->externalJobs.indexOf(jobId);
QSSH_ASSERT_AND_RETURN(jobIndex != -1);
d->externalJobs.removeAt(jobIndex);
emit sftpOperationFinished(jobId, errorMessage);
}
} // namespace QSsh

View File

@@ -1,107 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "ssh_global.h"
#include <QAbstractItemModel>
namespace QSsh {
class SshConnectionParameters;
namespace Internal { class SftpFileSystemModelPrivate; }
// Very simple read-only model. Symbolic links are not followed.
class QSSH_EXPORT SftpFileSystemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit SftpFileSystemModel(QObject *parent = nullptr);
~SftpFileSystemModel();
/*
* Once this is called, an SFTP connection is established and the model is populated.
* The effect of additional calls is undefined.
*/
void setSshConnection(const SshConnectionParameters &sshParams);
void setRootDirectory(const QString &path); // Default is "/".
QString rootDirectory() const;
SftpJobId downloadFile(const QModelIndex &index, const QString &targetFilePath);
// Use this to get the full path of a file or directory.
static const int PathRole = Qt::UserRole;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
signals:
/*
* E.g. "Permission denied". Note that this can happen without direct user intervention,
* due to e.g. the view calling rowCount() on a non-readable directory. This signal should
* therefore not result in a message box or similar, since it might occur very often.
*/
void sftpOperationFailed(const QString &errorMessage);
/*
* This error is not recoverable. The model will not have any content after
* the signal has been emitted.
*/
void connectionError(const QString &errorMessage);
// Success <=> error.isEmpty().
void sftpOperationFinished(QSsh::SftpJobId, const QString &error);
private:
void handleSshConnectionEstablished();
void handleSshConnectionFailure();
void handleSftpChannelInitialized();
void handleSftpChannelError(const QString &reason);
void handleFileInfo(QSsh::SftpJobId jobId, const QList<QSsh::SftpFileInfo> &fileInfoList);
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;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
void statRootDirectory();
void shutDown();
Internal::SftpFileSystemModelPrivate * const d;
};
} // namespace QSsh;
#endif // SFTPFILESYSTEMMODEL_H

View File

@@ -1,223 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshexception_p.h"
#include "sshlogging_p.h"
#include "sshpacketparser_p.h"
namespace QSsh {
namespace Internal {
SftpIncomingPacket::SftpIncomingPacket() : m_length(0)
{
}
void SftpIncomingPacket::consumeData(QByteArray &newData)
{
qCDebug(sshLog, "%s: current data size = %d, new data size = %d", Q_FUNC_INFO,
m_data.size(), newData.size());
if (isComplete() || dataSize() + newData.size() < sizeof m_length)
return;
if (dataSize() < sizeof m_length) {
moveFirstBytes(m_data, newData, sizeof m_length - m_data.size());
m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
if (m_length < static_cast<quint32>(TypeOffset + 1)
|| m_length > MaxPacketSize) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid length field in SFTP packet.");
}
}
moveFirstBytes(m_data, newData,
qMin<quint32>(m_length - dataSize() + 4, newData.size()));
}
void SftpIncomingPacket::moveFirstBytes(QByteArray &target, QByteArray &source,
int n)
{
target.append(source.left(n));
source.remove(0, n);
}
bool SftpIncomingPacket::isComplete() const
{
return m_length == dataSize() - 4;
}
void SftpIncomingPacket::clear()
{
m_data.clear();
m_length = 0;
}
quint32 SftpIncomingPacket::extractServerVersion() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_VERSION);
try {
return SshPacketParser::asUint32(m_data, TypeOffset + 1);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_VERSION packet.");
}
}
SftpHandleResponse SftpIncomingPacket::asHandleResponse() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_HANDLE);
try {
SftpHandleResponse response;
quint32 offset = RequestIdOffset;
response.requestId = SshPacketParser::asUint32(m_data, &offset);
response.handle = SshPacketParser::asString(m_data, &offset);
return response;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_HANDLE packet");
}
}
SftpStatusResponse SftpIncomingPacket::asStatusResponse() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_STATUS);
try {
SftpStatusResponse response;
quint32 offset = RequestIdOffset;
response.requestId = SshPacketParser::asUint32(m_data, &offset);
response.status = static_cast<SftpStatusCode>(SshPacketParser::asUint32(m_data, &offset));
response.errorString = SshPacketParser::asUserString(m_data, &offset);
response.language = SshPacketParser::asString(m_data, &offset);
return response;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_STATUS packet.");
}
}
SftpNameResponse SftpIncomingPacket::asNameResponse() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_NAME);
try {
SftpNameResponse response;
quint32 offset = RequestIdOffset;
response.requestId = SshPacketParser::asUint32(m_data, &offset);
const quint32 count = SshPacketParser::asUint32(m_data, &offset);
for (quint32 i = 0; i < count; ++i)
response.files << asFile(offset);
return response;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_NAME packet.");
}
}
SftpDataResponse SftpIncomingPacket::asDataResponse() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_DATA);
try {
SftpDataResponse response;
quint32 offset = RequestIdOffset;
response.requestId = SshPacketParser::asUint32(m_data, &offset);
response.data = SshPacketParser::asString(m_data, &offset);
return response;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_DATA packet.");
}
}
SftpAttrsResponse SftpIncomingPacket::asAttrsResponse() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_FXP_ATTRS);
try {
SftpAttrsResponse response;
quint32 offset = RequestIdOffset;
response.requestId = SshPacketParser::asUint32(m_data, &offset);
response.attrs = asFileAttributes(offset);
return response;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_FXP_ATTRS packet.");
}
}
SftpFile SftpIncomingPacket::asFile(quint32 &offset) const
{
SftpFile file;
file.fileName
= QString::fromUtf8(SshPacketParser::asString(m_data, &offset));
file.longName
= QString::fromUtf8(SshPacketParser::asString(m_data, &offset));
file.attributes = asFileAttributes(offset);
return file;
}
SftpFileAttributes SftpIncomingPacket::asFileAttributes(quint32 &offset) const
{
SftpFileAttributes attributes;
const quint32 flags = SshPacketParser::asUint32(m_data, &offset);
attributes.sizePresent = flags & SSH_FILEXFER_ATTR_SIZE;
attributes.timesPresent = flags & SSH_FILEXFER_ATTR_ACMODTIME;
attributes.uidAndGidPresent = flags & SSH_FILEXFER_ATTR_UIDGID;
attributes.permissionsPresent = flags & SSH_FILEXFER_ATTR_PERMISSIONS;
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);
}
if (attributes.permissionsPresent)
attributes.permissions = SshPacketParser::asUint32(m_data, &offset);
if (attributes.timesPresent) {
attributes.atime = SshPacketParser::asUint32(m_data, &offset);
attributes.mtime = SshPacketParser::asUint32(m_data, &offset);
}
if (flags & SSH_FILEXFER_ATTR_EXTENDED) {
const quint32 count = SshPacketParser::asUint32(m_data, &offset);
for (quint32 i = 0; i < count; ++i) {
SshPacketParser::asString(m_data, &offset);
SshPacketParser::asString(m_data, &offset);
}
}
return attributes;
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,112 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTPINCOMINGPACKET_P_H
#define SFTPINCOMINGPACKET_P_H
#include "sftppacket_p.h"
namespace QSsh {
namespace Internal {
struct SftpHandleResponse {
quint32 requestId;
QByteArray handle;
};
struct SftpStatusResponse {
quint32 requestId;
SftpStatusCode status;
QString errorString;
QByteArray language;
};
struct SftpFileAttributes {
bool sizePresent;
bool timesPresent;
bool uidAndGidPresent;
bool permissionsPresent;
quint64 size;
quint32 uid;
quint32 gid;
quint32 permissions;
quint32 atime;
quint32 mtime;
};
struct SftpFile {
QString fileName;
QString longName; // Not present in later RFCs, so we don't expose this to the user.
SftpFileAttributes attributes;
};
struct SftpNameResponse {
quint32 requestId;
QList<SftpFile> files;
};
struct SftpDataResponse {
quint32 requestId;
QByteArray data;
};
struct SftpAttrsResponse {
quint32 requestId;
SftpFileAttributes attrs;
};
class SftpIncomingPacket : public AbstractSftpPacket
{
public:
SftpIncomingPacket();
void consumeData(QByteArray &data);
void clear();
bool isComplete() const;
quint32 extractServerVersion() const;
SftpHandleResponse asHandleResponse() const;
SftpStatusResponse asStatusResponse() const;
SftpNameResponse asNameResponse() const;
SftpDataResponse asDataResponse() const;
SftpAttrsResponse asAttrsResponse() const;
private:
void moveFirstBytes(QByteArray &target, QByteArray &source, int n);
SftpFileAttributes asFileAttributes(quint32 &offset) const;
SftpFile asFile(quint32 &offset) const;
quint32 m_length;
};
} // namespace Internal
} // namespace QSsh
#endif // SFTPINCOMINGPACKET_P_H

View File

@@ -1,236 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sftpoutgoingpacket_p.h"
#include <QFile>
namespace QSsh {
namespace Internal {
AbstractSftpOperation::AbstractSftpOperation(SftpJobId jobId) : jobId(jobId)
{
}
AbstractSftpOperation::~AbstractSftpOperation() { }
SftpStatFile::SftpStatFile(SftpJobId jobId, const QString &path)
: AbstractSftpOperation(jobId), path(path)
{
}
SftpOutgoingPacket &SftpStatFile::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateStat(path, jobId);
}
SftpMakeDir::SftpMakeDir(SftpJobId jobId, const QString &path,
const SftpUploadDir::Ptr &parentJob)
: AbstractSftpOperation(jobId), parentJob(parentJob), remoteDir(path)
{
}
SftpOutgoingPacket &SftpMakeDir::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateMkDir(remoteDir, jobId);
}
SftpRmDir::SftpRmDir(SftpJobId id, const QString &path)
: AbstractSftpOperation(id), remoteDir(path)
{
}
SftpOutgoingPacket &SftpRmDir::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateRmDir(remoteDir, jobId);
}
SftpRm::SftpRm(SftpJobId jobId, const QString &path)
: AbstractSftpOperation(jobId), remoteFile(path) {}
SftpOutgoingPacket &SftpRm::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateRm(remoteFile, jobId);
}
SftpRename::SftpRename(SftpJobId jobId, const QString &oldPath,
const QString &newPath)
: AbstractSftpOperation(jobId), oldPath(oldPath), newPath(newPath)
{
}
SftpOutgoingPacket &SftpRename::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateRename(oldPath, newPath, jobId);
}
SftpCreateLink::SftpCreateLink(SftpJobId jobId, const QString &filePath, const QString &target)
: AbstractSftpOperation(jobId), filePath(filePath), target(target)
{
}
SftpOutgoingPacket &SftpCreateLink::initialPacket(SftpOutgoingPacket &packet)
{
return packet.generateCreateLink(filePath, target, jobId);
}
AbstractSftpOperationWithHandle::AbstractSftpOperationWithHandle(SftpJobId jobId,
const QString &remotePath)
: AbstractSftpOperation(jobId),
remotePath(remotePath), state(Inactive), hasError(false)
{
}
AbstractSftpOperationWithHandle::~AbstractSftpOperationWithHandle() { }
SftpListDir::SftpListDir(SftpJobId jobId, const QString &path,
const QSharedPointer<SftpDownloadDir> &parentJob)
: AbstractSftpOperationWithHandle(jobId, path), parentJob(parentJob)
{
}
SftpOutgoingPacket &SftpListDir::initialPacket(SftpOutgoingPacket &packet)
{
state = OpenRequested;
return packet.generateOpenDir(remotePath, jobId);
}
SftpCreateFile::SftpCreateFile(SftpJobId jobId, const QString &path,
SftpOverwriteMode mode)
: AbstractSftpOperationWithHandle(jobId, path), mode(mode)
{
}
SftpOutgoingPacket & SftpCreateFile::initialPacket(SftpOutgoingPacket &packet)
{
state = OpenRequested;
return packet.generateOpenFileForWriting(remotePath, mode,
SftpOutgoingPacket::DefaultPermissions, jobId);
}
const int AbstractSftpTransfer::MaxInFlightCount = 10; // Experimentally found to be enough.
AbstractSftpTransfer::AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QIODevice> &localFile)
: AbstractSftpOperationWithHandle(jobId, remotePath),
localFile(localFile), fileSize(0), offset(0), inFlightCount(0),
statRequested(false)
{
}
AbstractSftpTransfer::~AbstractSftpTransfer() {}
void AbstractSftpTransfer::calculateInFlightCount(quint32 chunkSize)
{
if (fileSize == 0) {
inFlightCount = 1;
} else {
inFlightCount = fileSize / chunkSize;
if (fileSize % chunkSize)
++inFlightCount;
if (inFlightCount > MaxInFlightCount)
inFlightCount = MaxInFlightCount;
}
}
SftpDownload::SftpDownload(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const QSharedPointer<QSsh::Internal::SftpDownloadDir> &parentJob)
: AbstractSftpTransfer(jobId, remotePath, localFile), eofId(SftpInvalidJob), mode(mode),
parentJob(parentJob)
{
}
SftpOutgoingPacket &SftpDownload::initialPacket(SftpOutgoingPacket &packet)
{
state = OpenRequested;
return packet.generateOpenFileForReading(remotePath, jobId);
}
SftpUploadFile::SftpUploadFile(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const SftpUploadDir::Ptr &parentJob)
: AbstractSftpTransfer(jobId, remotePath, localFile),
parentJob(parentJob), mode(mode)
{
fileSize = localFile->size();
}
SftpOutgoingPacket &SftpUploadFile::initialPacket(SftpOutgoingPacket &packet)
{
state = OpenRequested;
quint32 permissions = 0;
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;
// read owner
permissions |= 1<< 8;
}
return packet.generateOpenFileForWriting(remotePath, mode, permissions, jobId);
}
SftpUploadDir::~SftpUploadDir() {}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,290 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTPOPERATION_P_H
#define SFTPOPERATION_P_H
#include "sftpdefs.h"
#include <QByteArray>
#include <QList>
#include <QMap>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
class QIODevice;
QT_END_NAMESPACE
namespace QSsh {
namespace Internal {
class SftpOutgoingPacket;
struct AbstractSftpOperation
{
typedef QSharedPointer<AbstractSftpOperation> Ptr;
enum Type {
StatFile, ListDir, MakeDir, RmDir, Rm, Rename, CreateLink, CreateFile, Download, UploadFile
};
AbstractSftpOperation(SftpJobId jobId);
virtual ~AbstractSftpOperation();
virtual Type type() const = 0;
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet) = 0;
const SftpJobId jobId;
private:
AbstractSftpOperation(const AbstractSftpOperation &);
AbstractSftpOperation &operator=(const AbstractSftpOperation &);
};
struct SftpUploadDir;
struct SftpDownloadDir;
struct SftpStatFile : public AbstractSftpOperation
{
typedef QSharedPointer<SftpStatFile> Ptr;
SftpStatFile(SftpJobId jobId, const QString &path);
virtual Type type() const { return StatFile; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QString path;
};
struct SftpMakeDir : public AbstractSftpOperation
{
typedef QSharedPointer<SftpMakeDir> Ptr;
SftpMakeDir(SftpJobId jobId, const QString &path,
const QSharedPointer<SftpUploadDir> &parentJob = QSharedPointer<SftpUploadDir>());
virtual Type type() const { return MakeDir; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QSharedPointer<SftpUploadDir> parentJob;
const QString remoteDir;
};
struct SftpRmDir : public AbstractSftpOperation
{
typedef QSharedPointer<SftpRmDir> Ptr;
SftpRmDir(SftpJobId id, const QString &path);
virtual Type type() const { return RmDir; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QString remoteDir;
};
struct SftpRm : public AbstractSftpOperation
{
typedef QSharedPointer<SftpRm> Ptr;
SftpRm(SftpJobId jobId, const QString &path);
virtual Type type() const { return Rm; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QString remoteFile;
};
struct SftpRename : public AbstractSftpOperation
{
typedef QSharedPointer<SftpRename> Ptr;
SftpRename(SftpJobId jobId, const QString &oldPath, const QString &newPath);
virtual Type type() const { return Rename; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QString oldPath;
const QString newPath;
};
struct SftpCreateLink : public AbstractSftpOperation
{
typedef QSharedPointer<SftpCreateLink> Ptr;
SftpCreateLink(SftpJobId jobId, const QString &filePath, const QString &target);
virtual Type type() const { return CreateLink; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QString filePath;
const QString target;
};
struct AbstractSftpOperationWithHandle : public AbstractSftpOperation
{
typedef QSharedPointer<AbstractSftpOperationWithHandle> Ptr;
enum State { Inactive, OpenRequested, Open, CloseRequested };
AbstractSftpOperationWithHandle(SftpJobId jobId, const QString &remotePath);
~AbstractSftpOperationWithHandle();
const QString remotePath;
QByteArray remoteHandle;
State state;
bool hasError;
};
struct SftpListDir : public AbstractSftpOperationWithHandle
{
typedef QSharedPointer<SftpListDir> Ptr;
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;
};
struct SftpCreateFile : public AbstractSftpOperationWithHandle
{
typedef QSharedPointer<SftpCreateFile> Ptr;
SftpCreateFile(SftpJobId jobId, const QString &path, SftpOverwriteMode mode);
virtual Type type() const { return CreateFile; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const SftpOverwriteMode mode;
};
struct AbstractSftpTransfer : public AbstractSftpOperationWithHandle
{
typedef QSharedPointer<AbstractSftpTransfer> Ptr;
AbstractSftpTransfer(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QIODevice> &localFile);
~AbstractSftpTransfer();
void calculateInFlightCount(quint32 chunkSize);
static const int MaxInFlightCount;
const QSharedPointer<QIODevice> localFile;
quint64 fileSize;
quint64 offset;
int inFlightCount;
bool statRequested;
};
struct SftpDownload : public AbstractSftpTransfer
{
typedef QSharedPointer<SftpDownload> Ptr;
SftpDownload(SftpJobId jobId, const QString &remotePath,
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
{
typedef QSharedPointer<SftpUploadFile> Ptr;
SftpUploadFile(SftpJobId jobId, const QString &remotePath,
const QSharedPointer<QIODevice> &localFile, SftpOverwriteMode mode,
const QSharedPointer<SftpUploadDir> &parentJob = QSharedPointer<SftpUploadDir>());
virtual Type type() const { return UploadFile; }
virtual SftpOutgoingPacket &initialPacket(SftpOutgoingPacket &packet);
const QSharedPointer<SftpUploadDir> parentJob;
SftpOverwriteMode mode;
};
// Composite operation.
struct SftpUploadDir
{
typedef QSharedPointer<SftpUploadDir> Ptr;
struct Dir {
Dir(const QString &l, const QString &r) : localDir(l), remoteDir(r) {}
QString localDir;
QString remoteDir;
};
SftpUploadDir(SftpJobId jobId) : jobId(jobId), hasError(false) {}
~SftpUploadDir();
void setError()
{
hasError = true;
uploadsInProgress.clear();
mkdirsInProgress.clear();
}
const SftpJobId jobId;
bool hasError;
QList<SftpUploadFile::Ptr> uploadsInProgress;
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,225 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshlogging_p.h"
#include "sshpacket_p.h"
#include <QtEndian>
#include <limits>
namespace QSsh {
namespace Internal {
namespace {
const quint32 DefaultAttributes = 0;
const quint32 SSH_FXF_READ = 0x00000001;
const quint32 SSH_FXF_WRITE = 0x00000002;
const quint32 SSH_FXF_APPEND = 0x00000004;
const quint32 SSH_FXF_CREAT = 0x00000008;
const quint32 SSH_FXF_TRUNC = 0x00000010;
const quint32 SSH_FXF_EXCL = 0x00000020;
}
SftpOutgoingPacket::SftpOutgoingPacket()
{
}
SftpOutgoingPacket &SftpOutgoingPacket::generateInit(quint32 version)
{
return init(SSH_FXP_INIT, 0).appendInt(version).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateStat(const QString &path, quint32 requestId)
{
return init(SSH_FXP_LSTAT, requestId).appendString(path).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateOpenDir(const QString &path,
quint32 requestId)
{
return init(SSH_FXP_OPENDIR, requestId).appendString(path).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateReadDir(const QByteArray &handle,
quint32 requestId)
{
return init(SSH_FXP_READDIR, requestId).appendString(handle).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateCloseHandle(const QByteArray &handle,
quint32 requestId)
{
return init(SSH_FXP_CLOSE, requestId).appendString(handle).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateMkDir(const QString &path,
quint32 requestId)
{
return init(SSH_FXP_MKDIR, requestId).appendString(path)
.appendInt(DefaultAttributes).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateRmDir(const QString &path,
quint32 requestId)
{
return init(SSH_FXP_RMDIR, requestId).appendString(path).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateRm(const QString &path,
quint32 requestId)
{
return init(SSH_FXP_REMOVE, requestId).appendString(path).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateRename(const QString &oldPath,
const QString &newPath, quint32 requestId)
{
return init(SSH_FXP_RENAME, requestId).appendString(oldPath)
.appendString(newPath).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFileForWriting(const QString &path,
SftpOverwriteMode mode, quint32 permissions, quint32 requestId)
{
QList<quint32> attributes;
if (permissions != DefaultPermissions)
attributes << SSH_FILEXFER_ATTR_PERMISSIONS << permissions;
else
attributes << DefaultAttributes;
return generateOpenFile(path, Write, mode, attributes, requestId);
}
SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFileForReading(const QString &path,
quint32 requestId)
{
// Note: Overwrite mode is irrelevant and will be ignored.
return generateOpenFile(path, Read, SftpSkipExisting, QList<quint32>() << DefaultAttributes,
requestId);
}
SftpOutgoingPacket &SftpOutgoingPacket::generateReadFile(const QByteArray &handle,
quint64 offset, quint32 length, quint32 requestId)
{
return init(SSH_FXP_READ, requestId).appendString(handle).appendInt64(offset)
.appendInt(length).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateFstat(const QByteArray &handle,
quint32 requestId)
{
return init(SSH_FXP_FSTAT, requestId).appendString(handle).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateWriteFile(const QByteArray &handle,
quint64 offset, const QByteArray &data, quint32 requestId)
{
return init(SSH_FXP_WRITE, requestId).appendString(handle)
.appendInt64(offset).appendString(data).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateCreateLink(const QString &filePath,
const QString &target, quint32 requestId)
{
return init(SSH_FXP_SYMLINK, requestId).appendString(filePath).appendString(target).finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::generateOpenFile(const QString &path,
OpenType openType, SftpOverwriteMode mode, const QList<quint32> &attributes, quint32 requestId)
{
quint32 pFlags = 0;
switch (openType) {
case Read:
pFlags = SSH_FXF_READ;
break;
case Write:
pFlags = SSH_FXF_WRITE | SSH_FXF_CREAT;
switch (mode) {
case SftpOverwriteExisting: pFlags |= SSH_FXF_TRUNC; break;
case SftpAppendToExisting: pFlags |= SSH_FXF_APPEND; break;
case SftpSkipExisting: pFlags |= SSH_FXF_EXCL; break;
}
break;
}
init(SSH_FXP_OPEN, requestId).appendString(path).appendInt(pFlags);
foreach (const quint32 attribute, attributes)
appendInt(attribute);
return finalize();
}
SftpOutgoingPacket &SftpOutgoingPacket::init(SftpPacketType type,
quint32 requestId)
{
m_data.resize(TypeOffset + 1);
m_data[TypeOffset] = type;
if (type != SSH_FXP_INIT) {
appendInt(requestId);
qCDebug(sshLog, "Generating SFTP packet of type %d with request id %u", type, requestId);
}
return *this;
}
SftpOutgoingPacket &SftpOutgoingPacket::appendInt(quint32 val)
{
m_data.append(AbstractSshPacket::encodeInt(val));
return *this;
}
SftpOutgoingPacket &SftpOutgoingPacket::appendInt64(quint64 value)
{
m_data.append(AbstractSshPacket::encodeInt(value));
return *this;
}
SftpOutgoingPacket &SftpOutgoingPacket::appendString(const QString &string)
{
m_data.append(AbstractSshPacket::encodeString(string.toUtf8()));
return *this;
}
SftpOutgoingPacket &SftpOutgoingPacket::appendString(const QByteArray &string)
{
m_data += AbstractSshPacket::encodeString(string);
return *this;
}
SftpOutgoingPacket &SftpOutgoingPacket::finalize()
{
AbstractSshPacket::setLengthField(m_data);
return *this;
}
const quint32 SftpOutgoingPacket::DefaultPermissions = std::numeric_limits<quint32>::max();
} // namespace Internal
} // namespace QSsh

View File

@@ -1,92 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTPOUTGOINGPACKET_P_H
#define SFTPOUTGOINGPACKET_P_H
#include "sftppacket_p.h"
#include "sftpdefs.h"
namespace QSsh {
namespace Internal {
class SftpOutgoingPacket : public AbstractSftpPacket
{
public:
SftpOutgoingPacket();
SftpOutgoingPacket &generateInit(quint32 version);
SftpOutgoingPacket &generateStat(const QString &path, quint32 requestId);
SftpOutgoingPacket &generateOpenDir(const QString &path, quint32 requestId);
SftpOutgoingPacket &generateReadDir(const QByteArray &handle,
quint32 requestId);
SftpOutgoingPacket &generateCloseHandle(const QByteArray &handle,
quint32 requestId);
SftpOutgoingPacket &generateMkDir(const QString &path, quint32 requestId);
SftpOutgoingPacket &generateRmDir(const QString &path, quint32 requestId);
SftpOutgoingPacket &generateRm(const QString &path, quint32 requestId);
SftpOutgoingPacket &generateRename(const QString &oldPath,
const QString &newPath, quint32 requestId);
SftpOutgoingPacket &generateOpenFileForWriting(const QString &path,
SftpOverwriteMode mode, quint32 permissions, quint32 requestId);
SftpOutgoingPacket &generateOpenFileForReading(const QString &path,
quint32 requestId);
SftpOutgoingPacket &generateReadFile(const QByteArray &handle,
quint64 offset, quint32 length, quint32 requestId);
SftpOutgoingPacket &generateFstat(const QByteArray &handle,
quint32 requestId);
SftpOutgoingPacket &generateWriteFile(const QByteArray &handle,
quint64 offset, const QByteArray &data, quint32 requestId);
// Note: OpenSSH's SFTP server has a bug that reverses the filePath and target
// arguments, so this operation is not portable.
SftpOutgoingPacket &generateCreateLink(const QString &filePath, const QString &target,
quint32 requestId);
static const quint32 DefaultPermissions;
private:
static QByteArray encodeString(const QString &string);
enum OpenType { Read, Write };
SftpOutgoingPacket &generateOpenFile(const QString &path, OpenType openType,
SftpOverwriteMode mode, const QList<quint32> &attributes, quint32 requestId);
SftpOutgoingPacket &init(SftpPacketType type, quint32 requestId);
SftpOutgoingPacket &appendInt(quint32 value);
SftpOutgoingPacket &appendInt64(quint64 value);
SftpOutgoingPacket &appendString(const QString &string);
SftpOutgoingPacket &appendString(const QByteArray &string);
SftpOutgoingPacket &finalize();
};
} // namespace Internal
} // namespace QSsh
#endif // SFTPOUTGOINGPACKET_P_H

View File

@@ -1,57 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshpacketparser_p.h"
namespace QSsh {
namespace Internal {
// 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;
AbstractSftpPacket::AbstractSftpPacket()
{
}
quint32 AbstractSftpPacket::requestId() const
{
return SshPacketParser::asUint32(m_data, RequestIdOffset);
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,117 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SFTPPACKET_P_H
#define SFTPPACKET_P_H
#include <QByteArray>
#include <QList>
#include <QString>
namespace QSsh {
namespace Internal {
enum SftpPacketType {
SSH_FXP_INIT = 1,
SSH_FXP_VERSION = 2,
SSH_FXP_OPEN = 3,
SSH_FXP_CLOSE = 4,
SSH_FXP_READ = 5,
SSH_FXP_WRITE = 6,
SSH_FXP_LSTAT = 7,
SSH_FXP_FSTAT = 8,
SSH_FXP_SETSTAT = 9,
SSH_FXP_FSETSTAT = 10,
SSH_FXP_OPENDIR = 11,
SSH_FXP_READDIR = 12,
SSH_FXP_REMOVE = 13,
SSH_FXP_MKDIR = 14,
SSH_FXP_RMDIR = 15,
SSH_FXP_REALPATH = 16,
SSH_FXP_STAT = 17,
SSH_FXP_RENAME = 18,
SSH_FXP_READLINK = 19,
SSH_FXP_SYMLINK = 20, // Removed from later protocol versions. Try not to use.
SSH_FXP_STATUS = 101,
SSH_FXP_HANDLE = 102,
SSH_FXP_DATA = 103,
SSH_FXP_NAME = 104,
SSH_FXP_ATTRS = 105,
SSH_FXP_EXTENDED = 200,
SSH_FXP_EXTENDED_REPLY = 201
};
enum SftpStatusCode {
SSH_FX_OK = 0,
SSH_FX_EOF = 1,
SSH_FX_NO_SUCH_FILE = 2,
SSH_FX_PERMISSION_DENIED = 3,
SSH_FX_FAILURE = 4,
SSH_FX_BAD_MESSAGE = 5,
SSH_FX_NO_CONNECTION = 6,
SSH_FX_CONNECTION_LOST = 7,
SSH_FX_OP_UNSUPPORTED = 8
};
enum SftpAttributeType {
SSH_FILEXFER_ATTR_SIZE = 0x00000001,
SSH_FILEXFER_ATTR_UIDGID = 0x00000002,
SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004,
SSH_FILEXFER_ATTR_ACMODTIME = 0x00000008,
SSH_FILEXFER_ATTR_EXTENDED = 0x80000000
};
class AbstractSftpPacket
{
public:
AbstractSftpPacket();
quint32 requestId() const;
const QByteArray &rawData() const { return m_data; }
SftpPacketType type() const { return static_cast<SftpPacketType>(m_data.at(TypeOffset)); }
static const quint32 MaxDataSize; // "Pure" data size per read/writepacket.
static const quint32 MaxPacketSize;
protected:
quint32 dataSize() const { return static_cast<quint32>(m_data.size()); }
static const int TypeOffset;
static const int RequestIdOffset;
static const int PayloadOffset;
QByteArray m_data;
};
} // namespace Internal
} // namespace QSsh
#endif // SFTPPACKET_P_H

View File

@@ -1,66 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSH_GLOBAL_H
#define SSH_GLOBAL_H
#include <QtGlobal>
#include <QObject>
#ifdef Q_OS_IOS
class QProcess {
public:
QProcess(QObject *){}
enum ProcessChannel {
StandardOutput,
StandardError
};
};
#endif
#ifdef _MSC_VER
// For static cmake building removing dll export/import
# define QSSH_EXPORT
#else
#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

@@ -1,313 +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 "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

@@ -1,125 +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.
**
****************************************************************************/
#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,172 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 BYTEARRAYCONVERSIONS_P_H
#define BYTEARRAYCONVERSIONS_P_H
#include "sshcapabilities_p.h"
#include "sshexception_p.h"
#include <botan_all.h>
namespace QSsh {
namespace Internal {
inline const Botan::byte *convertByteArray(const QByteArray &a)
{
return reinterpret_cast<const Botan::byte *>(a.constData());
}
inline Botan::byte *convertByteArray(QByteArray &a)
{
return reinterpret_cast<Botan::byte *>(a.data());
}
inline QByteArray convertByteArray(const Botan::secure_vector<Botan::byte> &v)
{
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)
{
if (rfcAlgoName == SshCapabilities::DiffieHellmanGroup1Sha1)
return "modp/ietf/1024";
if (rfcAlgoName == SshCapabilities::DiffieHellmanGroup14Sha1)
return "modp/ietf/2048";
if (rfcAlgoName == SshCapabilities::EcdhNistp256)
return "secp256r1";
if (rfcAlgoName == SshCapabilities::EcdhNistp384)
return "secp384r1";
if (rfcAlgoName == SshCapabilities::EcdhNistp521)
return "secp521r1";
throw SshClientException(SshInternalError, SSH_TR("Unexpected key exchange algorithm \"%1\"")
.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";
}
if (rfcAlgoName == SshCapabilities::CryptAlgo3DesCbc
|| rfcAlgoName == SshCapabilities::CryptAlgo3DesCtr) {
return "TripleDES";
}
if (rfcAlgoName == SshCapabilities::CryptAlgoAes192Ctr) {
return "AES-192";
}
if (rfcAlgoName == SshCapabilities::CryptAlgoAes256Ctr) {
return "AES-256";
}
throw SshClientException(SshInternalError, SSH_TR("Unexpected cipher \"%1\"")
.arg(QString::fromLatin1(rfcAlgoName)));
}
inline const char *botanEmsaAlgoName(const QByteArray &rfcAlgoName)
{
if (rfcAlgoName == SshCapabilities::PubKeyDss)
return "EMSA1(SHA-1)";
if (rfcAlgoName == SshCapabilities::PubKeyRsa)
return "EMSA3(SHA-1)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa256)
return "EMSA1(SHA-256)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa384)
return "EMSA1_BSI(SHA-384)";
if (rfcAlgoName == SshCapabilities::PubKeyEcdsa521)
return "EMSA1_BSI(SHA-512)";
throw SshClientException(SshInternalError, SSH_TR("Unexpected host key algorithm \"%1\"")
.arg(QString::fromLatin1(rfcAlgoName)));
}
inline const char *botanHMacAlgoName(const QByteArray &rfcAlgoName)
{
if (rfcAlgoName == SshCapabilities::HMacSha1)
return "SHA-1";
if (rfcAlgoName == SshCapabilities::HMacSha256)
return "SHA-256";
if (rfcAlgoName == SshCapabilities::HMacSha384)
return "SHA-384";
if (rfcAlgoName == SshCapabilities::HMacSha512)
return "SHA-512";
throw SshClientException(SshInternalError, SSH_TR("Unexpected hashing algorithm \"%1\"")
.arg(QString::fromLatin1(rfcAlgoName)));
}
inline quint32 botanHMacKeyLen(const QByteArray &rfcAlgoName)
{
if (rfcAlgoName == SshCapabilities::HMacSha1)
return 20;
if (rfcAlgoName == SshCapabilities::HMacSha256)
return 32;
if (rfcAlgoName == SshCapabilities::HMacSha384)
return 48;
if (rfcAlgoName == SshCapabilities::HMacSha512)
return 64;
throw SshClientException(SshInternalError, SSH_TR("Unexpected hashing algorithm \"%1\"")
.arg(QString::fromLatin1(rfcAlgoName)));
}
} // namespace Internal
} // namespace QSsh
#endif // BYTEARRAYCONVERSIONS_P_H

View File

@@ -1,177 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshexception_p.h"
#include <QCoreApplication>
#include <QString>
namespace QSsh {
namespace Internal {
namespace {
QByteArray listAsByteArray(const QList<QByteArray> &list)
{
QByteArray array;
foreach(const QByteArray &elem, list)
array += elem + ',';
if (!array.isEmpty())
array.remove(array.count() - 1, 1);
return array;
}
} // anonymous namspace
const QByteArray SshCapabilities::DiffieHellmanGroup1Sha1("diffie-hellman-group1-sha1");
const QByteArray SshCapabilities::DiffieHellmanGroup14Sha1("diffie-hellman-group14-sha1");
const QByteArray SshCapabilities::EcdhKexNamePrefix("ecdh-sha2-nistp");
const QByteArray SshCapabilities::EcdhNistp256 = EcdhKexNamePrefix + "256";
const QByteArray SshCapabilities::EcdhNistp384 = EcdhKexNamePrefix + "384";
const QByteArray SshCapabilities::EcdhNistp521 = EcdhKexNamePrefix + "521";
const QList<QByteArray> SshCapabilities::KeyExchangeMethods = QList<QByteArray>()
<< SshCapabilities::EcdhNistp256
<< SshCapabilities::EcdhNistp384
<< SshCapabilities::EcdhNistp521
<< SshCapabilities::DiffieHellmanGroup1Sha1
<< SshCapabilities::DiffieHellmanGroup14Sha1;
const QByteArray SshCapabilities::PubKeyDss("ssh-dss");
const QByteArray SshCapabilities::PubKeyRsa("ssh-rsa");
const QByteArray SshCapabilities::PubKeyEcdsaPrefix("ecdsa-sha2-nistp");
const QByteArray SshCapabilities::PubKeyEcdsa256 = SshCapabilities::PubKeyEcdsaPrefix + "256";
const QByteArray SshCapabilities::PubKeyEcdsa384 = SshCapabilities::PubKeyEcdsaPrefix + "384";
const QByteArray SshCapabilities::PubKeyEcdsa521 = SshCapabilities::PubKeyEcdsaPrefix + "521";
const QList<QByteArray> SshCapabilities::PublicKeyAlgorithms = QList<QByteArray>()
<< SshCapabilities::PubKeyEcdsa256
<< SshCapabilities::PubKeyEcdsa384
<< SshCapabilities::PubKeyEcdsa521
<< SshCapabilities::PubKeyRsa
<< SshCapabilities::PubKeyDss;
const QByteArray SshCapabilities::CryptAlgo3DesCbc("3des-cbc");
const QByteArray SshCapabilities::CryptAlgo3DesCtr("3des-ctr");
const QByteArray SshCapabilities::CryptAlgoAes128Cbc("aes128-cbc");
const QByteArray SshCapabilities::CryptAlgoAes128Ctr("aes128-ctr");
const QByteArray SshCapabilities::CryptAlgoAes192Ctr("aes192-ctr");
const QByteArray SshCapabilities::CryptAlgoAes256Ctr("aes256-ctr");
const QList<QByteArray> SshCapabilities::EncryptionAlgorithms
= QList<QByteArray>() << SshCapabilities::CryptAlgoAes256Ctr
<< SshCapabilities::CryptAlgoAes192Ctr
<< SshCapabilities::CryptAlgoAes128Ctr
<< SshCapabilities::CryptAlgo3DesCtr
<< SshCapabilities::CryptAlgoAes128Cbc
<< SshCapabilities::CryptAlgo3DesCbc;
const QByteArray SshCapabilities::HMacSha1("hmac-sha1");
const QByteArray SshCapabilities::HMacSha196("hmac-sha1-96");
const QByteArray SshCapabilities::HMacSha256("hmac-sha2-256");
const QByteArray SshCapabilities::HMacSha384("hmac-sha2-384");
const QByteArray SshCapabilities::HMacSha512("hmac-sha2-512");
const QList<QByteArray> SshCapabilities::MacAlgorithms
= QList<QByteArray>() /* << SshCapabilities::HMacSha196 */
<< SshCapabilities::HMacSha256
<< SshCapabilities::HMacSha384
<< SshCapabilities::HMacSha512
<< SshCapabilities::HMacSha1;
const QList<QByteArray> SshCapabilities::CompressionAlgorithms
= QList<QByteArray>() << "none";
const QByteArray SshCapabilities::SshConnectionService("ssh-connection");
QList<QByteArray> SshCapabilities::commonCapabilities(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities, const QByteArray &group)
{
QList<QByteArray> capabilities;
foreach (const QByteArray &myCapability, myCapabilities) {
if (serverCapabilities.contains(myCapability))
capabilities << myCapability;
}
if (!capabilities.isEmpty())
return capabilities;
throw SshServerException(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Server and client capabilities do not match.",
QCoreApplication::translate("SshConnection",
"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 QByteArray &group)
{
return commonCapabilities(myCapabilities, serverCapabilities, group).first();
}
int SshCapabilities::ecdsaIntegerWidthInBytes(const QByteArray &ecdsaAlgo)
{
if (ecdsaAlgo == PubKeyEcdsa256)
return 32;
if (ecdsaAlgo == PubKeyEcdsa384)
return 48;
if (ecdsaAlgo == PubKeyEcdsa521)
return 66;
throw SshClientException(SshInternalError, SSH_TR("Unexpected ecdsa algorithm \"%1\"")
.arg(QString::fromLatin1(ecdsaAlgo)));
}
QByteArray SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(int keyWidthInBytes)
{
if (keyWidthInBytes <= 32)
return PubKeyEcdsa256;
if (keyWidthInBytes <= 48)
return PubKeyEcdsa384;
if (keyWidthInBytes <= 66)
return PubKeyEcdsa521;
throw SshClientException(SshInternalError, SSH_TR("Unexpected ecdsa key size (%1 bytes)")
.arg(keyWidthInBytes));
}
const char *SshCapabilities::oid(const QByteArray &ecdsaAlgo)
{
if (ecdsaAlgo == PubKeyEcdsa256)
return "secp256r1";
if (ecdsaAlgo == PubKeyEcdsa384)
return "secp384r1";
if (ecdsaAlgo == PubKeyEcdsa521)
return "secp521r1";
throw SshClientException(SshInternalError, SSH_TR("Unexpected ecdsa algorithm \"%1\"")
.arg(QString::fromLatin1(ecdsaAlgo)));
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,91 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 CAPABILITIES_P_H
#define CAPABILITIES_P_H
#include <QByteArray>
#include <QList>
namespace QSsh {
namespace Internal {
class SshCapabilities
{
public:
static const QByteArray DiffieHellmanGroup1Sha1;
static const QByteArray DiffieHellmanGroup14Sha1;
static const QByteArray EcdhKexNamePrefix;
static const QByteArray EcdhNistp256;
static const QByteArray EcdhNistp384;
static const QByteArray EcdhNistp521; // sic
static const QList<QByteArray> KeyExchangeMethods;
static const QByteArray PubKeyDss;
static const QByteArray PubKeyRsa;
static const QByteArray PubKeyEcdsaPrefix;
static const QByteArray PubKeyEcdsa256;
static const QByteArray PubKeyEcdsa384;
static const QByteArray PubKeyEcdsa521;
static const QList<QByteArray> PublicKeyAlgorithms;
static const QByteArray CryptAlgo3DesCbc;
static const QByteArray CryptAlgo3DesCtr;
static const QByteArray CryptAlgoAes128Cbc;
static const QByteArray CryptAlgoAes128Ctr;
static const QByteArray CryptAlgoAes192Ctr;
static const QByteArray CryptAlgoAes256Ctr;
static const QList<QByteArray> EncryptionAlgorithms;
static const QByteArray HMacSha1;
static const QByteArray HMacSha196;
static const QByteArray HMacSha256;
static const QByteArray HMacSha384;
static const QByteArray HMacSha512;
static const QList<QByteArray> MacAlgorithms;
static const QList<QByteArray> CompressionAlgorithms;
static const QByteArray SshConnectionService;
static QList<QByteArray> commonCapabilities(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities, const QByteArray &group);
static QByteArray findBestMatch(const QList<QByteArray> &myCapabilities,
const QList<QByteArray> &serverCapabilities, const QByteArray &group);
static int ecdsaIntegerWidthInBytes(const QByteArray &ecdsaAlgo);
static QByteArray ecdsaPubKeyAlgoForKeyWidth(int keyWidthInBytes);
static const char *oid(const QByteArray &ecdsaAlgo);
};
} // namespace Internal
} // namespace QSsh
#endif // CAPABILITIES_P_H

View File

@@ -1,277 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 "sshsendfacility_p.h"
#include "sshlogging_p.h"
#include <botan_all.h>
#include <QTimer>
namespace QSsh {
namespace Internal {
const quint32 NoChannel = 0xffffffffu;
AbstractSshChannel::AbstractSshChannel(quint32 channelId,
SshSendFacility &sendFacility)
: m_sendFacility(sendFacility),
m_localChannel(channelId), m_remoteChannel(NoChannel),
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);
}
AbstractSshChannel::~AbstractSshChannel()
{
}
void AbstractSshChannel::setChannelState(ChannelState state)
{
m_state = state;
if (state == Closed)
closeHook();
}
void AbstractSshChannel::requestSessionStart()
{
// Note: We are just being paranoid here about the Botan exceptions,
// which are extremely unlikely to happen, because if there was a problem
// with our cryptography stuff, it would have hit us before, on
// establishing the connection.
try {
m_sendFacility.sendSessionPacket(m_localChannel, initialWindowSize(), maxPacketSize());
setChannelState(SessionRequested);
m_timeoutTimer.start(ReplyTimeout);
} catch (const std::exception &e) {
qCWarning(sshLog, "Botan error: %s", e.what());
closeChannel();
}
}
void AbstractSshChannel::sendData(const QByteArray &data)
{
try {
m_sendBuffer += data;
flushSendBuffer();
} catch (const std::exception &e) {
qCWarning(sshLog, "Botan error: %s", e.what());
closeChannel();
}
}
quint32 AbstractSshChannel::initialWindowSize()
{
return maxPacketSize();
}
quint32 AbstractSshChannel::maxPacketSize()
{
return 16 * 1024 * 1024;
}
void AbstractSshChannel::handleWindowAdjust(quint64 bytesToAdd)
{
checkChannelActive();
const quint64 newValue = m_remoteWindowSize + bytesToAdd;
if (newValue > 0xffffffffu) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Illegal window size requested.");
}
m_remoteWindowSize = newValue;
flushSendBuffer();
}
void AbstractSshChannel::flushSendBuffer()
{
while (true) {
const quint32 bytesToSend = qMin(m_remoteMaxPacketSize,
qMin<quint32>(m_remoteWindowSize, m_sendBuffer.size()));
if (bytesToSend == 0)
break;
const QByteArray &data = m_sendBuffer.left(bytesToSend);
m_sendFacility.sendChannelDataPacket(m_remoteChannel, data);
m_sendBuffer.remove(0, bytesToSend);
m_remoteWindowSize -= bytesToSend;
}
}
void AbstractSshChannel::handleOpenSuccess(quint32 remoteChannelId,
quint32 remoteWindowSize, quint32 remoteMaxPacketSize)
{
const ChannelState oldState = m_state;
switch (oldState) {
case CloseRequested: // closeChannel() was called while we were in SessionRequested state
case SessionRequested:
break; // Ok, continue.
default:
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet.");
}
m_timeoutTimer.stop();
qCDebug(sshLog, "Channel opened. remote channel id: %u, remote window size: %u, "
"remote max packet size: %u",
remoteChannelId, remoteWindowSize, remoteMaxPacketSize);
m_remoteChannel = remoteChannelId;
m_remoteWindowSize = remoteWindowSize;
m_remoteMaxPacketSize = remoteMaxPacketSize;
setChannelState(SessionEstablished);
if (oldState == CloseRequested)
closeChannel();
else
handleOpenSuccessInternal();
}
void AbstractSshChannel::handleOpenFailure(const QString &reason)
{
switch (m_state) {
case SessionRequested:
break; // Ok, continue.
case CloseRequested:
return; // Late server reply; we requested a channel close in the meantime.
default:
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
}
m_timeoutTimer.stop();
qCDebug(sshLog, "Channel open request failed for channel %u", m_localChannel);
handleOpenFailureInternal(reason);
}
void AbstractSshChannel::handleChannelEof()
{
if (m_state == Inactive || m_state == Closed) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_EOF message.");
}
m_localWindowSize = 0;
emit eof();
}
void AbstractSshChannel::handleChannelClose()
{
qCDebug(sshLog, "Receiving CLOSE for channel %u", m_localChannel);
if (channelState() == Inactive || channelState() == Closed) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected SSH_MSG_CHANNEL_CLOSE message.");
}
closeChannel();
setChannelState(Closed);
}
void AbstractSshChannel::handleChannelData(const QByteArray &data)
{
const int bytesToDeliver = handleChannelOrExtendedChannelData(data);
handleChannelDataInternal(bytesToDeliver == data.size()
? data : data.left(bytesToDeliver));
}
void AbstractSshChannel::handleChannelExtendedData(quint32 type, const QByteArray &data)
{
const int bytesToDeliver = handleChannelOrExtendedChannelData(data);
handleChannelExtendedDataInternal(type, bytesToDeliver == data.size()
? data : data.left(bytesToDeliver));
}
void AbstractSshChannel::handleChannelRequest(const SshIncomingPacket &packet)
{
checkChannelActive();
const QByteArray &requestType = packet.extractChannelRequestType();
if (requestType == SshIncomingPacket::ExitStatusType)
handleExitStatus(packet.extractChannelExitStatus());
else if (requestType == SshIncomingPacket::ExitSignalType)
handleExitSignal(packet.extractChannelExitSignal());
else if (requestType != "eow@openssh.com") // Suppress warning for this one, as it's sent all the time.
qCWarning(sshLog, "Ignoring unknown request type '%s'", requestType.data());
}
int AbstractSshChannel::handleChannelOrExtendedChannelData(const QByteArray &data)
{
checkChannelActive();
const int bytesToDeliver = qMin<quint32>(data.size(), maxDataSize());
if (bytesToDeliver != data.size())
qCWarning(sshLog, "Misbehaving server does not respect local window, clipping.");
m_localWindowSize -= bytesToDeliver;
if (m_localWindowSize < maxPacketSize()) {
m_localWindowSize += maxPacketSize();
m_sendFacility.sendWindowAdjustPacket(m_remoteChannel, maxPacketSize());
}
return bytesToDeliver;
}
void AbstractSshChannel::closeChannel()
{
if (m_state == CloseRequested) {
m_timeoutTimer.stop();
} else if (m_state != Closed) {
if (m_state == Inactive) {
setChannelState(Closed);
} else {
const ChannelState oldState = m_state;
setChannelState(CloseRequested);
if (m_remoteChannel != NoChannel) {
m_sendFacility.sendChannelEofPacket(m_remoteChannel);
m_sendFacility.sendChannelClosePacket(m_remoteChannel);
} else {
QSSH_ASSERT(oldState == SessionRequested);
}
}
}
}
void AbstractSshChannel::checkChannelActive() const
{
if (channelState() == Inactive || channelState() == Closed)
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Channel not open.");
}
quint32 AbstractSshChannel::maxDataSize() const
{
return qMin(m_localWindowSize, maxPacketSize());
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,125 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHCHANNEL_P_H
#define SSHCHANNEL_P_H
#include <QByteArray>
#include <QObject>
#include <QString>
#include <QTimer>
namespace QSsh {
namespace Internal {
struct SshChannelExitSignal;
struct SshChannelExitStatus;
class SshIncomingPacket;
class SshSendFacility;
class AbstractSshChannel : public QObject
{
Q_OBJECT
public:
enum ChannelState {
Inactive, SessionRequested, SessionEstablished, CloseRequested, Closed
};
quint32 localChannelId() const { return m_localChannel; }
quint32 remoteChannel() const { return m_remoteChannel; }
virtual void handleChannelSuccess() = 0;
virtual void handleChannelFailure() = 0;
void handleOpenSuccess(quint32 remoteChannelId, quint32 remoteWindowSize,
quint32 remoteMaxPacketSize);
void handleOpenFailure(const QString &reason);
void handleWindowAdjust(quint64 bytesToAdd);
void handleChannelEof();
void handleChannelClose();
void handleChannelData(const QByteArray &data);
void handleChannelExtendedData(quint32 type, const QByteArray &data);
void handleChannelRequest(const SshIncomingPacket &packet);
void closeChannel();
virtual ~AbstractSshChannel();
static const int ReplyTimeout = 10000; // milli seconds
ChannelState channelState() const { return m_state; }
signals:
void timeout();
void eof();
protected:
AbstractSshChannel(quint32 channelId, SshSendFacility &sendFacility);
void setChannelState(ChannelState state);
void requestSessionStart();
void sendData(const QByteArray &data);
static quint32 initialWindowSize();
static quint32 maxPacketSize();
quint32 maxDataSize() const;
void checkChannelActive() const;
SshSendFacility &m_sendFacility;
QTimer m_timeoutTimer;
private:
virtual void handleOpenSuccessInternal() = 0;
virtual void handleOpenFailureInternal(const QString &reason) = 0;
virtual void handleChannelDataInternal(const QByteArray &data) = 0;
virtual void handleChannelExtendedDataInternal(quint32 type,
const QByteArray &data) = 0;
virtual void handleExitStatus(const SshChannelExitStatus &exitStatus) = 0;
virtual void handleExitSignal(const SshChannelExitSignal &signal) = 0;
virtual void closeHook() = 0;
void flushSendBuffer();
int handleChannelOrExtendedChannelData(const QByteArray &data);
const quint32 m_localChannel;
quint32 m_remoteChannel;
quint32 m_localWindowSize;
quint32 m_remoteWindowSize;
quint32 m_remoteMaxPacketSize;
ChannelState m_state;
QByteArray m_sendBuffer;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHCHANNEL_P_H

View File

@@ -1,412 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sftpchannel.h"
#include "sftpchannel_p.h"
#include "sshdirecttcpiptunnel.h"
#include "sshdirecttcpiptunnel_p.h"
#include "sshforwardedtcpiptunnel.h"
#include "sshforwardedtcpiptunnel_p.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include "sshremoteprocess.h"
#include "sshremoteprocess_p.h"
#include "sshsendfacility_p.h"
#include "sshtcpipforwardserver.h"
#include "sshtcpipforwardserver_p.h"
#include "sshx11channel_p.h"
#include "sshx11inforetriever_p.h"
#include <QList>
namespace QSsh {
namespace Internal {
SshChannelManager::SshChannelManager(SshSendFacility &sendFacility,
QObject *parent)
: QObject(parent), m_sendFacility(sendFacility), m_nextLocalChannelId(0)
{
}
void SshChannelManager::handleChannelRequest(const SshIncomingPacket &packet)
{
lookupChannel(packet.extractRecipientChannel())
->handleChannelRequest(packet);
}
void SshChannelManager::handleChannelOpen(const SshIncomingPacket &packet)
{
const SshChannelOpenGeneric channelOpen = packet.extractChannelOpen();
if (channelOpen.channelType == SshIncomingPacket::ForwardedTcpIpType) {
handleChannelOpenForwardedTcpIp(channelOpen);
return;
}
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)
{
const SshChannelOpenFailure &failure = packet.extractChannelOpenFailure();
ChannelIterator it = lookupChannelAsIterator(failure.localChannel);
try {
it.value()->handleOpenFailure(failure.reasonString);
} catch (const SshServerException &e) {
removeChannel(it);
throw;
}
removeChannel(it);
}
void SshChannelManager::handleChannelOpenConfirmation(const SshIncomingPacket &packet)
{
const SshChannelOpenConfirmation &confirmation
= packet.extractChannelOpenConfirmation();
lookupChannel(confirmation.localChannel)->handleOpenSuccess(confirmation.remoteChannel,
confirmation.remoteWindowSize, confirmation.remoteMaxPacketSize);
}
void SshChannelManager::handleChannelSuccess(const SshIncomingPacket &packet)
{
lookupChannel(packet.extractRecipientChannel())->handleChannelSuccess();
}
void SshChannelManager::handleChannelFailure(const SshIncomingPacket &packet)
{
lookupChannel(packet.extractRecipientChannel())->handleChannelFailure();
}
void SshChannelManager::handleChannelWindowAdjust(const SshIncomingPacket &packet)
{
const SshChannelWindowAdjust adjust = packet.extractWindowAdjust();
lookupChannel(adjust.localChannel)->handleWindowAdjust(adjust.bytesToAdd);
}
void SshChannelManager::handleChannelData(const SshIncomingPacket &packet)
{
const SshChannelData &data = packet.extractChannelData();
lookupChannel(data.localChannel)->handleChannelData(data.data);
}
void SshChannelManager::handleChannelExtendedData(const SshIncomingPacket &packet)
{
const SshChannelExtendedData &data = packet.extractChannelExtendedData();
lookupChannel(data.localChannel)->handleChannelExtendedData(data.type, data.data);
}
void SshChannelManager::handleChannelEof(const SshIncomingPacket &packet)
{
AbstractSshChannel * const channel
= lookupChannel(packet.extractRecipientChannel(), true);
if (channel)
channel->handleChannelEof();
}
void SshChannelManager::handleChannelClose(const SshIncomingPacket &packet)
{
const quint32 channelId = packet.extractRecipientChannel();
ChannelIterator it = lookupChannelAsIterator(channelId, true);
if (it != m_channels.end()) {
it.value()->handleChannelClose();
removeChannel(it);
}
}
void SshChannelManager::handleRequestSuccess(const SshIncomingPacket &packet)
{
if (m_waitingForwardServers.isEmpty()) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected request success packet.",
tr("Unexpected request success packet."));
}
SshTcpIpForwardServer::Ptr server = m_waitingForwardServers.takeFirst();
if (server->state() == SshTcpIpForwardServer::Closing) {
server->setClosed();
} else if (server->state() == SshTcpIpForwardServer::Initializing) {
quint16 port = server->port();
if (port == 0)
port = packet.extractRequestSuccess().bindPort;
server->setListening(port);
m_listeningForwardServers.append(server);
} else {
QSSH_ASSERT(false);
}
}
void SshChannelManager::handleRequestFailure(const SshIncomingPacket &packet)
{
Q_UNUSED(packet);
if (m_waitingForwardServers.isEmpty()) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Unexpected request failure packet.",
tr("Unexpected request failure packet."));
}
SshTcpIpForwardServer::Ptr tunnel = m_waitingForwardServers.takeFirst();
tunnel->setClosed();
}
SshChannelManager::ChannelIterator SshChannelManager::lookupChannelAsIterator(quint32 channelId,
bool allowNotFound)
{
ChannelIterator it = m_channels.find(channelId);
if (it == m_channels.end() && !allowNotFound) {
throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid channel id.",
tr("Invalid channel id %1").arg(channelId));
}
return it;
}
AbstractSshChannel *SshChannelManager::lookupChannel(quint32 channelId,
bool allowNotFound)
{
ChannelIterator it = lookupChannelAsIterator(channelId, allowNotFound);
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;
}
QSsh::SshRemoteProcess::Ptr SshChannelManager::createRemoteShell()
{
SshRemoteProcess::Ptr proc(new SshRemoteProcess(m_nextLocalChannelId++, m_sendFacility));
insertChannel(proc->d, proc);
return proc;
}
QSsh::SftpChannel::Ptr SshChannelManager::createSftpChannel()
{
SftpChannel::Ptr sftp(new SftpChannel(m_nextLocalChannelId++, m_sendFacility));
insertChannel(sftp->d, sftp);
return sftp;
}
SshDirectTcpIpTunnel::Ptr SshChannelManager::createDirectTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort)
{
SshDirectTcpIpTunnel::Ptr tunnel(new SshDirectTcpIpTunnel(m_nextLocalChannelId++,
originatingHost, originatingPort, remoteHost, remotePort, m_sendFacility));
insertChannel(tunnel->d, tunnel);
return tunnel;
}
SshTcpIpForwardServer::Ptr SshChannelManager::createForwardServer(const QString &remoteHost,
quint16 remotePort)
{
SshTcpIpForwardServer::Ptr server(new SshTcpIpForwardServer(remoteHost, remotePort,
m_sendFacility));
connect(server.data(), &SshTcpIpForwardServer::stateChanged,
this, [this, server](SshTcpIpForwardServer::State state) {
switch (state) {
case SshTcpIpForwardServer::Closing:
m_listeningForwardServers.removeOne(server);
Q_FALLTHROUGH();
case SshTcpIpForwardServer::Initializing:
m_waitingForwardServers.append(server);
break;
case SshTcpIpForwardServer::Listening:
case SshTcpIpForwardServer::Inactive:
break;
}
});
return server;
}
void SshChannelManager::insertChannel(AbstractSshChannel *priv,
const QSharedPointer<QObject> &pub)
{
connect(priv, &AbstractSshChannel::timeout, this, &SshChannelManager::timeout);
m_channels.insert(priv->localChannelId(), 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;
for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it) {
AbstractSshChannel * const channel = it.value();
QSSH_ASSERT(channel->channelState() != AbstractSshChannel::Closed);
if (channel->channelState() != AbstractSshChannel::CloseRequested) {
channel->closeChannel();
++count;
}
}
if (mode == CloseAllAndReset) {
m_channels.clear();
m_sessions.clear();
}
return count;
}
int SshChannelManager::channelCount() const
{
return m_channels.count();
}
void SshChannelManager::removeChannel(ChannelIterator it)
{
if (it == m_channels.end()) {
throw SshClientException(SshInternalError,
QLatin1String("Internal error: Unexpected channel lookup failure"));
}
const int removeCount = m_sessions.remove(it.value());
if (removeCount != 1) {
throw SshClientException(SshInternalError,
QString::fromLatin1("Internal error: Unexpected session count %1 for channel.")
.arg(removeCount));
}
m_channels.erase(it);
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,117 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHCHANNELLAYER_P_H
#define SSHCHANNELLAYER_P_H
#include "sshx11displayinfo_p.h"
#include <QHash>
#include <QObject>
#include <QSharedPointer>
namespace QSsh {
class SftpChannel;
class SshDirectTcpIpTunnel;
class SshRemoteProcess;
class SshTcpIpForwardServer;
namespace Internal {
class AbstractSshChannel;
struct SshChannelOpenGeneric;
class SshIncomingPacket;
class SshSendFacility;
class SshRemoteProcessPrivate;
class SshChannelManager : public QObject
{
Q_OBJECT
public:
SshChannelManager(SshSendFacility &sendFacility, QObject *parent);
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createDirectTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
QSharedPointer<SshTcpIpForwardServer> createForwardServer(const QString &remoteHost,
quint16 remotePort);
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);
void handleChannelOpenFailure(const SshIncomingPacket &packet);
void handleChannelOpenConfirmation(const SshIncomingPacket &packet);
void handleChannelSuccess(const SshIncomingPacket &packet);
void handleChannelFailure(const SshIncomingPacket &packet);
void handleChannelWindowAdjust(const SshIncomingPacket &packet);
void handleChannelData(const SshIncomingPacket &packet);
void handleChannelExtendedData(const SshIncomingPacket &packet);
void handleChannelEof(const SshIncomingPacket &packet);
void handleChannelClose(const SshIncomingPacket &packet);
void handleRequestSuccess(const SshIncomingPacket &packet);
void handleRequestFailure(const SshIncomingPacket &packet);
signals:
void timeout();
private:
typedef QHash<quint32, AbstractSshChannel *>::Iterator ChannelIterator;
ChannelIterator lookupChannelAsIterator(quint32 channelId,
bool allowNotFound = false);
AbstractSshChannel *lookupChannel(quint32 channelId,
bool allowNotFound = false);
void removeChannel(ChannelIterator it);
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

File diff suppressed because it is too large Load Diff

View File

@@ -1,298 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHCONNECTION_H
#define SSHCONNECTION_H
#include "ssherrors.h"
#include "sshhostkeydatabase.h"
#include "ssh_global.h"
#include <QByteArray>
#include <QFlags>
#include <QMetaType>
#include <QObject>
#include <QSharedPointer>
#include <QString>
#include <QHostAddress>
#include <QUrl>
namespace QSsh {
class SftpChannel;
class SshDirectTcpIpTunnel;
class SshRemoteProcess;
class SshTcpIpForwardServer;
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,
/// 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, ///< 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,
/// 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();
/*!
* \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;
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:
SshConnectionInfo() : localPort(0), peerPort(0) {}
SshConnectionInfo(const QHostAddress &la, quint16 lp, const QHostAddress &pa, quint16 pp)
: localAddress(la), localPort(lp), peerAddress(pa), peerPort(pp) {}
QHostAddress localAddress;
quint16 localPort;
QHostAddress peerAddress;
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 };
/*!
* \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,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
QSharedPointer<SshTcpIpForwardServer> createForwardServer(const QString &remoteHost,
quint16 remotePort);
// -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:
Internal::SshConnectionPrivate *d;
};
} // namespace QSsh
Q_DECLARE_METATYPE(QSsh::SshConnectionParameters::AuthenticationType)
#endif // SSHCONNECTION_H

View File

@@ -1,204 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHCONNECTION_P_H
#define SSHCONNECTION_P_H
#include "sshconnection.h"
#include "sshexception_p.h"
#include "sshincomingpacket_p.h"
#include "sshsendfacility_p.h"
#include <QHash>
#include <QList>
#include <QQueue>
#include <QObject>
#include <QPair>
#include <QScopedPointer>
#include <QTimer>
QT_BEGIN_NAMESPACE
class QTcpSocket;
QT_END_NAMESPACE
namespace QSsh {
class SftpChannel;
class SshRemoteProcess;
class SshDirectTcpIpTunnel;
class SshTcpIpForwardServer;
namespace Internal {
class SshChannelManager;
// NOTE: When you add stuff here, don't forget to update m_packetHandlers.
enum SshStateInternal {
SocketUnconnected, // initial and after disconnect
SocketConnecting, // After connectToHost()
SocketConnected, // After socket's connected() signal
UserAuthServiceRequested,
WaitingForAgentKeys,
UserAuthRequested,
ConnectionEstablished // After service has been started
// ...
};
enum SshKeyExchangeState {
NoKeyExchange,
KexInitSent,
DhInitSent,
NewKeysSent,
KeyExchangeSuccess // After server's DH_REPLY message
};
class SshConnectionPrivate : public QObject
{
Q_OBJECT
friend class QSsh::SshConnection;
public:
SshConnectionPrivate(SshConnection *conn,
const SshConnectionParameters &serverInfo);
~SshConnectionPrivate();
void connectToHost();
void closeConnection(SshErrorCode sshError, SshError userError,
const QByteArray &serverErrorString, const QString &userErrorString);
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createDirectTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
QSharedPointer<SshTcpIpForwardServer> createForwardServer(const QString &remoteHost,
quint16 remotePort);
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();
void disconnected();
void dataAvailable(const QString &message);
void error(QSsh::SshError);
private:
void handleSocketConnected();
void handleIncomingData();
void handleSocketError();
void handleSocketDisconnected();
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();
void handleKeyExchangeInitPacket();
void handleKeyExchangeReplyPacket();
void handleNewKeysPacket();
void handleServiceAcceptPacket();
void handlePasswordExpiredPacket();
void handleUserAuthInfoRequestPacket();
void handleUserAuthSuccessPacket();
void handleUserAuthFailurePacket();
void handleUserAuthKeyOkPacket();
void handleUserAuthBannerPacket();
void handleUnexpectedPacket();
void handleGlobalRequest();
void handleDebugPacket();
void handleUnimplementedPacket();
void handleChannelRequest();
void handleChannelOpen();
void handleChannelOpenFailure();
void handleChannelOpenConfirmation();
void handleChannelSuccess();
void handleChannelFailure();
void handleChannelWindowAdjust();
void handleChannelData();
void handleChannelExtendedData();
void handleChannelEof();
void handleChannelClose();
void handleDisconnect();
void handleRequestSuccess();
void handleRequestFailure();
bool canUseSocket() const;
void createPrivateKey();
void sendData(const QByteArray &data);
uint tokenForAgent() const;
typedef void (SshConnectionPrivate::*PacketHandler)();
typedef QList<SshStateInternal> StateList;
void setupPacketHandlers();
void setupPacketHandler(SshPacketType type, const StateList &states,
PacketHandler handler);
typedef QPair<StateList, PacketHandler> HandlerInStates;
QHash<SshPacketType, HandlerInStates> m_packetHandlers;
static const quint64 InvalidSeqNr;
QTcpSocket *m_socket;
SshStateInternal m_state;
SshKeyExchangeState m_keyExchangeState;
SshIncomingPacket m_incomingPacket;
SshSendFacility m_sendFacility;
SshChannelManager * const m_channelManager;
const SshConnectionParameters m_connParams;
QByteArray m_incomingData;
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,276 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "sshconnection.h"
#include <QCoreApplication>
#include <QList>
#include <QMutex>
#include <QMutexLocker>
#include <QObject>
#include <QThread>
#include <QTimer>
namespace QSsh {
namespace Internal {
class UnaquiredConnection {
public:
UnaquiredConnection(SshConnection *conn) : connection(conn), scheduledForRemoval(false) {}
SshConnection *connection;
bool scheduledForRemoval;
};
bool operator==(UnaquiredConnection c1, UnaquiredConnection c2) {
return c1.connection == c2.connection;
}
bool operator!=(UnaquiredConnection c1, UnaquiredConnection c2) {
return !(c1 == c2);
}
class SshConnectionManager : public QObject
{
Q_OBJECT
public:
SshConnectionManager()
{
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, nullptr, this, nullptr);
delete connection.connection;
}
QSSH_ASSERT(m_acquiredConnections.isEmpty());
QSSH_ASSERT(m_deprecatedConnections.isEmpty());
}
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
{
QMutexLocker locker(&m_listMutex);
// Check in-use connections:
foreach (SshConnection * const connection, m_acquiredConnections) {
if (connection->connectionParameters() != sshParams)
continue;
if (connection->thread() != QThread::currentThread())
continue;
if (m_deprecatedConnections.contains(connection)) // we were asked to no longer use this one...
continue;
m_acquiredConnections.append(connection);
return connection;
}
// Check cached open connections:
foreach (const UnaquiredConnection &c, m_unacquiredConnections) {
SshConnection * const connection = c.connection;
if (connection->state() != SshConnection::Connected
|| connection->connectionParameters() != sshParams)
continue;
if (connection->thread() != QThread::currentThread()) {
if (connection->channelCount() != 0)
continue;
QMetaObject::invokeMethod(this, "switchToCallerThread",
Qt::BlockingQueuedConnection,
Q_ARG(SshConnection *, connection),
Q_ARG(QObject *, QThread::currentThread()));
}
m_unacquiredConnections.removeOne(c);
m_acquiredConnections.append(connection);
return connection;
}
// create a new connection:
SshConnection * const connection = new SshConnection(sshParams);
connect(connection, &SshConnection::disconnected,
this, &SshConnectionManager::cleanup);
m_acquiredConnections.append(connection);
return connection;
}
void releaseConnection(SshConnection *connection)
{
QMutexLocker locker(&m_listMutex);
const bool wasAquired = m_acquiredConnections.removeOne(connection);
QSSH_ASSERT_AND_RETURN(wasAquired);
if (m_acquiredConnections.contains(connection))
return;
bool doDelete = false;
connection->moveToThread(QCoreApplication::instance()->thread());
if (m_deprecatedConnections.removeOne(connection)
|| connection->state() != SshConnection::Connected) {
doDelete = true;
} else {
QSSH_ASSERT_AND_RETURN(!m_unacquiredConnections.contains(UnaquiredConnection(connection)));
// It can happen that two or more connections with the same parameters were acquired
// if the clients were running in different threads. Only keep one of them in
// such a case.
bool haveConnection = false;
foreach (const UnaquiredConnection &c, m_unacquiredConnections) {
if (c.connection->connectionParameters() == connection->connectionParameters()) {
haveConnection = true;
break;
}
}
if (!haveConnection) {
connection->closeAllChannels(); // Clean up after neglectful clients.
m_unacquiredConnections.append(UnaquiredConnection(connection));
} else {
doDelete = true;
}
}
if (doDelete) {
disconnect(connection, nullptr, this, nullptr);
m_deprecatedConnections.removeAll(connection);
connection->deleteLater();
}
}
void forceNewConnection(const SshConnectionParameters &sshParams)
{
QMutexLocker locker(&m_listMutex);
for (int i = 0; i < m_unacquiredConnections.count(); ++i) {
SshConnection * const connection = m_unacquiredConnections.at(i).connection;
if (connection->connectionParameters() == sshParams) {
disconnect(connection, nullptr, this, nullptr);
delete connection;
m_unacquiredConnections.removeAt(i);
break;
}
}
foreach (SshConnection * const connection, m_acquiredConnections) {
if (connection->connectionParameters() == sshParams) {
if (!m_deprecatedConnections.contains(connection))
m_deprecatedConnections.append(connection);
}
}
}
private:
Q_INVOKABLE void switchToCallerThread(SshConnection *connection, QObject *threadObj)
{
connection->moveToThread(qobject_cast<QThread *>(threadObj));
}
void cleanup()
{
QMutexLocker locker(&m_listMutex);
SshConnection *currentConnection = qobject_cast<SshConnection *>(sender());
if (!currentConnection)
return;
if (m_unacquiredConnections.removeOne(UnaquiredConnection(currentConnection))) {
disconnect(currentConnection, nullptr, this, nullptr);
currentConnection->deleteLater();
}
}
void removeInactiveConnections()
{
QMutexLocker locker(&m_listMutex);
for (int i = m_unacquiredConnections.count() - 1; i >= 0; --i) {
UnaquiredConnection &c = m_unacquiredConnections[i];
if (c.scheduledForRemoval) {
disconnect(c.connection, nullptr, this, nullptr);
c.connection->deleteLater();
m_unacquiredConnections.removeAt(i);
} else {
c.scheduledForRemoval = true;
}
}
}
private:
// We expect the number of concurrently open connections to be small.
// If that turns out to not be the case, we can still use a data
// structure with faster access.
QList<UnaquiredConnection> m_unacquiredConnections;
// Can contain the same connection more than once; this acts as a reference count.
QList<SshConnection *> m_acquiredConnections;
QList<SshConnection *> m_deprecatedConnections;
QMutex m_listMutex;
QTimer m_removalTimer;
};
} // namespace Internal
static QMutex instanceMutex;
static Internal::SshConnectionManager &instance()
{
static Internal::SshConnectionManager manager;
return manager;
}
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
{
QMutexLocker locker(&instanceMutex);
return instance().acquireConnection(sshParams);
}
void releaseConnection(SshConnection *connection)
{
QMutexLocker locker(&instanceMutex);
instance().releaseConnection(connection);
}
void forceNewConnection(const SshConnectionParameters &sshParams)
{
QMutexLocker locker(&instanceMutex);
instance().forceNewConnection(sshParams);
}
} // namespace QSsh
#include "sshconnectionmanager.moc"

View File

@@ -1,63 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHCONNECTIONMANAGER_H
#define SSHCONNECTIONMANAGER_H
#include "ssh_global.h"
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);
/*!
* \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,456 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 "sshpacket_p.h"
#include "sshlogging_p.h"
#include <botan_all.h>
#include <QDebug>
#include <QList>
#include <string>
using namespace Botan;
namespace QSsh {
namespace Internal {
SshAbstractCryptoFacility::SshAbstractCryptoFacility()
: m_cipherBlockSize(0), m_macLength(0)
{
}
SshAbstractCryptoFacility::~SshAbstractCryptoFacility() {}
void SshAbstractCryptoFacility::clearKeys()
{
m_cipherBlockSize = 0;
m_macLength = 0;
m_sessionId.clear();
m_pipe.reset(nullptr);
m_hMac.reset(nullptr);
}
SshAbstractCryptoFacility::Mode SshAbstractCryptoFacility::getMode(const QByteArray &algoName)
{
if (algoName.endsWith("-ctr"))
return CtrMode;
if (algoName.endsWith("-cbc"))
return CbcMode;
throw SshClientException(SshInternalError, SSH_TR("Unexpected cipher \"%1\"")
.arg(QString::fromLatin1(algoName)));
}
void SshAbstractCryptoFacility::recreateKeys(const SshKeyExchange &kex)
{
checkInvariant();
if (m_sessionId.isEmpty())
m_sessionId = kex.h();
const QByteArray &rfcCryptAlgoName = cryptAlgoName(kex);
{ // 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);
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);
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());
m_hMac = MessageAuthenticationCode::create_or_throw("HMAC(" + std::string(botanHMacAlgoName(hMacAlgoName(kex))) + ")");
m_hMac->set_key(hMacKey);
}
void SshAbstractCryptoFacility::convert(QByteArray &data, quint32 offset,
quint32 dataSize) const
{
Q_ASSERT(offset + dataSize <= static_cast<quint32>(data.size()));
checkInvariant();
// Session id empty => No key exchange has happened yet.
if (dataSize == 0 || m_sessionId.isEmpty())
return;
if (dataSize % cipherBlockSize() != 0) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid packet size");
}
m_pipe->process_msg(reinterpret_cast<const byte *>(data.constData()) + offset,
dataSize);
// Can't use Pipe::LAST_MESSAGE because of a VC bug.
quint32 bytesRead = static_cast<quint32>(m_pipe->read(
reinterpret_cast<byte *>(data.data()) + offset, dataSize, m_pipe->message_count() - 1));
if (bytesRead != dataSize) {
throw SshClientException(SshInternalError,
QLatin1String("Internal error: Botan::Pipe::read() returned unexpected value"));
}
}
Keyed_Filter *SshAbstractCryptoFacility::makeCtrCipherMode(const QByteArray &cipher)
{
StreamCipher_Filter *filter = new StreamCipher_Filter(cipher.toStdString());
return filter;
}
QByteArray SshAbstractCryptoFacility::generateMac(const QByteArray &data,
quint32 dataSize) const
{
return m_sessionId.isEmpty()
? QByteArray()
: convertByteArray(m_hMac->process(reinterpret_cast<const byte *>(data.constData()),
dataSize));
}
QByteArray SshAbstractCryptoFacility::generateHash(const SshKeyExchange &kex,
char c, quint32 length)
{
const QByteArray &k = kex.k();
const QByteArray &h = kex.h();
QByteArray data(k);
data.append(h).append(c).append(m_sessionId);
SecureVector<byte> key
= kex.hash()->process(convertByteArray(data), data.size());
while (key.size() < length) {
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.data()), length);
}
void SshAbstractCryptoFacility::checkInvariant() const
{
Q_ASSERT(m_sessionId.isEmpty() == !m_pipe);
}
const QByteArray SshEncryptionFacility::PrivKeyFileStartLineRsa("-----BEGIN RSA PRIVATE KEY-----");
const QByteArray SshEncryptionFacility::PrivKeyFileStartLineDsa("-----BEGIN DSA PRIVATE KEY-----");
const QByteArray SshEncryptionFacility::PrivKeyFileEndLineRsa("-----END RSA PRIVATE KEY-----");
const QByteArray SshEncryptionFacility::PrivKeyFileEndLineDsa("-----END DSA PRIVATE KEY-----");
const QByteArray SshEncryptionFacility::PrivKeyFileStartLineEcdsa("-----BEGIN EC PRIVATE KEY-----");
const QByteArray SshEncryptionFacility::PrivKeyFileEndLineEcdsa("-----END EC PRIVATE KEY-----");
QByteArray SshEncryptionFacility::cryptAlgoName(const SshKeyExchange &kex) const
{
return kex.encryptionAlgo();
}
QByteArray SshEncryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
{
return kex.hMacAlgoClientToServer();
}
Keyed_Filter *SshEncryptionFacility::makeCipherMode(const QByteArray &cipher, const Mode mode)
{
if (mode == CtrMode) {
return new StreamCipher_Filter(cipher.toStdString());
}
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
{
convert(data, 0, data.size());
}
void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFileContents)
{
if (privKeyFileContents == m_cachedPrivKeyContents)
return;
m_authKeyAlgoName.clear();
qCDebug(sshLog, "%s: Key not cached, reading", Q_FUNC_INFO);
QList<BigInt> pubKeyParams;
QList<BigInt> allKeyParams;
QString error1;
QString error2;
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));
throw SshClientException(SshKeyFileError, SSH_TR("Decoding of private key file failed: "
"Format not understood."));
}
foreach (const BigInt &b, allKeyParams) {
if (b.is_zero()) {
throw SshClientException(SshKeyFileError,
SSH_TR("Decoding of private key file failed: Invalid zero parameter."));
}
}
m_authPubKeyBlob = AbstractSshPacket::encodeString(m_authKeyAlgoName);
auto * const ecdsaKey = dynamic_cast<ECDSA_PrivateKey *>(m_authKey.data());
if (ecdsaKey) {
m_authPubKeyBlob += AbstractSshPacket::encodeString(m_authKeyAlgoName.mid(11)); // Without "ecdsa-sha2-" prefix.
m_authPubKeyBlob += AbstractSshPacket::encodeString(
convertByteArray(ecdsaKey->public_point().encode(PointGFp::UNCOMPRESSED)));
} else {
foreach (const BigInt &b, pubKeyParams)
m_authPubKeyBlob += AbstractSshPacket::encodeMpInt(b);
}
m_cachedPrivKeyContents = privKeyFileContents;
}
bool SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams, QString &error)
{
try {
Pipe pipe;
pipe.process_msg(convertByteArray(privKeyFileContents), privKeyFileContents.size());
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()
<< dsaKey->group_g() << dsaKey->get_y();
allKeyParams << pubKeyParams << dsaKey->get_x();
} else if (auto * const rsaKey = dynamic_cast<RSA_PrivateKey *>(m_authKey.data())) {
m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
pubKeyParams << rsaKey->get_e() << rsaKey->get_n();
allKeyParams << pubKeyParams << rsaKey->get_p() << rsaKey->get_q()
<< rsaKey->get_d();
} else if (auto * const ecdsaKey = dynamic_cast<ECDSA_PrivateKey *>(m_authKey.data())) {
const BigInt value = ecdsaKey->private_value();
m_authKeyAlgoName = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(
static_cast<int>(value.bytes()));
pubKeyParams << ecdsaKey->public_point().get_affine_x()
<< ecdsaKey->public_point().get_affine_y();
allKeyParams << pubKeyParams << value;
} else {
qCWarning(sshLog, "%s: Unexpected code flow, expected success or exception.",
Q_FUNC_INFO);
return false;
}
} catch (const std::exception &ex) {
error = QLatin1String(ex.what());
return false;
}
return true;
}
bool SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams, QString &error)
{
try {
bool syntaxOk = true;
QList<QByteArray> lines = privKeyFileContents.split('\n');
while (lines.last().isEmpty())
lines.removeLast();
if (lines.count() < 3) {
syntaxOk = false;
} else if (lines.first() == PrivKeyFileStartLineRsa) {
if (lines.last() != PrivKeyFileEndLineRsa)
syntaxOk = false;
else
m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
} else if (lines.first() == PrivKeyFileStartLineDsa) {
if (lines.last() != PrivKeyFileEndLineDsa)
syntaxOk = false;
else
m_authKeyAlgoName = SshCapabilities::PubKeyDss;
} else if (lines.first() == PrivKeyFileStartLineEcdsa) {
if (lines.last() != PrivKeyFileEndLineEcdsa)
syntaxOk = false;
// m_authKeyAlgoName set below, as we don't know the size yet.
} else {
syntaxOk = false;
}
if (!syntaxOk) {
error = SSH_TR("Unexpected format.");
return false;
}
QByteArray privateKeyBlob;
for (int i = 1; i < lines.size() - 1; ++i)
privateKeyBlob += lines.at(i);
privateKeyBlob = QByteArray::fromBase64(privateKeyBlob);
BER_Decoder decoder(convertByteArray(privateKeyBlob), privateKeyBlob.size());
BER_Decoder sequence = decoder.start_cons(SEQUENCE);
size_t version;
sequence.decode (version);
const size_t expectedVersion = m_authKeyAlgoName.isEmpty() ? 1 : 0;
if (version != expectedVersion) {
error = SSH_TR("Key encoding has version %1, expected %2.")
.arg(version).arg(expectedVersion);
return false;
}
if (m_authKeyAlgoName == SshCapabilities::PubKeyDss) {
BigInt p, q, g, y, x;
sequence.decode (p).decode (q).decode (g).decode (y).decode (x);
DSA_PrivateKey * const dsaKey = new DSA_PrivateKey(m_rng, DL_Group(p, q, g), x);
m_authKey.reset(dsaKey);
pubKeyParams << p << q << g << y;
allKeyParams << pubKeyParams << x;
} 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(p, q, e, d, n);
m_authKey.reset(rsaKey);
pubKeyParams << e << n;
allKeyParams << pubKeyParams << p << q << d;
} else {
BigInt privKey;
sequence.decode_octet_string_bigint(privKey);
m_authKeyAlgoName = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(
static_cast<int>(privKey.bytes()));
const EC_Group group(SshCapabilities::oid(m_authKeyAlgoName));
auto * const key = new ECDSA_PrivateKey(m_rng, group, privKey);
m_authKey.reset(key);
pubKeyParams << key->public_point().get_affine_x()
<< key->public_point().get_affine_y();
allKeyParams << pubKeyParams << privKey;
}
sequence.discard_remaining();
sequence.verify_end();
} catch (const std::exception &ex) {
error = QLatin1String(ex.what());
return false;
}
return true;
}
QByteArray SshEncryptionFacility::authenticationAlgorithmName() const
{
Q_ASSERT(m_authKey);
return m_authKeyAlgoName;
}
QByteArray SshEncryptionFacility::authenticationKeySignature(const QByteArray &data) const
{
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
= convertByteArray(signer->sign_message(convertByteArray(dataToSign),
dataToSign.size(), m_rng));
if (m_authKeyAlgoName.startsWith(SshCapabilities::PubKeyEcdsaPrefix)) {
// The Botan output is not quite in the format that SSH defines.
const int halfSize = signature.count() / 2;
const BigInt r = BigInt::decode(convertByteArray(signature), halfSize);
const BigInt s = BigInt::decode(convertByteArray(signature.mid(halfSize)), halfSize);
signature = AbstractSshPacket::encodeMpInt(r) + AbstractSshPacket::encodeMpInt(s);
}
return AbstractSshPacket::encodeString(m_authKeyAlgoName)
+ AbstractSshPacket::encodeString(signature);
}
QByteArray SshEncryptionFacility::getRandomNumbers(int count) const
{
QByteArray data;
data.resize(count);
m_rng.randomize(convertByteArray(data), count);
return data;
}
SshEncryptionFacility::~SshEncryptionFacility() {}
QByteArray SshDecryptionFacility::cryptAlgoName(const SshKeyExchange &kex) const
{
return kex.decryptionAlgo();
}
QByteArray SshDecryptionFacility::hMacAlgoName(const SshKeyExchange &kex) const
{
return kex.hMacAlgoServerToClient();
}
Keyed_Filter *SshDecryptionFacility::makeCipherMode(const QByteArray &cipher, const Mode mode)
{
if (mode == CtrMode) {
return new StreamCipher_Filter(cipher.toStdString());
}
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,
quint32 dataSize) const
{
convert(data, offset, dataSize);
qCDebug(sshLog, "Decrypted data:");
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) << ")";
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,144 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHABSTRACTCRYPTOFACILITY_P_H
#define SSHABSTRACTCRYPTOFACILITY_P_H
#include <botan_all.h>
#include <QByteArray>
#include <QScopedPointer>
namespace QSsh {
namespace Internal {
class SshKeyExchange;
class SshAbstractCryptoFacility
{
public:
virtual ~SshAbstractCryptoFacility();
void clearKeys();
void recreateKeys(const SshKeyExchange &kex);
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;
Botan::Keyed_Filter *makeCtrCipherMode(const QByteArray &cipher);
private:
SshAbstractCryptoFacility(const SshAbstractCryptoFacility &);
SshAbstractCryptoFacility &operator=(const SshAbstractCryptoFacility &);
virtual QByteArray cryptAlgoName(const SshKeyExchange &kex) const = 0;
virtual QByteArray hMacAlgoName(const SshKeyExchange &kex) const = 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;
QByteArray generateHash(const SshKeyExchange &kex, char c, quint32 length);
void checkInvariant() const;
static Mode getMode(const QByteArray &algoName);
QByteArray m_sessionId;
std::unique_ptr<Botan::Pipe> m_pipe;
std::unique_ptr<Botan::MessageAuthenticationCode> m_hMac;
quint32 m_cipherBlockSize;
quint32 m_macLength;
};
class SshEncryptionFacility : public SshAbstractCryptoFacility
{
public:
void encrypt(QByteArray &data) const;
void createAuthenticationKey(const QByteArray &privKeyFileContents);
QByteArray authenticationAlgorithmName() const;
QByteArray authenticationPublicKey() const { return m_authPubKeyBlob; }
QByteArray authenticationKeySignature(const QByteArray &data) const;
QByteArray getRandomNumbers(int count) const;
~SshEncryptionFacility();
private:
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);
bool createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams, QString &error);
static const QByteArray PrivKeyFileStartLineRsa;
static const QByteArray PrivKeyFileStartLineDsa;
static const QByteArray PrivKeyFileEndLineRsa;
static const QByteArray PrivKeyFileEndLineDsa;
static const QByteArray PrivKeyFileStartLineEcdsa;
static const QByteArray PrivKeyFileEndLineEcdsa;
QByteArray m_authKeyAlgoName;
QByteArray m_authPubKeyBlob;
QByteArray m_cachedPrivKeyContents;
QScopedPointer<Botan::Private_Key> m_authKey;
mutable Botan::AutoSeeded_RNG m_rng;
};
class SshDecryptionFacility : public SshAbstractCryptoFacility
{
public:
void decrypt(QByteArray &data, quint32 offset, quint32 dataSize) const;
private:
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,129 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** 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"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include "sshsendfacility_p.h"
#include <QTimer>
namespace QSsh {
namespace Internal {
SshDirectTcpIpTunnelPrivate::SshDirectTcpIpTunnelPrivate(quint32 channelId,
const QString &originatingHost, quint16 originatingPort, const QString &remoteHost,
quint16 remotePort, SshSendFacility &sendFacility)
: SshTcpIpTunnelPrivate(channelId, sendFacility),
m_originatingHost(originatingHost),
m_originatingPort(originatingPort),
m_remoteHost(remoteHost),
m_remotePort(remotePort)
{
}
void SshDirectTcpIpTunnelPrivate::handleOpenSuccessInternal()
{
emit initialized();
}
} // namespace Internal
using namespace Internal;
SshDirectTcpIpTunnel::SshDirectTcpIpTunnel(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
SshSendFacility &sendFacility)
: d(new SshDirectTcpIpTunnelPrivate(channelId, originatingHost, originatingPort, remoteHost,
remotePort, sendFacility))
{
d->init(this);
connect(d, &SshDirectTcpIpTunnelPrivate::initialized,
this, &SshDirectTcpIpTunnel::initialized, Qt::QueuedConnection);
}
SshDirectTcpIpTunnel::~SshDirectTcpIpTunnel()
{
delete d;
}
bool SshDirectTcpIpTunnel::atEnd() const
{
return QIODevice::atEnd() && d->m_data.isEmpty();
}
qint64 SshDirectTcpIpTunnel::bytesAvailable() const
{
return QIODevice::bytesAvailable() + d->m_data.count();
}
bool SshDirectTcpIpTunnel::canReadLine() const
{
return QIODevice::canReadLine() || d->m_data.contains('\n');
}
void SshDirectTcpIpTunnel::close()
{
d->closeChannel();
QIODevice::close();
}
void SshDirectTcpIpTunnel::initialize()
{
QSSH_ASSERT_AND_RETURN(d->channelState() == AbstractSshChannel::Inactive);
try {
QIODevice::open(QIODevice::ReadWrite);
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.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();
}
}
qint64 SshDirectTcpIpTunnel::readData(char *data, qint64 maxlen)
{
return d->readData(data, maxlen);
}
qint64 SshDirectTcpIpTunnel::writeData(const char *data, qint64 len)
{
return d->writeData(data, len);
}
} // namespace QSsh

View File

@@ -1,89 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** 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 SSHDIRECTTCPIPTUNNEL_H
#define SSHDIRECTTCPIPTUNNEL_H
#include "ssh_global.h"
#include <QIODevice>
#include <QSharedPointer>
namespace QSsh {
namespace Internal {
class SshChannelManager;
class SshDirectTcpIpTunnelPrivate;
class SshSendFacility;
class SshTcpIpTunnelPrivate;
} // namespace Internal
class QSSH_EXPORT SshDirectTcpIpTunnel : public QIODevice
{
Q_OBJECT
friend class Internal::SshChannelManager;
friend class Internal::SshTcpIpTunnelPrivate;
public:
typedef QSharedPointer<SshDirectTcpIpTunnel> Ptr;
~SshDirectTcpIpTunnel();
// QIODevice stuff
bool atEnd() const;
qint64 bytesAvailable() const;
bool canReadLine() const;
void close();
bool isSequential() const { return true; }
void initialize();
signals:
void initialized();
void error(const QString &reason);
private:
SshDirectTcpIpTunnel(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
Internal::SshSendFacility &sendFacility);
// QIODevice stuff
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
Internal::SshDirectTcpIpTunnelPrivate * const d;
};
} // namespace QSsh
#endif // SSHDIRECTTCPIPTUNNEL_H

View File

@@ -1,68 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** 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"
namespace QSsh {
class SshDirectTcpIpTunnel;
namespace Internal {
class SshDirectTcpIpTunnelPrivate : public SshTcpIpTunnelPrivate
{
Q_OBJECT
friend class QSsh::SshDirectTcpIpTunnel;
public:
explicit SshDirectTcpIpTunnelPrivate(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
SshSendFacility &sendFacility);
signals:
void initialized();
private:
void handleOpenSuccessInternal();
const QString m_originatingHost;
const quint16 m_originatingPort;
const QString m_remoteHost;
const quint16 m_remotePort;
};
} // namespace Internal
} // namespace QSsh
#endif // DIRECTTCPIPCHANNEL_P_H

View File

@@ -1,77 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHERRORS_P_H
#define SSHERRORS_P_H
#include <QMetaType>
namespace QSsh {
/*!
* \brief SSH specific errors
*/
enum SshError {
/// 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,95 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHEXCEPTION_P_H
#define SSHEXCEPTION_P_H
#include "ssherrors.h"
#include <QByteArray>
#include <QCoreApplication>
#include <QString>
#include <exception>
namespace QSsh {
namespace Internal {
enum SshErrorCode {
SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1,
SSH_DISCONNECT_PROTOCOL_ERROR = 2,
SSH_DISCONNECT_KEY_EXCHANGE_FAILED = 3,
SSH_DISCONNECT_RESERVED = 4,
SSH_DISCONNECT_MAC_ERROR = 5,
SSH_DISCONNECT_COMPRESSION_ERROR = 6,
SSH_DISCONNECT_SERVICE_NOT_AVAILABLE = 7,
SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8,
SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9,
SSH_DISCONNECT_CONNECTION_LOST = 10,
SSH_DISCONNECT_BY_APPLICATION = 11,
SSH_DISCONNECT_TOO_MANY_CONNECTIONS = 12,
SSH_DISCONNECT_AUTH_CANCELLED_BY_USER = 13,
SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14,
SSH_DISCONNECT_ILLEGAL_USER_NAME = 15
};
#define SSH_TR(string) QCoreApplication::translate("SshConnection", string)
#define SSH_SERVER_EXCEPTION(error, errorString) \
SshServerException((error), (errorString), SSH_TR(errorString))
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 : public std::exception
{
SshClientException(SshError error, const QString &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,100 +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 "sshforwardedtcpiptunnel.h"
#include "sshforwardedtcpiptunnel_p.h"
#include "sshlogging_p.h"
#include "sshsendfacility_p.h"
namespace QSsh {
namespace Internal {
SshForwardedTcpIpTunnelPrivate::SshForwardedTcpIpTunnelPrivate(quint32 channelId,
SshSendFacility &sendFacility) :
SshTcpIpTunnelPrivate(channelId, sendFacility)
{
setChannelState(SessionRequested);
}
void SshForwardedTcpIpTunnelPrivate::handleOpenSuccessInternal()
{
QSSH_ASSERT_AND_RETURN(channelState() == AbstractSshChannel::SessionEstablished);
try {
m_sendFacility.sendChannelOpenConfirmationPacket(remoteChannel(), localChannelId(),
initialWindowSize(), maxPacketSize());
} catch (const std::exception &e) { // Won't happen, but let's play it safe.
qCWarning(sshLog, "Botan error: %s", e.what());
closeChannel();
}
}
} // namespace Internal
using namespace Internal;
SshForwardedTcpIpTunnel::SshForwardedTcpIpTunnel(quint32 channelId, SshSendFacility &sendFacility) :
d(new SshForwardedTcpIpTunnelPrivate(channelId, sendFacility))
{
d->init(this);
}
SshForwardedTcpIpTunnel::~SshForwardedTcpIpTunnel()
{
delete d;
}
bool SshForwardedTcpIpTunnel::atEnd() const
{
return QIODevice::atEnd() && d->m_data.isEmpty();
}
qint64 SshForwardedTcpIpTunnel::bytesAvailable() const
{
return QIODevice::bytesAvailable() + d->m_data.count();
}
bool SshForwardedTcpIpTunnel::canReadLine() const
{
return QIODevice::canReadLine() || d->m_data.contains('\n');
}
void SshForwardedTcpIpTunnel::close()
{
d->closeChannel();
QIODevice::close();
}
qint64 SshForwardedTcpIpTunnel::readData(char *data, qint64 maxlen)
{
return d->readData(data, maxlen);
}
qint64 SshForwardedTcpIpTunnel::writeData(const char *data, qint64 len)
{
return d->writeData(data, len);
}
} // namespace QSsh

View File

@@ -1,70 +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.
**
****************************************************************************/
#pragma once
#include "ssh_global.h"
#include <QIODevice>
#include <QSharedPointer>
namespace QSsh {
namespace Internal {
class SshChannelManager;
class SshForwardedTcpIpTunnelPrivate;
class SshSendFacility;
class SshTcpIpTunnelPrivate;
} // namespace Internal
class QSSH_EXPORT SshForwardedTcpIpTunnel : public QIODevice
{
Q_OBJECT
friend class Internal::SshChannelManager;
friend class Internal::SshTcpIpTunnelPrivate;
public:
typedef QSharedPointer<SshForwardedTcpIpTunnel> Ptr;
~SshForwardedTcpIpTunnel() override;
// QIODevice stuff
bool atEnd() const override;
qint64 bytesAvailable() const override;
bool canReadLine() const override;
void close() override;
bool isSequential() const override { return true; }
signals:
void error(const QString &reason);
private:
SshForwardedTcpIpTunnel(quint32 channelId, Internal::SshSendFacility &sendFacility);
// QIODevice stuff
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
Internal::SshForwardedTcpIpTunnelPrivate * const d;
};
} // namespace QSsh

View File

@@ -1,44 +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.
**
****************************************************************************/
#pragma once
#include "sshforwardedtcpiptunnel.h"
#include "sshtcpiptunnel_p.h"
namespace QSsh {
namespace Internal {
class SshForwardedTcpIpTunnelPrivate : public SshTcpIpTunnelPrivate
{
Q_OBJECT
friend class QSsh::SshForwardedTcpIpTunnel;
public:
SshForwardedTcpIpTunnelPrivate(quint32 channelId, SshSendFacility &sendFacility);
void handleOpenSuccessInternal() override;
};
} // namespace Internal
} // namespace QSsh

View File

@@ -1,127 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 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"
#include <QByteArray>
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QHash>
#include <QString>
namespace QSsh {
class SshHostKeyDatabase::SshHostKeyDatabasePrivate
{
public:
QHash<QString, QByteArray> hostKeys;
};
SshHostKeyDatabase::SshHostKeyDatabase() : d(new SshHostKeyDatabasePrivate)
{
}
SshHostKeyDatabase::~SshHostKeyDatabase()
{
delete d;
}
bool SshHostKeyDatabase::load(const QString &filePath, QString *error)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
if (error) {
*error = QCoreApplication::translate("QSsh::Ssh",
"Failed to open key file \"%1\" for reading: %2")
.arg(QDir::toNativeSeparators(filePath), file.errorString());
}
return false;
}
d->hostKeys.clear();
const QByteArray content = file.readAll().trimmed();
if (content.isEmpty())
return true;
foreach (const QByteArray &line, content.split('\n')) {
const QList<QByteArray> &lineData = line.trimmed().split(' ');
if (lineData.count() != 2) {
qCDebug(Internal::sshLog, "Unexpected line \"%s\" in file \"%s\".", line.constData(),
qPrintable(filePath));
continue;
}
d->hostKeys.insert(QString::fromUtf8(lineData.first()),
QByteArray::fromHex(lineData.last()));
}
return true;
}
bool SshHostKeyDatabase::store(const QString &filePath, QString *error) const
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly)) {
if (error) {
*error = QCoreApplication::translate("QSsh::Ssh",
"Failed to open key file \"%1\" for writing: %2")
.arg(QDir::toNativeSeparators(filePath), file.errorString());
}
return false;
}
file.resize(0);
for (auto it = d->hostKeys.constBegin(); it != d->hostKeys.constEnd(); ++it)
file.write(it.key().toUtf8() + ' ' + it.value().toHex() + '\n');
return true;
}
SshHostKeyDatabase::KeyLookupResult SshHostKeyDatabase::matchHostKey(const QString &hostName,
const QByteArray &key) const
{
auto it = d->hostKeys.constFind(hostName);
if (it == d->hostKeys.constEnd())
return KeyLookupNoMatch;
if (it.value() == key)
return KeyLookupMatch;
return KeyLookupMismatch;
}
void SshHostKeyDatabase::insertHostKey(const QString &hostName, const QByteArray &key)
{
d->hostKeys.insert(hostName, key);
}
QByteArray SshHostKeyDatabase::retrieveHostKey(const QString &hostName)
{
return d->hostKeys.value(hostName);
}
} // namespace QSsh

View File

@@ -1,75 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 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.
**
****************************************************************************/
#ifndef SSHHOSTKEYDATABASE_H
#define SSHHOSTKEYDATABASE_H
#include "ssh_global.h"
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
class QByteArray;
class QString;
QT_END_NAMESPACE
namespace QSsh {
class SshHostKeyDatabase;
/// Convenience typedef
typedef QSharedPointer<SshHostKeyDatabase> SshHostKeyDatabasePtr;
class QSSH_EXPORT SshHostKeyDatabase
{
friend class QSharedPointer<SshHostKeyDatabase>; // To give create() access to our constructor.
public:
enum KeyLookupResult {
KeyLookupMatch,
KeyLookupNoMatch,
KeyLookupMismatch
};
SshHostKeyDatabase();
~SshHostKeyDatabase();
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:
class SshHostKeyDatabasePrivate;
SshHostKeyDatabasePrivate * const d;
};
} // namespace QSsh
#endif // Include guard.

View File

@@ -1,609 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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"
#include "ssh_global.h"
#include "sshbotanconversions_p.h"
#include "sshcapabilities_p.h"
#include "sshlogging_p.h"
namespace QSsh {
namespace Internal {
const QByteArray SshIncomingPacket::ExitStatusType("exit-status");
const QByteArray SshIncomingPacket::ExitSignalType("exit-signal");
const QByteArray SshIncomingPacket::ForwardedTcpIpType("forwarded-tcpip");
SshIncomingPacket::SshIncomingPacket() : m_serverSeqNr(0) { }
quint32 SshIncomingPacket::cipherBlockSize() const
{
return qMax(m_decrypter.cipherBlockSize(), 8U);
}
quint32 SshIncomingPacket::macLength() const
{
return m_decrypter.macLength();
}
void SshIncomingPacket::recreateKeys(const SshKeyExchange &keyExchange)
{
m_decrypter.recreateKeys(keyExchange);
}
void SshIncomingPacket::reset()
{
clear();
m_serverSeqNr = 0;
m_decrypter.clearKeys();
}
void SshIncomingPacket::consumeData(QByteArray &newData)
{
qCDebug(sshLog, "%s: current data size = %d, new data size = %d",
Q_FUNC_INFO, m_data.size(), newData.size());
if (isComplete() || newData.isEmpty())
return;
/*
* Until we have reached the minimum packet size, we cannot decrypt the
* length field.
*/
const quint32 minSize = minPacketSize();
if (currentDataSize() < minSize) {
const int bytesToTake
= qMin<quint32>(minSize - currentDataSize(), newData.size());
moveFirstBytes(m_data, newData, bytesToTake);
qCDebug(sshLog, "Took %d bytes from new data", bytesToTake);
if (currentDataSize() < minSize)
return;
}
if (4 + length() + macLength() < currentDataSize())
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Server sent invalid packet.");
const int bytesToTake
= qMin<quint32>(length() + 4 + macLength() - currentDataSize(),
newData.size());
moveFirstBytes(m_data, newData, bytesToTake);
qCDebug(sshLog, "Took %d bytes from new data", bytesToTake);
if (isComplete()) {
qCDebug(sshLog, "Message complete. Overall size: %u, payload size: %u",
m_data.size(), m_length - paddingLength() - 1);
decrypt();
++m_serverSeqNr;
}
}
void SshIncomingPacket::decrypt()
{
Q_ASSERT(isComplete());
const quint32 netDataLength = length() + 4;
m_decrypter.decrypt(m_data, cipherBlockSize(),
netDataLength - cipherBlockSize());
const QByteArray &mac = m_data.mid(netDataLength, macLength());
if (mac != generateMac(m_decrypter, m_serverSeqNr)) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_MAC_ERROR,
"Message authentication failed.");
}
}
void SshIncomingPacket::moveFirstBytes(QByteArray &target, QByteArray &source,
int n)
{
target.append(source.left(n));
source.remove(0, n);
}
SshKeyExchangeInit SshIncomingPacket::extractKeyExchangeInitData() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_KEXINIT);
SshKeyExchangeInit exchangeData;
try {
quint32 offset = TypeOffset + 1;
std::memcpy(exchangeData.cookie, &m_data.constData()[offset],
sizeof exchangeData.cookie);
offset += sizeof exchangeData.cookie;
exchangeData.keyAlgorithms
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.serverHostKeyAlgorithms
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.encryptionAlgorithmsClientToServer
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.encryptionAlgorithmsServerToClient
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.macAlgorithmsClientToServer
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.macAlgorithmsServerToClient
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.compressionAlgorithmsClientToServer
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.compressionAlgorithmsServerToClient
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.languagesClientToServer
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.languagesServerToClient
= SshPacketParser::asNameList(m_data, &offset);
exchangeData.firstKexPacketFollows
= SshPacketParser::asBool(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Key exchange failed: Server sent invalid SSH_MSG_KEXINIT packet.");
}
return exchangeData;
}
static void getHostKeySpecificReplyData(SshKeyExchangeReply &replyData,
const QByteArray &hostKeyAlgo, const QByteArray &input)
{
quint32 offset = 0;
if (hostKeyAlgo == SshCapabilities::PubKeyDss || hostKeyAlgo == SshCapabilities::PubKeyRsa) {
// DSS: p and q, RSA: e and n
replyData.hostKeyParameters << SshPacketParser::asBigInt(input, &offset);
replyData.hostKeyParameters << SshPacketParser::asBigInt(input, &offset);
// g and y
if (hostKeyAlgo == SshCapabilities::PubKeyDss) {
replyData.hostKeyParameters << SshPacketParser::asBigInt(input, &offset);
replyData.hostKeyParameters << SshPacketParser::asBigInt(input, &offset);
}
} else {
QSSH_ASSERT_AND_RETURN(hostKeyAlgo.startsWith(SshCapabilities::PubKeyEcdsaPrefix));
if (SshPacketParser::asString(input, &offset)
!= hostKeyAlgo.mid(11)) { // Without "ecdsa-sha2-" prefix.
throw SshPacketParseException();
}
replyData.q = SshPacketParser::asString(input, &offset);
}
}
static QByteArray &padToWidth(QByteArray &data, int targetWidth)
{
return data.prepend(QByteArray(targetWidth - data.count(), 0));
}
SshKeyExchangeReply SshIncomingPacket::extractKeyExchangeReply(const QByteArray &kexAlgo,
const QByteArray &hostKeyAlgo) const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_KEXDH_REPLY);
try {
SshKeyExchangeReply replyData;
quint32 topLevelOffset = TypeOffset + 1;
replyData.k_s = SshPacketParser::asString(m_data, &topLevelOffset);
quint32 k_sOffset = 0;
if (SshPacketParser::asString(replyData.k_s, &k_sOffset) != hostKeyAlgo)
throw SshPacketParseException();
getHostKeySpecificReplyData(replyData, hostKeyAlgo, replyData.k_s.mid(k_sOffset));
if (kexAlgo == SshCapabilities::DiffieHellmanGroup1Sha1
|| kexAlgo == SshCapabilities::DiffieHellmanGroup14Sha1) {
replyData.f = SshPacketParser::asBigInt(m_data, &topLevelOffset);
} else {
QSSH_ASSERT_AND_RETURN_VALUE(kexAlgo.startsWith(SshCapabilities::EcdhKexNamePrefix),
SshKeyExchangeReply());
replyData.q_s = SshPacketParser::asString(m_data, &topLevelOffset);
}
const QByteArray fullSignature = SshPacketParser::asString(m_data, &topLevelOffset);
quint32 sigOffset = 0;
if (SshPacketParser::asString(fullSignature, &sigOffset) != hostKeyAlgo)
throw SshPacketParseException();
replyData.signatureBlob = SshPacketParser::asString(fullSignature, &sigOffset);
if (hostKeyAlgo.startsWith(SshCapabilities::PubKeyEcdsaPrefix)) {
// Botan's PK_Verifier wants the signature in this format.
quint32 blobOffset = 0;
const Botan::BigInt r = SshPacketParser::asBigInt(replyData.signatureBlob, &blobOffset);
const Botan::BigInt s = SshPacketParser::asBigInt(replyData.signatureBlob, &blobOffset);
const int width = SshCapabilities::ecdsaIntegerWidthInBytes(hostKeyAlgo);
QByteArray encodedR = convertByteArray(Botan::BigInt::encode(r));
replyData.signatureBlob = padToWidth(encodedR, width);
QByteArray encodedS = convertByteArray(Botan::BigInt::encode(s));
replyData.signatureBlob += padToWidth(encodedS, width);
}
replyData.k_s.prepend(m_data.mid(TypeOffset + 1, 4));
return replyData;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Key exchange failed: "
"Server sent invalid key exchange reply packet.");
}
}
SshDisconnect SshIncomingPacket::extractDisconnect() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_DISCONNECT);
SshDisconnect msg;
try {
quint32 offset = TypeOffset + 1;
msg.reasonCode = SshPacketParser::asUint32(m_data, &offset);
msg.description = SshPacketParser::asUserString(m_data, &offset);
msg.language = SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_DISCONNECT.");
}
return msg;
}
SshUserAuthBanner SshIncomingPacket::extractUserAuthBanner() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_USERAUTH_BANNER);
try {
SshUserAuthBanner msg;
quint32 offset = TypeOffset + 1;
msg.message = SshPacketParser::asUserString(m_data, &offset);
msg.language = SshPacketParser::asString(m_data, &offset);
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_USERAUTH_BANNER.");
}
}
SshUserAuthInfoRequestPacket SshIncomingPacket::extractUserAuthInfoRequest() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_USERAUTH_INFO_REQUEST);
try {
SshUserAuthInfoRequestPacket msg;
quint32 offset = TypeOffset + 1;
msg.name = SshPacketParser::asUserString(m_data, &offset);
msg.instruction = SshPacketParser::asUserString(m_data, &offset);
msg.languageTag = SshPacketParser::asString(m_data, &offset);
const quint32 promptCount = SshPacketParser::asUint32(m_data, &offset);
msg.prompts.reserve(promptCount);
msg.echos.reserve(promptCount);
for (quint32 i = 0; i < promptCount; ++i) {
msg.prompts << SshPacketParser::asUserString(m_data, &offset);
msg.echos << SshPacketParser::asBool(m_data, &offset);
}
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_USERAUTH_INFO_REQUEST.");
}
}
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());
Q_ASSERT(type() == SSH_MSG_DEBUG);
try {
SshDebug msg;
quint32 offset = TypeOffset + 1;
msg.display = SshPacketParser::asBool(m_data, &offset);
msg.message = SshPacketParser::asUserString(m_data, &offset);
msg.language = SshPacketParser::asString(m_data, &offset);
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_DEBUG.");
}
}
SshRequestSuccess SshIncomingPacket::extractRequestSuccess() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_REQUEST_SUCCESS);
try {
SshRequestSuccess msg;
quint32 offset = TypeOffset + 1;
msg.bindPort = SshPacketParser::asUint32(m_data, &offset);
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_REQUEST_SUCCESS.");
}
}
SshUnimplemented SshIncomingPacket::extractUnimplemented() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_UNIMPLEMENTED);
try {
SshUnimplemented msg;
quint32 offset = TypeOffset + 1;
msg.invalidMsgSeqNr = SshPacketParser::asUint32(m_data, &offset);
return msg;
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_UNIMPLEMENTED.");
}
}
SshChannelOpenGeneric SshIncomingPacket::extractChannelOpen() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN);
try {
SshChannelOpenGeneric channelOpen;
quint32 offset = TypeOffset + 1;
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.");
}
}
SshChannelOpenFailure SshIncomingPacket::extractChannelOpenFailure() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_FAILURE);
SshChannelOpenFailure openFailure;
try {
quint32 offset = TypeOffset + 1;
openFailure.localChannel = SshPacketParser::asUint32(m_data, &offset);
openFailure.reasonCode = SshPacketParser::asUint32(m_data, &offset);
openFailure.reasonString = QString::fromLocal8Bit(SshPacketParser::asString(m_data, &offset));
openFailure.language = SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
}
return openFailure;
}
SshChannelOpenConfirmation SshIncomingPacket::extractChannelOpenConfirmation() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
SshChannelOpenConfirmation confirmation;
try {
quint32 offset = TypeOffset + 1;
confirmation.localChannel = SshPacketParser::asUint32(m_data, &offset);
confirmation.remoteChannel = SshPacketParser::asUint32(m_data, &offset);
confirmation.remoteWindowSize = SshPacketParser::asUint32(m_data, &offset);
confirmation.remoteMaxPacketSize = SshPacketParser::asUint32(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet.");
}
return confirmation;
}
SshChannelWindowAdjust SshIncomingPacket::extractWindowAdjust() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_WINDOW_ADJUST);
SshChannelWindowAdjust adjust;
try {
quint32 offset = TypeOffset + 1;
adjust.localChannel = SshPacketParser::asUint32(m_data, &offset);
adjust.bytesToAdd = SshPacketParser::asUint32(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_CHANNEL_WINDOW_ADJUST packet.");
}
return adjust;
}
SshChannelData SshIncomingPacket::extractChannelData() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_DATA);
SshChannelData data;
try {
quint32 offset = TypeOffset + 1;
data.localChannel = SshPacketParser::asUint32(m_data, &offset);
data.data = SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_CHANNEL_DATA packet.");
}
return data;
}
SshChannelExtendedData SshIncomingPacket::extractChannelExtendedData() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_EXTENDED_DATA);
SshChannelExtendedData data;
try {
quint32 offset = TypeOffset + 1;
data.localChannel = SshPacketParser::asUint32(m_data, &offset);
data.type = SshPacketParser::asUint32(m_data, &offset);
data.data = SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_CHANNEL_EXTENDED_DATA packet.");
}
return data;
}
SshChannelExitStatus SshIncomingPacket::extractChannelExitStatus() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
SshChannelExitStatus exitStatus;
try {
quint32 offset = TypeOffset + 1;
exitStatus.localChannel = SshPacketParser::asUint32(m_data, &offset);
const QByteArray &type = SshPacketParser::asString(m_data, &offset);
Q_ASSERT(type == ExitStatusType);
Q_UNUSED(type);
if (SshPacketParser::asBool(m_data, &offset))
throw SshPacketParseException();
exitStatus.exitStatus = SshPacketParser::asUint32(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid exit-status packet.");
}
return exitStatus;
}
SshChannelExitSignal SshIncomingPacket::extractChannelExitSignal() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
SshChannelExitSignal exitSignal;
try {
quint32 offset = TypeOffset + 1;
exitSignal.localChannel = SshPacketParser::asUint32(m_data, &offset);
const QByteArray &type = SshPacketParser::asString(m_data, &offset);
Q_ASSERT(type == ExitSignalType);
Q_UNUSED(type);
if (SshPacketParser::asBool(m_data, &offset))
throw SshPacketParseException();
exitSignal.signal = SshPacketParser::asString(m_data, &offset);
exitSignal.coreDumped = SshPacketParser::asBool(m_data, &offset);
exitSignal.error = SshPacketParser::asUserString(m_data, &offset);
exitSignal.language = SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid exit-signal packet.");
}
return exitSignal;
}
quint32 SshIncomingPacket::extractRecipientChannel() const
{
Q_ASSERT(isComplete());
try {
quint32 offset = TypeOffset + 1;
return SshPacketParser::asUint32(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Server sent invalid packet.");
}
}
QByteArray SshIncomingPacket::extractChannelRequestType() const
{
Q_ASSERT(isComplete());
Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);
try {
quint32 offset = TypeOffset + 1;
SshPacketParser::asUint32(m_data, &offset);
return SshPacketParser::asString(m_data, &offset);
} catch (const SshPacketParseException &) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
"Invalid SSH_MSG_CHANNEL_REQUEST packet.");
}
}
void SshIncomingPacket::calculateLength() const
{
Q_ASSERT(currentDataSize() >= minPacketSize());
qCDebug(sshLog, "Length field before decryption: %d-%d-%d-%d", m_data.at(0) & 0xff,
m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff);
m_decrypter.decrypt(m_data, 0, cipherBlockSize());
qCDebug(sshLog, "Length field after decryption: %d-%d-%d-%d", m_data.at(0) & 0xff, m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff);
qCDebug(sshLog, "message type = %d", m_data.at(TypeOffset));
m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
qCDebug(sshLog, "decrypted length is %u", m_length);
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,252 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHINCOMINGPACKET_P_H
#define SSHINCOMINGPACKET_P_H
#include "sshpacket_p.h"
#include "sshcryptofacility_p.h"
#include "sshpacketparser_p.h"
#include <QStringList>
namespace QSsh {
namespace Internal {
class SshKeyExchange;
struct SshKeyExchangeInit
{
char cookie[16];
SshNameList keyAlgorithms;
SshNameList serverHostKeyAlgorithms;
SshNameList encryptionAlgorithmsClientToServer;
SshNameList encryptionAlgorithmsServerToClient;
SshNameList macAlgorithmsClientToServer;
SshNameList macAlgorithmsServerToClient;
SshNameList compressionAlgorithmsClientToServer;
SshNameList compressionAlgorithmsServerToClient;
SshNameList languagesClientToServer;
SshNameList languagesServerToClient;
bool firstKexPacketFollows;
};
struct SshKeyExchangeReply
{
QByteArray k_s;
QList<Botan::BigInt> hostKeyParameters; // DSS: p, q, g, y. RSA: e, n.
QByteArray q; // For ECDSA host keys only.
Botan::BigInt f; // For DH only.
QByteArray q_s; // For ECDH only.
QByteArray signatureBlob;
};
struct SshDisconnect
{
quint32 reasonCode;
QString description;
QByteArray language;
};
struct SshUserAuthBanner
{
QString message;
QByteArray language;
};
struct SshUserAuthPkOkPacket
{
QByteArray algoName;
QByteArray keyBlob;
};
struct SshUserAuthInfoRequestPacket
{
QString name;
QString instruction;
QByteArray languageTag;
QStringList prompts;
QList<bool> echos;
};
struct SshDebug
{
bool display;
QString message;
QByteArray language;
};
struct SshUnimplemented
{
quint32 invalidMsgSeqNr;
};
struct SshRequestSuccess
{
quint32 bindPort;
};
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
{
quint32 localChannel;
quint32 reasonCode;
QString reasonString;
QByteArray language;
};
struct SshChannelOpenConfirmation
{
quint32 localChannel;
quint32 remoteChannel;
quint32 remoteWindowSize;
quint32 remoteMaxPacketSize;
};
struct SshChannelWindowAdjust
{
quint32 localChannel;
quint32 bytesToAdd;
};
struct SshChannelData
{
quint32 localChannel;
QByteArray data;
};
struct SshChannelExtendedData
{
quint32 localChannel;
quint32 type;
QByteArray data;
};
struct SshChannelExitStatus
{
quint32 localChannel;
quint32 exitStatus;
};
struct SshChannelExitSignal
{
quint32 localChannel;
QByteArray signal;
bool coreDumped;
QString error;
QByteArray language;
};
class SshIncomingPacket : public AbstractSshPacket
{
public:
SshIncomingPacket();
void consumeData(QByteArray &data);
void recreateKeys(const SshKeyExchange &keyExchange);
void reset();
SshKeyExchangeInit extractKeyExchangeInitData() const;
SshKeyExchangeReply extractKeyExchangeReply(const QByteArray &kexAlgo,
const QByteArray &hostKeyAlgo) const;
SshDisconnect extractDisconnect() const;
SshUserAuthBanner extractUserAuthBanner() const;
SshUserAuthInfoRequestPacket extractUserAuthInfoRequest() const;
SshUserAuthPkOkPacket extractUserAuthPkOk() const;
SshDebug extractDebug() const;
SshRequestSuccess extractRequestSuccess() const;
SshUnimplemented extractUnimplemented() 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;
SshChannelData extractChannelData() const;
SshChannelExtendedData extractChannelExtendedData() const;
SshChannelExitStatus extractChannelExitStatus() const;
SshChannelExitSignal extractChannelExitSignal() const;
quint32 extractRecipientChannel() const;
QByteArray extractChannelRequestType() const;
quint32 serverSeqNr() const { return m_serverSeqNr; }
static const QByteArray ExitStatusType;
static const QByteArray ExitSignalType;
static const QByteArray ForwardedTcpIpType;
private:
virtual quint32 cipherBlockSize() const;
virtual quint32 macLength() const;
virtual void calculateLength() const;
void decrypt();
void moveFirstBytes(QByteArray &target, QByteArray &source, int n);
quint32 m_serverSeqNr;
SshDecryptionFacility m_decrypter;
};
} // namespace Internal
} // namespace QSsh
#endif // SSHINCOMINGPACKET_P_H

View File

@@ -1,292 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 "sshsendfacility_p.h"
#include "sshexception_p.h"
#include "sshincomingpacket_p.h"
#include "sshlogging_p.h"
#include <botan_all.h>
#ifdef CREATOR_SSH_DEBUG
#include <iostream>
#endif
#include <string>
using namespace Botan;
namespace QSsh {
namespace Internal {
namespace {
// For debugging
void printNameList(const char *listName, const SshNameList &list)
{
qCDebug(sshLog, "%s:", listName);
foreach (const QByteArray &name, list.names)
qCDebug(sshLog, "%s", name.constData());
}
void printData(const char *name, const QByteArray &data)
{
qCDebug(sshLog, "The client thinks the %s has length %d and is: %s", name, data.count(),
data.toHex().constData());
}
} // anonymous namespace
SshKeyExchange::SshKeyExchange(const SshConnectionParameters &connParams,
SshSendFacility &sendFacility)
: m_connParams(connParams), m_sendFacility(sendFacility)
{
}
SshKeyExchange::~SshKeyExchange() {}
void SshKeyExchange::sendKexInitPacket(const QByteArray &serverId)
{
m_serverId = serverId;
m_clientKexInitPayload = m_sendFacility.sendKeyExchangeInitPacket();
}
bool SshKeyExchange::sendDhInitPacket(const SshIncomingPacket &serverKexInit)
{
qCDebug(sshLog, "server requests key exchange");
serverKexInit.printRawBytes();
SshKeyExchangeInit kexInitParams
= serverKexInit.extractKeyExchangeInitData();
printNameList("Key Algorithms", kexInitParams.keyAlgorithms);
printNameList("Server Host Key Algorithms", kexInitParams.serverHostKeyAlgorithms);
printNameList("Encryption algorithms client to server", kexInitParams.encryptionAlgorithmsClientToServer);
printNameList("Encryption algorithms server to client", kexInitParams.encryptionAlgorithmsServerToClient);
printNameList("MAC algorithms client to server", kexInitParams.macAlgorithmsClientToServer);
printNameList("MAC algorithms server to client", kexInitParams.macAlgorithmsServerToClient);
printNameList("Compression algorithms client to server", kexInitParams.compressionAlgorithmsClientToServer);
printNameList("Compression algorithms client to server", kexInitParams.compressionAlgorithmsClientToServer);
printNameList("Languages client to server", kexInitParams.languagesClientToServer);
printNameList("Languages server to client", kexInitParams.languagesServerToClient);
qCDebug(sshLog, "First packet follows: %d", kexInitParams.firstKexPacketFollows);
m_kexAlgoName = SshCapabilities::findBestMatch(SshCapabilities::KeyExchangeMethods,
kexInitParams.keyAlgorithms.names,
"KeyExchange");
m_serverHostKeyAlgo = SshCapabilities::findBestMatch(SshCapabilities::PublicKeyAlgorithms,
kexInitParams.serverHostKeyAlgorithms.names, "HostKey");
determineHashingAlgorithm(kexInitParams, true);
determineHashingAlgorithm(kexInitParams, false);
m_encryptionAlgo
= SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
kexInitParams.encryptionAlgorithmsClientToServer.names, "Encryption");
m_decryptionAlgo
= SshCapabilities::findBestMatch(SshCapabilities::EncryptionAlgorithms,
kexInitParams.encryptionAlgorithmsServerToClient.names, "Decryption");
SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
kexInitParams.compressionAlgorithmsClientToServer.names, "Compression Client to Server");
SshCapabilities::findBestMatch(SshCapabilities::CompressionAlgorithms,
kexInitParams.compressionAlgorithmsServerToClient.names, "Compression Server to Client");
AutoSeeded_RNG rng;
if (m_kexAlgoName.startsWith(SshCapabilities::EcdhKexNamePrefix)) {
m_ecdhKey.reset(new ECDH_PrivateKey(rng, EC_Group(botanKeyExchangeAlgoName(m_kexAlgoName))));
m_sendFacility.sendKeyEcdhInitPacket(convertByteArray(m_ecdhKey->public_value()));
} else {
m_dhKey.reset(new DH_PrivateKey(rng, DL_Group(botanKeyExchangeAlgoName(m_kexAlgoName))));
m_sendFacility.sendKeyDhInitPacket(m_dhKey->get_y());
}
m_serverKexInitPayload = serverKexInit.payLoad();
return kexInitParams.firstKexPacketFollows;
}
void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
const QByteArray &clientId)
{
const SshKeyExchangeReply &reply
= dhReply.extractKeyExchangeReply(m_kexAlgoName, m_serverHostKeyAlgo);
if (m_dhKey && (reply.f <= 0 || reply.f >= m_dhKey->group_p())) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Server sent invalid f.");
}
QByteArray concatenatedData = AbstractSshPacket::encodeString(clientId);
concatenatedData += AbstractSshPacket::encodeString(m_serverId);
concatenatedData += AbstractSshPacket::encodeString(m_clientKexInitPayload);
concatenatedData += AbstractSshPacket::encodeString(m_serverKexInitPayload);
concatenatedData += reply.k_s;
printData("Client Id", AbstractSshPacket::encodeString(clientId));
printData("Server Id", AbstractSshPacket::encodeString(m_serverId));
printData("Client Payload", AbstractSshPacket::encodeString(m_clientKexInitPayload));
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);
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();
} else {
Q_ASSERT(m_ecdhKey);
concatenatedData // Q_C.
+= AbstractSshPacket::encodeString(convertByteArray(m_ecdhKey->public_value()));
concatenatedData += AbstractSshPacket::encodeString(reply.q_s);
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();
}
// 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 = 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;
if (m_serverHostKeyAlgo == SshCapabilities::PubKeyDss) {
const DL_Group group(reply.hostKeyParameters.at(0), reply.hostKeyParameters.at(1),
reply.hostKeyParameters.at(2));
DSA_PublicKey * const dsaKey
= new DSA_PublicKey(group, reply.hostKeyParameters.at(3));
sigKey.reset(dsaKey);
} else if (m_serverHostKeyAlgo == SshCapabilities::PubKeyRsa) {
RSA_PublicKey * const rsaKey
= new RSA_PublicKey(reply.hostKeyParameters.at(1), reply.hostKeyParameters.at(0));
sigKey.reset(rsaKey);
} else {
QSSH_ASSERT_AND_RETURN(m_serverHostKeyAlgo.startsWith(SshCapabilities::PubKeyEcdsaPrefix));
const EC_Group domain(SshCapabilities::oid(m_serverHostKeyAlgo));
const PointGFp point = domain.OS2ECP(convertByteArray(reply.q), reply.q.count());
ECDSA_PublicKey * const ecdsaKey = new ECDSA_PublicKey(domain, point);
sigKey.reset(ecdsaKey);
}
const byte * const botanH = convertByteArray(m_h);
const Botan::byte * const botanSig = convertByteArray(reply.signatureBlob);
PK_Verifier verifier(*sigKey, botanEmsaAlgoName(m_serverHostKeyAlgo));
if (!verifier.verify_message(botanH, m_h.size(), botanSig, reply.signatureBlob.size())) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Invalid signature in key exchange reply packet.");
}
checkHostKey(reply.k_s);
m_sendFacility.sendNewKeysPacket();
m_hostFingerprint = QByteArray::fromStdString(sigKey->fingerprint_public("SHA-256"));
}
QByteArray SshKeyExchange::hashAlgoForKexAlgo() const
{
if (m_kexAlgoName == SshCapabilities::EcdhNistp256)
return SshCapabilities::HMacSha256;
if (m_kexAlgoName == SshCapabilities::EcdhNistp384)
return SshCapabilities::HMacSha384;
if (m_kexAlgoName == SshCapabilities::EcdhNistp521)
return SshCapabilities::HMacSha512;
return SshCapabilities::HMacSha1;
}
void SshKeyExchange::determineHashingAlgorithm(const SshKeyExchangeInit &kexInit,
bool serverToClient)
{
QByteArray * const algo = serverToClient ? &m_s2cHMacAlgo : &m_c2sHMacAlgo;
const QList<QByteArray> &serverCapabilities = serverToClient
? kexInit.macAlgorithmsServerToClient.names
: kexInit.macAlgorithmsClientToServer.names;
*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);
return;
}
if (!m_connParams.hostKeyDatabase) {
throw SshClientException(SshInternalError,
SSH_TR("Host key database must exist "
"if host key checking is enabled."));
}
switch (m_connParams.hostKeyDatabase->matchHostKey(m_connParams.host(), hostKey)) {
case SshHostKeyDatabase::KeyLookupMatch:
return; // Nothing to do.
case SshHostKeyDatabase::KeyLookupMismatch:
if (m_connParams.hostKeyCheckingMode != SshHostKeyCheckingAllowMismatch)
throwHostKeyException();
break;
case SshHostKeyDatabase::KeyLookupNoMatch:
if (m_connParams.hostKeyCheckingMode == SshHostKeyCheckingStrict)
throwHostKeyException();
break;
}
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()));
}
} // namespace Internal
} // namespace QSsh

View File

@@ -1,105 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** 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 SSHKEYEXCHANGE_P_H
#define SSHKEYEXCHANGE_P_H
#include "sshconnection.h"
#include <QByteArray>
#include <QScopedPointer>
#include <memory>
namespace Botan {
class DH_PrivateKey;
class ECDH_PrivateKey;
class HashFunction;
}
namespace QSsh {
namespace Internal {
struct SshKeyExchangeInit;
class SshSendFacility;
class SshIncomingPacket;
class SshKeyExchange
{
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.
bool sendDhInitPacket(const SshIncomingPacket &serverKexInit);
void sendNewKeysPacket(const SshIncomingPacket &dhReply,
const QByteArray &clientId);
QByteArray k() const { return m_k; }
QByteArray h() const { return m_h; }
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; }
QByteArray hMacAlgoServerToClient() const { return m_s2cHMacAlgo; }
private:
QByteArray hashAlgoForKexAlgo() const;
void determineHashingAlgorithm(const SshKeyExchangeInit &kexInit, bool serverToClient);
void checkHostKey(const QByteArray &hostKey);
Q_NORETURN void throwHostKeyException();
QByteArray m_serverId;
QByteArray m_clientKexInitPayload;
QByteArray m_serverKexInitPayload;
QScopedPointer<Botan::DH_PrivateKey> m_dhKey;
QScopedPointer<Botan::ECDH_PrivateKey> m_ecdhKey;
QByteArray m_kexAlgoName;
QByteArray m_k;
QByteArray m_h;
QByteArray m_serverHostKeyAlgo;
QByteArray m_encryptionAlgo;
QByteArray m_decryptionAlgo;
QByteArray m_c2sHMacAlgo;
QByteArray m_s2cHMacAlgo;
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

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