Compare commits

..

249 Commits
1.0 ... 2.0

Author SHA1 Message Date
pokamest
ddca4f9068 Software verion 2.0.0
Билд выпущен при поддержке Теплицы социальных технологий
2021-09-24 14:01:53 +03:00
pokamest
b244158b95 website in tor network container improved
Sponsored by "Теплица социальных технологий", 2021
В рамках работы над задачами по хакатону 2021
2021-09-24 13:14:35 +03:00
pokamest
3bcc12869b Поддержка протокола Sftp (File Sharing) по ТЗ по гранту от Теплицы
социальных технологий (2021 год)
+ небольшой рефакторинг
2021-09-22 14:49:08 +03:00
pokamest
6ee203a21d Merge branch 'tor_site_container' into teplitsa_tz
Containers page refactoring
2021-09-21 01:49:28 +03:00
pokamest
157d7c4f23 Various types containers support 2021-09-20 21:51:28 +03:00
pokamest
0d9f1ba95b qml ui fixes 2021-09-19 14:31:38 +03:00
pokamest
a390f2e988 Qml Containers Page refact 2021-09-16 19:49:50 +03:00
pokamest
0faf6c8599 QML ServerContainers page refact 2021-09-16 16:19:14 +03:00
pokamest
9ae2e3fba2 ios fixes 2021-09-15 08:03:28 -07:00
pokamest
12b079df65 qml refactoring 2021-09-14 00:39:07 +03:00
pokamest
e920d9cdf3 esc and back button support 2021-09-13 17:36:48 +03:00
Pokamest Nikak
542f363e92 ServerContainers qml ui started to fix 2021-09-10 22:19:00 +03:00
Pokamest Nikak
40fa2d6779 NewServerSettings qml rework 2021-09-09 20:15:44 +03:00
Pokamest Nikak
3175bc1e48 QML Fixes 2021-09-08 21:24:09 +03:00
Pokamest Nikak
62262a3572 BackButton.qml added 2021-09-08 15:09:16 +03:00
Pokamest Nikak
6516a84986 refact fixes 2021-09-08 14:23:02 +03:00
Pokamest Nikak
16e887dcf0 AUTO_PROPERTY finished 2021-09-08 13:52:36 +03:00
Pokamest Nikak
63ffa4a212 AUTO_PROPERTY added 2021-09-07 22:11:43 +03:00
Pokamest Nikak
539bf2ee24 VpnLogic 2021-09-07 21:01:56 +03:00
Pokamest Nikak
deaeda59d0 ServerContainersLogic 2021-09-07 19:26:58 +03:00
Pokamest Nikak
4c0ff29488 NewServerConfiguringLogic
NewServerProtocolsLogic
2021-09-07 18:06:05 +03:00
pokamest
7c28fe2795 NewServerConfiguringLogic
NewServerProtocolsLogic
2021-09-07 11:48:25 +03:00
pokamest
deda2e158e ShadowSocksLogic
CloakLogic
2021-09-06 14:35:57 +03:00
pokamest
a6e5cfff8a OpenVpnLogic added 2021-09-06 13:41:45 +03:00
pokamest
d1ea625435 codestyle fixes 2021-09-06 12:39:46 +03:00
pokamest
ea551ab0a0 qml ui protocols separated 2021-09-06 12:30:26 +03:00
pokamest
d9ae10f5bc qml ui fixes 2021-09-06 12:29:56 +03:00
pokamest
d90211ef48 Wizard Logic added
TODO_REFACTs fixed
2021-09-06 11:44:03 +03:00
Pokamest Nikak
ace304914e share page refact 2 2021-09-04 15:21:36 +03:00
Pokamest Nikak
6dc13b2c00 start page refact 2021-09-04 12:53:58 +03:00
Pokamest Nikak
ca3617aa7d refact sharing 2021-09-04 11:26:16 +03:00
Pokamest Nikak
84ca7e8879 refact 2 2021-09-03 22:15:05 +03:00
Pokamest Nikak
135b96a280 QML gui refact started 2021-09-03 20:17:13 +03:00
pokamest
febf9cfafb Merge branch 'dev' into gui_qml 2021-08-19 01:51:02 +03:00
pokamest
27171ed974 qml ui fixes 2021-08-19 01:27:22 +03:00
pokamest
2c346fdc08 Merge pull request #33 from amnezia-vpn/Linux_fix_dirs_rsa_2
Linux bug fixes
2021-08-17 14:25:23 +03:00
leetthewire
229265cdd9 updated 2021-08-15 11:48:31 -07:00
pokamest
57234bc793 qml ui fixes 2021-08-13 18:40:03 +03:00
pokamest
d496d0cccd Botan linux fix 2021-08-13 07:04:11 -07:00
Ngoc Diep
c687bb39ef fix PageSites table error 2021-08-09 01:34:25 +07:00
Ngoc Diep
d1a3545912 port UI Logic to QML 2021-08-09 00:41:52 +07:00
pokamest
accdedfead botan build fix 2021-08-08 18:34:05 +03:00
pokamest
bedf669ca4 Botan switched to amalgamation build 2021-08-08 18:10:09 +03:00
pokamest
a9dc1b0603 Merge pull request #31 from amnezia-vpn/Linux_build_stable_2
updated linux build
2021-08-06 17:45:49 +03:00
leetthewire
9997fa8f3e updated linux build 2021-08-04 10:08:00 -07:00
pokamest
26524dd93a Merge pull request #29 from amnezia-vpn/update_botan_3
Update botan (final)
2021-08-03 17:34:26 +03:00
pokamest
bd586a1921 Botan for MacOS added 2021-08-03 07:32:04 -07:00
pokamest
dec04ccd06 Add botan for linux static lib 2021-08-03 06:36:03 -07:00
pokamest
64d4e96068 Add botan for linux 2021-08-03 06:34:37 -07:00
pokamest
6d83e16aa7 Android build config added 2021-08-01 19:57:04 +03:00
Ngoc Diep
8d36c31cb4 implement qml UI 2021-07-28 16:13:29 +07:00
pokamest
a49db653a1 botan.pri fix 2021-07-27 13:35:10 +03:00
pokamest
cd7884b508 Botan deploy fix (Windows x64) 2021-07-27 13:23:18 +03:00
pokamest
5bf2c1d6e1 Botan updated
QtSsh updated to https://github.com/sandsmark/QSsh
2021-07-27 09:33:49 +03:00
pokamest
08b2824ff0 tor site 2021-07-23 12:42:08 +03:00
pokamest
1baf36282e win32 deploy fix 2021-06-27 13:26:06 +03:00
pokamest
e45c7507f9 Merge pull request #22 from amnezia-vpn/linux_ui_fix
fixed UI for linux
2021-06-26 20:49:48 +03:00
leetthewire
148b1dacce fixed UI for linux
Signed-off-by: leetthewire <yaartjom@mail.ru>
2021-06-26 23:09:48 +00:00
leetthewire
d17906c2a6 Service: Fixed bug with permanent addresses on interface (#20)
Windows Service: Fixed bug with permanent addresses on interface
2021-06-19 16:41:16 +03:00
pokamest
b1f7baa79f Various bug fixes 2021-06-19 16:38:35 +03:00
pokamest
973cbd83d9 Update README.md 2021-06-18 23:19:44 +03:00
pokamest
a599ed6e24 Update README.md 2021-06-18 23:19:07 +03:00
pokamest
a1cbf8824f Readme fix 2021-06-18 19:18:50 +03:00
pokamest
52450ef2f5 Release 1.8 2021-06-17 01:04:09 +03:00
pokamest
69170940c9 Merge pull request #19 from amnezia-vpn/cloak_ss_2
ShadowSocks over cloak
2021-06-17 00:53:48 +03:00
pokamest
e89caaee52 bump version 1.7.6 2021-06-17 00:51:15 +03:00
pokamest
0b3535ff13 hide wireguard settings 2021-06-16 22:40:34 +03:00
pokamest
e7a22ad159 Export shadowsocks over cloak config support 2021-06-16 22:25:08 +03:00
pokamest
74a517d985 Windows server 2012 support 2021-06-16 22:24:33 +03:00
pokamest
d57e56de70 Setup container more debugging 2021-06-16 22:24:13 +03:00
pokamest
e2f8f77adf Revert "Added threads suspend, Edited suspendWcmSvc() func for Windows. Based on old SuspendProcess func."
This reverts commit 999087337e.
2021-06-16 20:09:49 +03:00
pokamest
db543b62ba Macos build fix 2021-06-14 03:48:46 -07:00
Sike
999087337e Added threads suspend, Edited suspendWcmSvc() func for Windows. Based on old SuspendProcess func. 2021-06-14 02:34:21 +06:00
pokamest
6788f0b7eb Wireguard deploy files 2021-06-12 12:02:46 +03:00
pokamest
2f6fb0d557 Wireguard protocol + refactoring 2021-06-12 11:59:36 +03:00
pokamest
8bdfe1741a Win Routes fix 2021-06-10 17:58:28 +03:00
pokamest
739781ece3 Saving files before refreshing line endings 2021-06-06 17:27:58 +03:00
pokamest
7e74b95976 Readme updated 2021-06-06 16:25:22 +03:00
pokamest
531695bd0b Windows x32 deploy files added 2021-06-06 16:18:01 +03:00
pokamest
dd959e7b26 Custom routing fixes 2021-06-05 20:55:57 +03:00
pokamest
c4235a60c8 Macos fixes 2021-06-05 01:18:28 -07:00
pokamest
f75456060f build fix 2021-06-03 10:42:58 -07:00
pokamest
623aae3718 Macos build fix 2021-06-03 10:34:28 -07:00
pokamest
974832f7d9 Tiny fix 2021-06-03 20:27:46 +03:00
pokamest
d13df65bfb Tiny fixes 2021-06-03 20:23:44 +03:00
pokamest
80ada3f241 Travis fix 2021-06-03 00:29:51 +03:00
pokamest
aad3677d45 Travis fix 2021-06-02 22:34:29 +03:00
pokamest
8892d3c5d9 Travis fix 2021-06-02 21:35:44 +03:00
pokamest
da08bef2f9 Travis fix 2021-06-02 20:46:59 +03:00
pokamest
d79483e967 Travis fix 2021-06-02 20:25:00 +03:00
pokamest
906391f786 Travis fix 2021-06-02 19:24:50 +03:00
pokamest
48a4aa399b Travis fix 2021-06-02 19:05:26 +03:00
pokamest
a8dd319a9d Travis fix 2021-06-02 18:54:39 +03:00
pokamest
815686cba6 Travis fix 2021-06-02 18:41:08 +03:00
pokamest
7232a14926 Travis fix 2021-06-02 17:56:01 +03:00
pokamest
dd526959eb easyrsa fix 2021-06-02 17:51:04 +03:00
pokamest
fe6f89c551 travis fix 2021-06-02 01:32:25 +03:00
pokamest
16c754e004 Disable openvpn log append 2021-06-02 00:54:47 +03:00
pokamest
8792a8673a gitignore fix 2021-06-02 00:53:44 +03:00
pokamest
9376df8703 deploy fixes 2021-06-02 00:49:42 +03:00
pokamest
435ee58d40 Macos fix: routes delete 2021-06-01 08:45:26 -07:00
pokamest
9dbe15a0e3 custom sitet pre release 2021-06-01 18:18:09 +03:00
pokamest
34b97bdc24 Macos fixes for route functions 2021-05-27 15:01:15 -07:00
pokamest
6c74f30d79 Custom sites reimplemented 2021-05-27 22:18:36 +03:00
pokamest
97e918ae72 ui fixes 2021-05-22 16:14:26 +03:00
pokamest
d0c66a693b macos deploy script fixes 2021-05-21 05:33:40 -07:00
pokamest
0ea085cc02 - Crash fix if service not connected
- import fix
- disabled share button for readonly server
2021-05-20 15:59:58 +03:00
pokamest
7fd13faa59 cloak stop() fixed 2021-05-19 00:26:36 +03:00
pokamest
d4c0e519d9 ui fixes 2021-05-19 00:15:40 +03:00
pokamest
4ba964db47 win7 support fixes
wizard added
2021-05-18 15:50:52 +03:00
pokamest
45e5ec76dd Windows 7 tap support improved 2021-05-14 23:30:13 +03:00
pokamest
df27003998 win build fix 2021-05-14 23:29:09 +03:00
pokamest
9002568474 Macos cached config fix 2021-05-14 04:27:30 -07:00
pokamest
5c5411261a macos dns setup fixed 2021-05-13 08:23:56 -07:00
pokamest
acf878c8dd Macos route add reimplemented using system call 2021-05-13 08:20:38 -07:00
pokamest
491a09b175 macos autostart fix 2021-05-12 13:07:22 -07:00
pokamest
51f7e6811e macos ui fix 2021-05-12 02:49:36 -07:00
pokamest
eee6b8b10f main.cpp default font removed 2021-05-11 12:15:33 -07:00
pokamest
dc4a1c6eca macos fix 2021-05-11 09:36:43 -07:00
pokamest
02810ff844 bug fixes 2021-05-11 17:04:04 +03:00
pokamest
1bb2ef9e30 ui fixes 2021-05-10 20:51:38 +03:00
pokamest
df2a6dc278 cloak for macos fixed 2021-05-10 05:25:20 -07:00
pokamest
835f767c3f import/export fixes 2021-05-10 14:19:36 +03:00
pokamest
e3fb239de9 Config export 2021-05-10 02:33:31 +03:00
pokamest
de67f244da Multiprotocol support 2021-05-07 23:28:37 +03:00
pokamest
d424bb24cf refactoring
Protocol to DockerContainer
2021-04-26 23:19:19 +03:00
pokamest
615bba69e5 refactoring 2021-04-26 22:54:31 +03:00
pokamest
7bba7a9eab cygwin grep added 2021-04-20 02:11:14 +03:00
pokamest
a5e9cea22f Release 1.6 WIP 2021-04-20 02:09:47 +03:00
pokamest
f9affb083b Macos route delete fix 2021-04-19 14:34:47 +03:00
pokamest
85b6b06cc9 - no dockerhub
- trafic masking
2021-04-04 23:12:36 +03:00
pokamest
059c6404ab gitignore updated 2021-04-04 23:09:31 +03:00
pokamest
0d989a7fae meta version updated 2021-04-04 23:08:01 +03:00
pokamest
7dfc002316 cloak exe added 2021-04-04 23:06:54 +03:00
pokamest
8d8d392e84 cygwin updated to x64 2021-04-04 23:04:31 +03:00
pokamest
c6e75d5f86 server script fixes 2021-03-25 23:26:59 +03:00
pokamest
99bfd56ef4 minor release 1.5.3 2021-03-19 15:03:44 +03:00
pokamest
c2f6c7d939 route delete fixed (Windows) 2021-03-18 22:13:05 +03:00
pokamest
d831d68e73 ShadowSocks protocol fixes:
- remote for OpenVPN is set to real ip address
- remote ip will be added as alias in docker container
- ss-local graceful shutdown
- crash fixes
2021-03-18 18:45:08 +03:00
pokamest
84e4b776ac openvpn target host is 10.8.0.1 via ss route 2021-03-17 03:47:33 +03:00
pokamest
f9e1b2c6dc QR code lib added
ShadowSocks export
ui stylesheet fixes
ip:port regexp fixed
dns settings reset bug fixed
2021-03-17 03:45:38 +03:00
pokamest
54fca5bebc cygpcre-1.dll added 2021-03-16 22:15:27 +03:00
pokamest
c5ce417d79 macos close button fix 2021-03-14 12:52:19 -07:00
pokamest
6765142ebc ssh key auth fix 2021-03-14 12:51:52 -07:00
pokamest
ca898a6759 Ssh key auth support added
yum/apt install support
2021-03-14 21:19:11 +03:00
pokamest
a2bb382652 ShadowSocks password - sha256 2021-03-13 14:16:24 +03:00
pokamest
02f966bc67 Win7 fix
Connection import fix
2021-03-13 13:56:52 +03:00
pokamest
65acdc8c09 readme added 2021-03-09 18:48:59 +03:00
pokamest
407ea77a9e ssh connection strict check disabled 2021-03-09 18:45:41 +03:00
pokamest
3e4a9f54a7 cygwin binaries added 2021-03-09 18:44:45 +03:00
pokamest
6b77bd5f13 Server install fix 2021-03-08 18:17:50 +03:00
pokamest
fb6de25e5f Migrate to cygwin sh 2021-03-06 15:07:43 +03:00
pokamest
ffbe5107e2 Secondary instance fix 2021-03-06 14:59:55 +03:00
pokamest
40a5b2e3f3 sites list ui fix 2021-02-25 23:11:46 +03:00
pokamest
c683884868 sites list reimplement 2021-02-25 21:16:00 +03:00
pokamest
65961d8d2e vpnconnection.cpp crash fix
ss server sript fix
2021-02-25 18:05:42 +03:00
pokamest
7dc1f1e225 Utils ip address regexp 2021-02-25 18:03:24 +03:00
pokamest
a47ab15aef mainwindow.ui fix 2021-02-25 01:06:02 +03:00
pokamest
c74efdaa9b ui fix for macos 2021-02-24 13:41:32 -08:00
pokamest
39224c7bf7 SingleApplication 2021-02-24 13:38:23 -08:00
pokamest
96aa3d409d SingleApplication 2021-02-24 23:40:57 +03:00
pokamest
c63990f720 Auto start
Auto connect
Dns settings
ui fixes
2021-02-24 21:58:32 +03:00
pokamest
ad643bf76e new icon 2021-02-22 18:07:39 +03:00
pokamest
c7ea4966fd minor fixes:
-build_windows.bat
-win build fix
-qdebug fix
2021-02-22 16:31:43 +03:00
pokamest
8fd81be477 ShadowSocks fixes for MacOS 2021-02-21 09:44:53 -08:00
pokamest
a1cb4ac544 Custom routing done
ShadowSocks enabled by default
2021-02-18 15:00:41 +03:00
pokamest
f91854594c Merge branch 'dev' into service_refact 2021-02-11 19:17:16 +03:00
pokamest
f661ea1d46 Merge branch 'macos_build_fix' into dev 2021-02-10 10:44:37 -08:00
pokamest
f50eea3eaf macos signing fixes 2021-02-10 06:57:26 -08:00
pokamest
c15b57e690 windows travis fix 2021-02-10 00:07:12 +03:00
pokamest
5f7ef31345 win cert updated 2021-02-09 00:33:26 +03:00
pokamest
447410a27a Macos build fix (#6)
macos deploy fixes
2021-02-08 23:57:35 +03:00
pokamest
2aa9f9cca9 macos build fix 2021-02-08 12:42:48 -08:00
pokamest
cba27d354d macos deploy fixes 2021-02-08 21:10:34 +03:00
pokamest
b398f42ada ipc process fix 2021-02-03 20:05:50 +03:00
pokamest
b6571d99de Qt ro refact 2021-02-03 15:42:36 +03:00
pokamest
b2392c1943 Qt Remote objects done 2021-02-02 22:51:31 +03:00
pokamest
048a673d31 Qt remote objects IPC 2021-02-02 01:47:40 +03:00
pokamest
c4df9c004b Merge branch 'dev' into service_refact 2021-01-30 15:03:01 +03:00
pokamest
b9d4c53eb6 travis macos fix 2021-01-28 14:18:28 +03:00
pokamest
5fdeea0581 travis fix 2021-01-28 13:26:43 +03:00
pokamest
e1cd764050 travis fix 2021-01-28 13:11:10 +03:00
pokamest
1e54379cc0 macos travis fix 2021-01-28 12:54:09 +03:00
pokamest
ba3f69d206 travis fix 2021-01-27 01:44:32 +03:00
pokamest
fcfd4181c7 merge fix 2021-01-27 01:32:36 +03:00
pokamest
ca05e64f35 travis fix 2021-01-27 01:18:09 +03:00
pokamest
0569c6411e Release 1.1 (#5)
* Crash fix in management server

* Openvpn scripts fixes
some refactoring

* deploy fix

* Scripts fix for macos

* OpenVpn runtime error codes handling

* MacOS deploy script fix

* easyrsa scripts for MacOS

* Refactoring
Ui improvements
Bug fixes

* new server page fix

* Fix some warnings, fix installation scripts (macOS)

* Fix crash on fatal error, remove moc files from Windows installation

* ss files

* Fix issue with easyrsa

* ss files

* shadowsocks impl

* ss fix

* ui fix

* Macos doc icon

* travis scripts

* server scripts fix

* icon changed

* Server scripts fix

* travis fix

* Bug fixes:
- auto install tap
- share connectionState
- service crash fix

* travis release

* macos deploy
2021-01-27 00:57:02 +03:00
pokamest
9f6ec6d3e2 Merge branch 'master' into gitfix 2021-01-27 00:50:55 +03:00
pokamest
2e50aae603 macos deploy 2021-01-26 22:15:49 +03:00
pokamest
5a16a07b57 travis release 2021-01-26 22:00:58 +03:00
pokamest
953eca6695 Bug fixes:
- auto install tap
- share connectionState
- service crash fix
2021-01-26 15:01:15 +03:00
pokamest
a50cdd5bc2 travis fix 2021-01-23 16:45:11 +03:00
pokamest
10eb65e545 travis fix 2021-01-23 16:28:06 +03:00
pokamest
5354344ba7 travis fix 2021-01-23 16:02:21 +03:00
pokamest
c000a93eef travis fix 2021-01-23 15:13:46 +03:00
pokamest
ef6bc5ae4a travis fix 2021-01-23 15:08:01 +03:00
pokamest
97c4564649 travis fix 2021-01-23 15:03:56 +03:00
pokamest
5bf31a8b50 travis fix 2021-01-23 01:09:27 +03:00
pokamest
18e0d7fb2c travis fix 2021-01-23 00:57:12 +03:00
pokamest
ac454d9d78 Server scripts fix 2021-01-22 16:06:43 +03:00
pokamest
806677510f icon changed 2021-01-21 19:16:10 +03:00
pokamest
68e0ba9923 server scripts fix 2021-01-21 19:14:07 +03:00
pokamest
22b33a4f25 remote_obj 2021-01-20 23:07:23 +03:00
pokamest
77f830acd5 travis fix 2021-01-19 09:48:50 +03:00
pokamest
eb3b090257 travis fix 2021-01-19 01:58:55 +03:00
pokamest
2e1c219093 travis fix 2021-01-19 01:54:42 +03:00
pokamest
e38f69caf0 travis fix 2021-01-19 01:54:27 +03:00
pokamest
795f286923 travis fix 2021-01-19 01:45:47 +03:00
pokamest
d62e5b51da travis fix 2021-01-19 01:44:17 +03:00
pokamest
96b267b1f7 travis fix 2021-01-19 01:31:59 +03:00
pokamest
568388367e travis fix 2021-01-19 01:18:23 +03:00
pokamest
5ca46edf33 travis fix 2021-01-19 01:15:05 +03:00
pokamest
af41abd346 travis fix 2021-01-19 01:09:41 +03:00
pokamest
5edb61641c travis fix 2021-01-19 00:27:35 +03:00
pokamest
af3b1caa87 travis fix 2021-01-18 22:30:32 +03:00
pokamest
cc4a7b32b0 travis fix 2021-01-18 22:07:31 +03:00
pokamest
dfd61f58d4 travis fix 2021-01-18 21:58:23 +03:00
pokamest
84a3c1f725 travis fix 2021-01-18 19:00:18 +03:00
pokamest
2419fa1a6e travis fix 2021-01-18 18:45:38 +03:00
pokamest
3b8ecd9e9d travis windows fix 2021-01-18 01:41:20 +03:00
pokamest
94ee4b76db travis fix 2021-01-18 01:18:22 +03:00
pokamest
d43a1cd753 travis fix 2021-01-18 01:14:04 +03:00
pokamest
8bc6852b39 travis fix 2021-01-17 16:27:33 +03:00
pokamest
3850be08f1 travis fix 2021-01-17 16:22:05 +03:00
pokamest
d72d1d56b1 travis fix 2021-01-17 16:15:52 +03:00
pokamest
2a4926843c travis fix 2021-01-17 14:14:26 +03:00
pokamest
1b357055a2 travis fix 2021-01-17 13:53:05 +03:00
pokamest
2d3d64e462 travis fix 2021-01-17 13:17:37 +03:00
pokamest
aa648d4e12 travis scripts 2021-01-17 13:11:39 +03:00
pokamest
bfa0ac4c34 Macos doc icon 2021-01-16 21:04:16 +03:00
pokamest
c37ddd83d5 ui fix 2021-01-16 15:08:27 +03:00
pokamest
96bbc1cdbc ss fix 2021-01-15 23:37:34 +03:00
pokamest
ec9ae0ef4f shadowsocks impl 2021-01-15 23:36:35 +03:00
pokamest
95cbb07cbb Merge branch 'dev' into ss/impl 2021-01-12 12:57:58 +03:00
pokamest
7b95d6a5fc ss files 2021-01-11 23:19:30 +03:00
driftingsun
bea19a9461 Fix issue with easyrsa 2021-01-11 16:41:17 +03:00
pokamest
ba686556d2 Merge branch 'dev' into ss/impl 2021-01-10 20:52:04 +03:00
pokamest
15dc6eaaf8 ss files 2021-01-10 20:37:57 +03:00
driftingsun
3369a387ce Fix crash on fatal error, remove moc files from Windows installation 2021-01-10 18:47:29 +03:00
michael
dd46d8cf99 Fix some warnings, fix installation scripts (macOS) 2021-01-10 16:50:38 +03:00
pokamest
0b8c8835c4 new server page fix 2021-01-09 20:05:16 +03:00
pokamest
441811e277 Refactoring
Ui improvements
Bug fixes
2021-01-09 19:55:16 +03:00
pokamest
3645735053 easyrsa scripts for MacOS 2021-01-08 18:10:52 +03:00
pokamest
416d597847 MacOS deploy script fix 2021-01-08 18:08:20 +03:00
pokamest
861c71e3a8 OpenVpn runtime error codes handling 2021-01-08 16:51:58 +03:00
pokamest
f45fb442de Scripts fix for macos 2021-01-08 15:43:45 +03:00
pokamest
82241701a9 deploy fix 2021-01-08 00:34:15 +03:00
pokamest
bfdbe27a8d Openvpn scripts fixes
some refactoring
2021-01-07 20:53:42 +03:00
pokamest
c7dafe9c00 Crash fix in management server 2021-01-07 19:10:24 +03:00
671 changed files with 1392397 additions and 71231 deletions

8
.gitignore vendored
View File

@@ -3,6 +3,11 @@
macOSPackage/
AmneziaVPN.dmg
AmneziaVPN.exe
AmneziaVPN_*.exe
deploy/build/*
deploy/build_32/*
deploy/build_64/*
winbuild*.bat
# Qt-es
/.qmake.cache
@@ -33,10 +38,9 @@ CMakeLists.txt.user*
.DS_Store
._.DS_Store
._*
*.dmg
# tmp files
*.*~
# Certificates
*.p12

144
.travis.yml Normal file
View File

@@ -0,0 +1,144 @@
language: cpp
branches:
only:
- master
- dev
- /\d+\.\d+/
jobs:
include:
- name: MacOS
os: osx
osx_image: xcode12.5
env:
- QT_VERSION=5.15.2
- QIF_VERSION=4.1
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
script:
- |
if [ ! -f $HOME/Qt/$QT_VERSION/clang_64/bin/qmake ]; then \
brew install p7zip && \
python3 -m pip install --upgrade pip && \
pip install -U aqtinstall requests py7zr && \
pip show aqtinstall && \
python3 -m aqt install --outputdir $HOME/Qt $QT_VERSION mac desktop clang_64 -m qtbase && \
python3 -m aqt tool --outputdir $HOME/Qt mac tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./};
fi
- bash deploy/build_macos.sh
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
file:
- "AmneziaVPN_unsigned.dmg"
on:
tags: true
branch: master
- name: Windows_x64
os: windows
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.14.2
- QIF_VERSION=4.1
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2017_64\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=64
before_install:
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then choco install python --version 3.9.1; fi
script:
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win64_msvc2017_64 -m qtbase && \
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
fi
- 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 \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
file:
- "AmneziaVPN_x64.exe"
on:
tags: true
branch: master
- name: Windows_x32
os: windows
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.14.2
- QIF_VERSION=4.1
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2017\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=32
before_install:
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then choco install python --version 3.9.1; fi
script:
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win32_msvc2017 -m qtbase && \
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
fi
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\"" > winbuild.bat
- 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 \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
file:
- "AmneziaVPN_x32.exe"
on:
tags: true
branch: master
deploy:
skip_cleanup: true
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
cache:
directories:
- $HOME/Qt
- /C/Qt
- $HOME/Library/Caches/Homebrew

View File

@@ -1,2 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = client service platform

View File

@@ -1,2 +1,50 @@
# Amnezia
# 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)
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.
## Tech
AmneziaVPN uses a number of open source projects to work:
- [OpenSSL](https://www.openssl.org/)
- [OpenVPN](https://openvpn.net/)
- [ShadowSocks](https://shadowsocks.org/)
- [Qt](https://www.qt.io/)
- [EasyRSA](https://github.com/OpenVPN/easy-rsa) - part of OpenVPN
- [CygWin](https://www.cygwin.com/) - only for Windiws, used for launching EasyRSA scripts
- [QtSsh](https://github.com/jaredtao/QtSsh) - forked form Qt Creator
- and more...
## Development
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.
## License
GPL v.3
## Contacts
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
[https://signal.group/...](https://signal.group/#CjQKIB2gUf8QH_IXnOJMGQWMDjYz9cNfmRQipGWLFiIgc4MwEhAKBONrSiWHvoUFbbD0xwdh) - Signal channel
[https://amnezia.org](https://amnezia.org) - project website
## Donate
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
payeer.com: P2561305
ko-fi.com: [https://ko-fi.com/amnezia_vpn](https://ko-fi.com/amnezia_vpn)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
#if !defined(AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_)
#define AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
//
#define QR_LEVEL_L 0
#define QR_LEVEL_M 1
#define QR_LEVEL_Q 2
#define QR_LEVEL_H 3
//
#define QR_MODE_NUMERAL 0
#define QR_MODE_ALPHABET 1
#define QR_MODE_8BIT 2
#define QR_MODE_KANJI 3
//
#define QR_VRESION_S 0
#define QR_VRESION_M 1
#define QR_VRESION_L 2
#define MAX_ALLCODEWORD 3706
#define MAX_DATACODEWORD 2956
#define MAX_CODEBLOCK 153
#define MAX_MODULESIZE 177
#define QR_MARGIN 0
/////////////////////////////////////////////////////////////////////////////
typedef struct tagRS_BLOCKINFO
{
int ncRSBlock;
int ncAllCodeWord;
int ncDataCodeWord;
} RS_BLOCKINFO, *LPRS_BLOCKINFO;
/////////////////////////////////////////////////////////////////////////////
typedef struct tagQR_VERSIONINFO
{
int nVersionNo;
int ncAllCodeWord;
int ncDataCodeWord[4];
int ncAlignPoint;
int nAlignPoint[6];
RS_BLOCKINFO RS_BlockInfo1[4];
RS_BLOCKINFO RS_BlockInfo2[4];
} QR_VERSIONINFO, *LPQR_VERSIONINFO;
/////////////////////////////////////////////////////////////////////////////
class CQR_Encode
{
public:
CQR_Encode();
~CQR_Encode();
public:
int m_nLevel;
int m_nVersion;
bool m_bAutoExtent;
int m_nMaskingNo;
public:
int m_nSymbleSize;
unsigned char m_byModuleData[MAX_MODULESIZE][MAX_MODULESIZE]; // [x][y]
private:
int m_ncDataCodeWordBit;
unsigned char m_byDataCodeWord[MAX_DATACODEWORD];
int m_ncDataBlock;
unsigned char m_byBlockMode[MAX_DATACODEWORD];
int m_nBlockLength[MAX_DATACODEWORD];
int m_ncAllCodeWord;
unsigned char m_byAllCodeWord[MAX_ALLCODEWORD];
unsigned char m_byRSWork[MAX_CODEBLOCK];
public:
bool EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, char* lpsSource, int ncSource = 0);
private:
int GetEncodeVersion(int nVersion, char* lpsSource, int ncLength);
bool EncodeSourceData(char* lpsSource, int ncLength, int nVerGroup);
int GetBitLength(unsigned char nMode, int ncData, int nVerGroup);
int SetBitStream(int nIndex, unsigned short wData, int ncData);
bool IsNumeralData(unsigned char c);
bool IsAlphabetData(unsigned char c);
bool IsKanjiData(unsigned char c1, unsigned char c2);
unsigned char AlphabetToBinaly(unsigned char c);
unsigned short KanjiToBinaly(unsigned short wc);
void GetRSCodeWord(unsigned char * lpbyRSWork, int ncDataCodeWord, int ncRSCodeWord);
private:
void FormatModule();
void SetFunctionModule();
void SetFinderPattern(int x, int y);
void SetAlignmentPattern(int x, int y);
void SetVersionPattern();
void SetCodeWordPattern();
void SetMaskingPattern(int nPatternNo);
void SetFormatInfoPattern(int nPatternNo);
int CountPenalty();
};
/////////////////////////////////////////////////////////////////////////////
#endif // !defined(AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_)

View File

@@ -0,0 +1,5 @@
HEADERS += \
3rd/QRCodeGenerator/QRCodeGenerator.h \
SOURCES += \
3rd/QRCodeGenerator/QRCodeGenerator.cpp \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,41 +1,66 @@
/****************************************************************************
/**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
** This file is part of Qt Creator
**
** This file is part of Qt Creator.
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** Contact: http://www.qt-project.org/
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/
#pragma once
#ifndef SSH_GLOBAL_H
#define SSH_GLOBAL_H
#include <QtGlobal>
#include <QObject>
//#if defined(QTCSSH_LIBRARY)
//# define QSSH_EXPORT Q_DECL_EXPORT
//#else
//# define QSSH_EXPORT Q_DECL_IMPORT
//#endif
#ifdef Q_OS_IOS
class QProcess {
public:
QProcess(QObject *){}
enum ProcessChannel {
StandardOutput,
StandardError
};
};
#endif
#define QSSH_EXPORT
#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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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