Compare commits

..

206 Commits
1.04 ... 1.06f

Author SHA1 Message Date
Philipp Crocoll
135d7ebda5 keep old keyboard dialog for Android <= 8, fix bugs with keyboard labels, release 1.06f 2018-09-10 09:51:53 +02:00
Philipp Crocoll
337297e3e0 manifest for 1.06d 2018-08-28 20:54:56 +02:00
Philipp Crocoll
26def9805f avoid potential OutOfBounds exception 2018-08-28 20:47:50 +02:00
Philipp Crocoll
5429876cde fix potential NullPointerExceptions 2018-08-28 05:39:28 +02:00
Philipp Crocoll
d13b2d236b manifest for 1.06c 2018-08-27 12:14:07 +02:00
Philipp Crocoll
9dce637d22 fix potential crash in FileSelectActivity 2018-08-27 12:06:04 +02:00
Philipp Crocoll
dbb291fb86 implement a new way to select additional fields in the keyboard, closes https://github.com/PhilippC/keepass2android/issues/377 2018-08-27 11:18:46 +02:00
Philipp Crocoll
bc2dc1b2e9 manifest for 1.06b 2018-08-23 07:01:36 +02:00
PhilippC
2d9429d688 Merge pull request #514 from PhilippC/l10n_master
New Crowdin translations
2018-08-21 20:35:40 +02:00
PhilippC
62f3ff1902 New translations strings.xml (German) 2018-08-21 20:32:04 +02:00
PhilippC
36735cdfbe New translations strings.xml (Chinese Traditional) 2018-08-21 20:31:51 +02:00
PhilippC
f57db90d7b New translations strings.xml (Portuguese, Brazilian) 2018-08-21 20:31:23 +02:00
Philipp Crocoll
97aec23384 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-08-21 20:27:59 +02:00
PhilippC
eb3bcf04ea Merge pull request #467 from PhilippC/l10n_master
New Crowdin translations
2018-08-21 20:27:13 +02:00
PhilippC
40626ba708 New translations strings.xml (Chinese Simplified) 2018-08-21 20:23:42 +02:00
PhilippC
882597365b New translations strings.xml (Portuguese) 2018-08-21 20:23:16 +02:00
PhilippC
6b456c2f57 New translations strings.xml (German) 2018-08-21 19:41:08 +02:00
PhilippC
515ae57e88 New translations strings.xml (French) 2018-08-21 19:41:04 +02:00
PhilippC
9cc9d6ab66 New translations strings.xml (Croatian) 2018-08-21 19:40:55 +02:00
PhilippC
40b4fd210a New translations strings.xml (Chinese Traditional) 2018-08-21 19:40:53 +02:00
PhilippC
2ce2d0efab New translations strings.xml (Portuguese, Brazilian) 2018-08-21 19:40:24 +02:00
PhilippC
97a863293d New translations strings.xml (Polish) 2018-08-21 19:40:20 +02:00
PhilippC
d45426a4c1 New translations strings.xml (Persian) 2018-08-21 19:40:17 +02:00
Philipp Crocoll
d5a49db782 Prevent users from accidentally opening the local backup, closes #479 2018-08-21 19:34:22 +02:00
Philipp Crocoll
4b393f412c avoid exception with new Keyboard dialog on some devices 2018-08-21 07:25:31 +02:00
Philipp Crocoll
8cc77fbe1d hide password input fields from accessibility services 2018-08-20 16:56:20 +02:00
PhilippC
673632bd92 Merge pull request #487 from mohammadnaseri/master
Password should be invisible to the accessibility services: fixed for entering online storage credentials
2018-08-20 16:47:08 +02:00
Philipp Crocoll
d2b9a5d1a9 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-08-20 16:45:34 +02:00
Philipp Crocoll
2bc46b0a0e fix a local build issue 2018-08-20 16:44:32 +02:00
Philipp Crocoll
74200daf90 finish transition to custom activity as dialog instead of using AlertDialog which is no longer working in Android P, closes #377 2018-08-20 16:44:23 +02:00
Philipp Crocoll
b89c127df4 try to introduce an activity as dialog for string selection, not yet working 2018-08-20 15:44:22 +02:00
Philipp Crocoll
67bbbb2097 handle empty initialPath in sftp dialog to close #499 2018-08-18 06:08:08 +02:00
PhilippC
c6ddf0de87 New translations strings.xml (Vietnamese) 2018-08-16 19:10:06 +02:00
Philipp Crocoll
0ef73952b1 fix crash when no FingerprintManager is available, fixes #474 2018-08-15 04:47:38 +02:00
PhilippC
0e02a3aeee New translations strings.xml (Croatian) 2018-08-12 16:00:05 +02:00
Mohammad Naseri
1558a7c386 Password should be invisible to the accessibility services 2018-08-03 12:38:48 +02:00
PhilippC
b72becd328 New translations strings.xml (Swedish) 2018-08-03 11:40:06 +02:00
PhilippC
df2ac8e203 New translations strings.xml (Portuguese) 2018-07-26 12:00:09 +02:00
PhilippC
c6c230002c New translations strings.xml (Portuguese) 2018-07-26 11:50:06 +02:00
PhilippC
885503b5fa New translations strings.xml (Persian) 2018-07-24 21:10:10 +02:00
PhilippC
40fd91257e New translations strings.xml (Vietnamese) 2018-07-23 13:40:11 +02:00
PhilippC
02ece3cf41 New translations strings.xml (Chinese Simplified) 2018-07-23 13:40:08 +02:00
PhilippC
901c879647 New translations strings.xml (Catalan) 2018-07-23 13:40:05 +02:00
PhilippC
990a73f4a4 New translations strings.xml (Chinese Traditional) 2018-07-23 13:31:16 +02:00
PhilippC
73169d339d New translations strings.xml (Croatian) 2018-07-23 13:31:14 +02:00
PhilippC
265b86c031 New translations strings.xml (Czech) 2018-07-23 13:31:11 +02:00
PhilippC
7c29c23015 New translations strings.xml (Danish) 2018-07-23 13:31:08 +02:00
PhilippC
538e579477 New translations strings.xml (Dutch) 2018-07-23 13:31:06 +02:00
PhilippC
73db5f55e2 New translations strings.xml (Finnish) 2018-07-23 13:31:02 +02:00
PhilippC
31a9980343 New translations strings.xml (French) 2018-07-23 13:31:00 +02:00
PhilippC
02c50f510f New translations strings.xml (Galician) 2018-07-23 13:30:57 +02:00
PhilippC
3541ee0512 New translations strings.xml (German) 2018-07-23 13:30:54 +02:00
PhilippC
e72821ba1e New translations strings.xml (Greek) 2018-07-23 13:30:51 +02:00
PhilippC
3af00871a5 New translations strings.xml (Hebrew) 2018-07-23 13:30:48 +02:00
PhilippC
22fe4ca790 New translations strings.xml (Bulgarian) 2018-07-23 13:30:46 +02:00
PhilippC
72d0570c15 New translations strings.xml (Hungarian) 2018-07-23 13:30:43 +02:00
PhilippC
62e0cc0867 New translations strings.xml (Italian) 2018-07-23 13:30:40 +02:00
PhilippC
8987480491 New translations strings.xml (Japanese) 2018-07-23 13:30:38 +02:00
PhilippC
70bb4c2478 New translations strings.xml (Korean) 2018-07-23 13:30:35 +02:00
PhilippC
cf079a6be4 New translations strings.xml (Portuguese, Brazilian) 2018-07-23 13:30:33 +02:00
PhilippC
f153cdcba1 New translations strings.xml (Russian) 2018-07-23 13:30:30 +02:00
PhilippC
4e048240c5 New translations strings.xml (Serbian (Cyrillic)) 2018-07-23 13:30:27 +02:00
PhilippC
c098bb1ca0 New translations strings.xml (Slovak) 2018-07-23 13:30:24 +02:00
PhilippC
e02ded734c New translations strings.xml (Slovenian) 2018-07-23 13:30:22 +02:00
PhilippC
e721f29f5a New translations strings.xml (Spanish) 2018-07-23 13:30:19 +02:00
PhilippC
f763d5f936 New translations strings.xml (Swedish) 2018-07-23 13:30:17 +02:00
PhilippC
a3368eb557 New translations strings.xml (Turkish) 2018-07-23 13:30:14 +02:00
PhilippC
b5758347c2 New translations strings.xml (Ukrainian) 2018-07-23 13:30:11 +02:00
PhilippC
775a6d92aa New translations strings.xml (Indonesian) 2018-07-23 13:30:09 +02:00
PhilippC
2ab5995177 New translations strings.xml (Basque) 2018-07-23 13:30:06 +02:00
PhilippC
f6e847d43f New translations strings.xml (Portuguese) 2018-07-23 13:28:28 +02:00
PhilippC
cac2ca3d18 New translations strings.xml (Polish) 2018-07-23 13:28:26 +02:00
PhilippC
d1e870cee0 New translations strings.xml (Persian) 2018-07-23 13:28:24 +02:00
PhilippC
ca0f65767b New translations strings.xml (Norwegian Nynorsk) 2018-07-23 13:28:22 +02:00
PhilippC
7968bfc262 New translations strings.xml (Norwegian Bokmal) 2018-07-23 13:28:19 +02:00
PhilippC
ed4bbe9814 New translations strings.xml (Romanian) 2018-07-23 13:28:16 +02:00
PhilippC
6e83eb6da2 New translations strings.xml (Arabic) 2018-07-23 13:28:14 +02:00
PhilippC
00949b6135 Update Crowdin configuration file 2018-07-23 11:37:54 +02:00
Philipp Crocoll
f3a857f26f Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-07-23 11:00:38 +02:00
PhilippC
4bd03372aa Update Crowdin configuration file 2018-07-23 10:36:20 +02:00
Philipp Crocoll
dcc589c57a Changelog for 1.06 2018-07-23 10:29:55 +02:00
Philipp Crocoll
3018ec8cf0 update translations from crowdin 2018-07-23 10:29:48 +02:00
Philipp Crocoll
c452a66a4f don't try to use samsung api if Fingprint Unlock with Android API is set up, should fix #126 2018-07-23 10:07:30 +02:00
Philipp Crocoll
7a860f8564 fix #460 ("Lookup entry with "%1$s"") 2018-07-20 21:44:29 +02:00
Philipp Crocoll
94f6f4bdff fix string error 2018-07-16 13:07:43 +02:00
Philipp Crocoll
a627dac4b7 remove internal YubiChallenge activity in favor of ykdroid (allows to reduce required permissions) 2018-07-16 13:07:29 +02:00
Philipp Crocoll
848b6862be harmonize wording for caching, closes #86 2018-07-13 06:47:48 +02:00
Philipp Crocoll
d181575e93 improve wording for file caching at more places (see discussion in #86) 2018-07-12 21:23:06 +02:00
Philipp Crocoll
778775055f suggest to enable fingerprint if hardware is detected but fingerprint unlock not configured, closes #426 and closes #355 2018-07-12 06:44:02 +02:00
Philipp Crocoll
22ccda8d34 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-07-12 05:29:08 +02:00
Philipp Crocoll
c5fc6fd72e manifest for next release 2018-07-12 05:28:59 +02:00
Philipp Crocoll
c8a4978b5f improve wording for file caching, considering that this is also used for the offline version (see discussion in #86) 2018-07-12 05:27:01 +02:00
PhilippC
9e88f8c884 Merge pull request #449 from pp3345/ykdroid-keyboard-configuration
Mark keyboard configuration changes as handled in PasswordActivity
2018-07-10 22:25:06 +02:00
Yussuf Khalil
2e543bf4d3 Mark keyboard configuration changes as handled in PasswordActivity
This is required to avoid screen flickering due to recreation of the
activity when the ykDroid overlay is presented.
2018-07-10 19:30:08 +02:00
Philipp Crocoll
caf42d423f make sure the underlying stream is only written when the write transaction is commited. Avoids corrupted files when cancelling Yubichallenge during saving (#4) 2018-07-09 12:34:21 +02:00
Philipp Crocoll
dc39f874ac fix potential null reference exception when displaying error message 2018-07-09 12:27:29 +02:00
Philipp Crocoll
d1c7a124cf don't return empty strings for filename without path and ext in content storage, fixes #446 2018-07-09 11:03:10 +02:00
Philipp Crocoll
8ec17ce9a6 add timeout to fix #444 2018-07-09 10:22:44 +02:00
Philipp Crocoll
012af35e87 fix potential crash in SearchProvider, fixes #429 2018-07-03 19:38:59 +02:00
Philipp Crocoll
78bd1f4a5d update translations from crowdin, activates KeepassXC-challenge-response for all languages, add Changelog for 1.06-pre1 2018-07-02 12:54:25 +02:00
Philipp Crocoll
4477158182 editing groups was not possible, fixed. fixes #434 2018-07-02 12:10:28 +02:00
Philipp Crocoll
6e96021047 allow to use ykDroid instead of built-in activity 2018-07-02 12:03:32 +02:00
Philipp Crocoll
48f57eea66 fix bug with progress dialog not disappearing somtimes 2018-07-02 12:01:47 +02:00
Philipp Crocoll
4b6cfefaf3 Merge branch '1.05b' 2018-06-30 22:14:03 +02:00
Philipp Crocoll
0e34cc7f26 change manifest version to 1.06-pre 2018-06-30 22:13:16 +02:00
Philipp Crocoll
27fb2870ab check if file is trashed, do not load trashed files, fixes #165 2018-06-30 22:13:00 +02:00
Philipp Crocoll
ee6b7c4fe0 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-06-30 21:45:13 +02:00
Philipp Crocoll
0464cecde5 add roundIcon property for app, now round icon should work on Android 7 2018-06-30 21:21:48 +02:00
Philipp Crocoll
b237259599 fix incorrect folder icon (fixes #433) 2018-06-30 21:10:56 +02:00
Philipp Crocoll
8c379739f0 refactoring of ProgressTask and OnFinish classes, allowing to access the currently active activity from the task handlers. This fixes #33 and is required to correctly manage the activity recreation caused by the NFC activity coming to foreground with KeepassXC challenge (#4) 2018-06-26 13:44:48 +02:00
Philipp Crocoll
4fb8db982c add missing calls to base.OnActivityResult() in *EditActivity, leading to errors saving with YubiChallenge (#4). 2018-06-25 13:24:22 +02:00
Philipp Crocoll
921b50b642 add NFC permission to debug manifest also 2018-06-25 13:23:34 +02:00
Philipp Crocoll
031332e8ab re-add KeepassXC-style challenge response support 2018-06-25 13:23:24 +02:00
Philipp Crocoll
f03ccced8d Merge branch 'master' into 1.05b 2018-06-25 12:21:34 +02:00
Philipp Crocoll
51973d225c switch to suggested Native TLS implementation and HttpClient stack (https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=windows) 2018-06-23 13:08:32 +02:00
Philipp Crocoll
a59666e752 workaround to fix #420, based on https://stackoverflow.com/questions/28411153/jsch-suppressed-java-lang-classnotfoundexception-lorg-ietf-jgss-oid/28965796#28965796 and https://github.com/zeapo/Android-Password-Store/issues/49 2018-06-23 13:03:51 +02:00
PhilippC
8259191e50 Merge pull request #415 from jakseb/docfix
Fix broken links to screenshots in documentation
2018-06-23 12:08:44 +02:00
Philipp Crocoll
3eb84cc955 improve permission handling related to GoogleDrive 2018-06-23 11:43:54 +02:00
Philipp Crocoll
b1b7bff09d Manifest for 1.05d 2018-06-18 13:05:35 +02:00
Sebastian Jakubiak
82f28bfc8c Update links to screenshots in docs
Fixes #366 and #396
2018-06-16 11:04:02 +02:00
Philipp Crocoll
dfed92ac61 don't create local backups of local backups 2018-06-11 07:16:04 +02:00
Philipp Crocoll
0d6c9b468e fix UI bug when opening read-only databases (checkmarks were visible in Group list) 2018-06-11 07:15:54 +02:00
Philipp Crocoll
2bc12c510b implement defaults for otpauth:// style otp entries 2018-06-06 06:02:48 +02:00
Philipp Crocoll
f3022a19c2 manifest for 1.05c 2018-06-06 06:02:19 +02:00
Philipp Crocoll
800afae1c9 catch potential null reference exception 2018-06-06 03:05:57 +02:00
Philipp Crocoll
3c19f8e76f fix for IllegalStateException also when stopping the OngoingNotificationsService 2018-06-06 02:57:50 +02:00
Philipp Crocoll
3ca462f46f Manifest for 1.05b 2018-06-06 02:56:49 +02:00
Philipp Crocoll
fadd21ebd0 fix translations errors 2018-06-05 21:35:11 +02:00
Philipp Crocoll
a10c474ce5 attempt to make OngoingNotificationsService compatible to Android 8 restrictions 2018-06-05 21:35:03 +02:00
Philipp Crocoll
513ea5a198 manifest for 1.05a 2018-06-02 09:50:36 +02:00
Philipp Crocoll
4bab1c32d7 fix for second button in bottom bar never visible 2018-06-02 09:50:25 +02:00
Philipp Crocoll
39064eb2c6 update translations from crowdin, make changelog more robust against different forms of list item characters 2018-06-02 07:11:32 +02:00
Philipp Crocoll
28a60f5243 fix bug with automatic addition of URI scheme for owncloud files, improve input types to avoid automatic trailing spaces when using keyboard suggestions 2018-06-02 06:57:00 +02:00
Philipp Crocoll
56b9b878f8 make sure the local backup is not used automatically instead of the actual file 2018-06-02 06:55:48 +02:00
Philipp Crocoll
e7ad6e32e3 avoid showing infotexts after showing android 8 specific texts, update changelog, change version number for actual 1.05-pre3 release 2018-06-02 06:36:36 +02:00
Philipp Crocoll
a1d6347db3 create own YubiChallenge activity 2018-05-28 10:39:09 +02:00
Philipp Crocoll
9e80013e28 check for null bitmap, should fix #369 2018-05-07 11:12:43 +02:00
PhilippC
e66a8a0b21 Merge pull request #367 from gacelperfinian/patch-1
Updated Documentation.md to GitHub-flavoured MarkDown
2018-05-07 10:56:10 +02:00
Philipp Crocoll
77593969b2 fix leaking data to logcat 2018-05-07 10:42:58 +02:00
Gacel Perfinian
186fa35f70 Updated Documentation.md to GitHub-flavoured MarkDown
Changes:
- Changed last bullet in **What you should know and think about** into two bullet points due to change 2.
- Changed MarkDown so it renders correctly on GitHub Parser.
- Changed wording into bullet 2.2 to emphasise storing any second-factor authentication (if any was used).
2018-05-04 14:13:02 +08:00
Philipp Crocoll
c39d0048a8 Merge branch 'filecorruptionhandling' 2018-04-11 06:28:33 +02:00
Philipp Crocoll
5fc22b9530 introduced automatic local backups after successfully opening a database. This should make sure that users can access their database even if the file gets corrupted (#238) 2018-04-11 06:27:56 +02:00
Philipp Crocoll
51735c3f6d implement saving with KeepassXC-Challenge (#4) 2018-04-10 21:44:37 +02:00
Philipp Crocoll
f14aad0c50 implemented loading of files with KeepassXC Challenge (#4).
requires write support, handling of Challenge/Response errors (or user cancels). Caution: saving corrupts the file at the moment!
2018-04-10 07:15:19 +02:00
Philipp Crocoll
cdbb492f2c implemented editing of connection settings for ftp/sftp/webdav, includes changing password. Closes #27 2018-04-06 06:06:03 +02:00
Philipp Crocoll
de18aefd7b introduce vdots for file select list, prepare GUI for editing of storage locations 2018-04-04 05:01:19 +02:00
Philipp Crocoll
5f8807d62c workaround for error with Thai calendar settings (https://bugzilla.xamarin.com/show_bug.cgi?id=59077), fixes #327 2018-04-04 04:06:11 +02:00
Philipp Crocoll
e42d8b8eeb improve message when storage access framework access permission is revoked 2018-04-02 19:05:32 +02:00
Philipp Crocoll
d67b8b8298 fix bug with displaying info texts 2018-04-02 19:04:51 +02:00
Philipp Crocoll
10c8d157f5 request Read AND Write permissions in BuiltInFileStorage to be more compatible with Android O, also request storage permissions for GDrive to fix #265, even though this seems to be a workaround 2018-04-02 17:02:09 +02:00
Philipp Crocoll
1f10558f1f Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-04-02 05:52:41 +02:00
Philipp Crocoll
409228285e upgrade JSch to 0.1.54, closes #48. Upgrade ADAL. 2018-04-02 05:52:37 +02:00
PhilippC
0ac7758c04 Merge pull request #322 from ypid/fix/typo
Fix typo in README.md
2018-04-01 07:11:38 +02:00
Robin Schneider
802e3d04b2 Fix typo in README.md 2018-03-31 22:19:37 +02:00
Philipp Crocoll
39ef4a4711 replace obsolete Android.Text.ClipboardManager, might help with #248 2018-03-29 06:53:56 +02:00
Philipp Crocoll
b2215e1db6 release 1.05-pre2 2018-03-29 06:14:40 +02:00
Philipp Crocoll
7d42da5d3c add an IME subtype to close #56 2018-03-27 21:57:53 +02:00
Philipp Crocoll
82770e6dd0 disable sounds from notifications 2018-03-27 21:37:45 +02:00
Philipp Crocoll
62bbfc6075 remove testing code 2018-03-27 20:45:47 +02:00
Philipp Crocoll
a5eb77dd87 register broadcast receiver on app create, fixes #266 2018-03-27 20:45:32 +02:00
Philipp Crocoll
cb9cf4885f refactor, maybe helps to find crash report cause 2018-03-27 07:15:08 +02:00
PhilippC
a5455925ea Merge pull request #270 from mydexterid/ISSUE-221-Yubikey-static-password-support
Fix for issue #221
2018-03-26 20:31:36 +02:00
Philipp Crocoll
61ef383c38 add button to hide autofill info text in Group activity, closes #311 2018-03-26 20:27:51 +02:00
Philipp Crocoll
b0aa706c07 upgrade to target Android 8.1 2018-03-26 19:56:55 +02:00
Philipp Crocoll
a04c8f6214 fix checking for InputTypes flags, fixes #303 2018-03-26 13:40:30 +02:00
Philipp Crocoll
fd5b582c6c fix crash when disabling log file before writing anything into it, fixes #301 2018-03-21 05:00:57 +01:00
Philipp Crocoll
dc45613b7b fix crash when searching from autofill/keyboard/search url. fixes https://github.com/PhilippC/keepass2android/issues/289 2018-03-21 04:57:27 +01:00
Philipp Crocoll
d986d8f398 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-03-21 04:56:45 +01:00
Philipp Crocoll
6c64f20a14 fix erroneous string value 2018-03-21 04:47:42 +01:00
Philipp Crocoll
2071087794 improve detection of file/folder, closes https://github.com/PhilippC/keepass2android/issues/276 2018-03-21 04:47:26 +01:00
PhilippC
ba56ab719c Update README.md 2018-03-12 11:36:52 +01:00
PhilippC
617c053b95 Update README.md 2018-03-12 11:36:35 +01:00
PhilippC
868cff2c4c Update README.md 2018-03-12 11:36:17 +01:00
Philipp Crocoll
8e23ebf3e4 add package to lock database broadcast from keyboard 2018-02-28 06:11:34 +01:00
DEXTER
6dd6eff02c PasswordActivity.cs: Do not clear the password field
when Yubikey is used to fill in the password entry.
2018-02-24 14:06:39 +01:00
DEXTER
3a1fcd2147 AndroidManifest*.xml: Add yubico's url to VIEW/BROWSABLE intent-filter
This patch makes it so that the user can choose keepass2android as
a handler for my.yubico.com in
Settings->Apps->App links->keepass2android->Open supported links->
Open in this app.
This is needed to be set manually by the user in order for their
Yubikey NEOs to work.
2018-02-24 14:06:01 +01:00
Philipp Crocoll
d4bd4a8150 update info text string to clarify things 2018-02-21 05:56:38 +01:00
Philipp Crocoll
2ace518db9 Merge branch '1.04'
Conflicts:
	src/keepass2android/ChangeLog.cs
	src/keepass2android/GroupBaseActivity.cs
	src/keepass2android/Properties/AndroidManifest_net.xml
	src/keepass2android/Resources/values/strings.xml
2018-02-20 22:18:20 +01:00
Philipp Crocoll
e8641cee8f changelog for 1.05-pre1 2018-02-20 22:15:49 +01:00
Philipp Crocoll
884328d10f refactor CopyToClipboardService to get (hopefully) more helpful reports on Google Play, see #248 2018-02-20 22:03:43 +01:00
Philipp Crocoll
d8bd8a29bc don't create notification channels for devices < sdk 26 2018-02-20 22:02:33 +01:00
Philipp Crocoll
cbd6b796ca created and integrated Adaptive Icons, closes #204 2018-02-20 21:52:25 +01:00
Philipp Crocoll
90cfa4ed5c refactor CopyToClipboardService to get (hopefully) more helpful reports on Google Play, see #248 2018-02-19 13:33:35 +01:00
Philipp Crocoll
6426abfedf commit missing change for previous commit 2018-02-19 13:24:44 +01:00
Philipp Crocoll
d746928765 show entry icon in notification, closes #21 2018-02-19 13:11:45 +01:00
Philipp Crocoll
f83554c817 prevent database from being loaded twice simultaneously, fixes #15 2018-02-12 13:21:58 +01:00
Philipp Crocoll
6fc4741c9a remove icon preferences on Android 8, show info on how to use notification channels on Android 8 2018-02-10 21:06:50 +01:00
Philipp Crocoll
7b63346bd0 set notification channel importances correctly 2018-02-09 12:22:49 +01:00
Philipp Crocoll
737c63e8b0 switch to TargetSDK 26, implement notification channels allowing customization of notification importance on Android 8, see #178 2018-02-09 12:07:21 +01:00
Philipp Crocoll
5fa2bc3bc8 allow to bring up search fied on start, closes #107 2018-02-08 12:44:50 +01:00
Philipp Crocoll
5d7a5ace66 change the way how Files are written through SAF. Fixes #241 2018-02-08 11:46:48 +01:00
Philipp Crocoll
0bd213a327 make sure correct items for ActionMode are displayed, fixes #231 2018-02-08 11:09:41 +01:00
Philipp Crocoll
3d9f351d84 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-02-08 08:54:36 +01:00
Philipp Crocoll
9fda220f33 move netftpandroid to github 2018-02-08 08:53:25 +01:00
PhilippC
991ae1d6e3 Merge pull request #203 from StefanSchoof/patch-1
Add Bugzilla link to Firefox Support
2018-01-23 23:10:33 +01:00
Philipp Crocoll
b993be4658 add some info texts, especialy for novice users to avoid some common misunderstandings. closes #46, closes #47 2018-01-23 23:09:17 +01:00
Philipp Crocoll
c4f8af2311 Merge branch '1.04' 2018-01-23 21:05:59 +01:00
Philipp Crocoll
c34e38e50f allow to import content-URI database files to internal folder (closes #158) 2018-01-23 20:23:23 +01:00
Philipp Crocoll
b98676ea77 avoid crash when IconSet was uninstalled (fixes #139) 2018-01-23 20:03:05 +01:00
Philipp Crocoll
002c67e48c support otpauth:// URIs in otp field as used by KeeWeb (closes #118) 2018-01-23 19:53:06 +01:00
Philipp Crocoll
cf21684916 fix display issue with dynamic fields and visible passwords (related to #96) 2018-01-23 19:52:33 +01:00
Philipp Crocoll
9fe1a904c8 allow to hide the length of the QuickUnlock code. Closes #52 2018-01-23 19:11:01 +01:00
Philipp Crocoll
c4e67db75f fix QuickUnlock with Unicode characters like emojis (length correction was incorrect or misleading), fixes #161 2018-01-22 13:07:04 +01:00
Philipp Crocoll
8487555315 fix issue with displaying long passwords by using two different TextViews for the visible and "protected" password view, toggling visibility instead of InputType. Fixes #96. 2018-01-22 12:48:40 +01:00
Philipp Crocoll
304c1ef5d2 don't use implicit intents for notification actions. Should fix #149. 2018-01-22 11:45:28 +01:00
StefanSchoof
f0a86db9e4 Add Bugzilla link to Firefox Support 2018-01-11 10:56:22 +01:00
388 changed files with 25319 additions and 5069 deletions

2
.gitignore vendored
View File

@@ -158,3 +158,5 @@ src/java/KP2ASoftkeyboard_AS/build/generated/mockable-android-23.jar
*.rawproto
src/java/Keepass2AndroidPluginSDK2/build/generated/mockable-Google-Inc.-Google-APIs-23.jar
/src/.vs
/src/JavaFileStorageBindings/Jars/JavaFileStorage-release.aar
/src/PluginSdkBinding/Jars/app-debug.aar

2
.gitmodules vendored
View File

@@ -3,4 +3,4 @@
url = https://github.com/PhilippC/Xamarin-Samsung-Pass.git
[submodule "src/netftpandroid"]
path = src/netftpandroid
url = https://git01.codeplex.com/forks/philippc/netftpandroid
url = https://github.com/PhilippC/netftpandroid.git

6
crowdin.yml Normal file
View File

@@ -0,0 +1,6 @@
files:
- source: src/keepass2android/Resources/values/strings.xml
translation: >-
/src/keepass2android/Resources/values-%two_letters_code%/%original_file_name%
translate_attributes: '0'
content_segmentation: '0'

View File

@@ -7,11 +7,12 @@ If you think something is missing in the documentation, please create an issue a
If you store important information using Keepass2Android, you should know a little bit about what's going on:
* Keepass2Android stores your password in an encrypted file. It is *your responsibility* to backup this file regularly and safely.
* There is no way for anyone, including the app's author, to access the information stored in your password database without
** having the database file
** knowing the master password (and additional second factor if you chose one)
This means that **if you forget the master password, your database is lost**! So make sure you remember the password. You might also want to think about:
** What happens if I have an accident? Should any trusted person be able to access my database?
** What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
* having the database file
* knowing the master password (and additional second factor if you chose one)
This means that **if you forget the master password, your database is lost**! So make sure you remember the password and retain any second factor method (if one is used).
* You might also want to think about:
* What happens if I have an accident? Should any trusted person be able to access my database?
* What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
# Getting started

View File

@@ -4,28 +4,28 @@
on how to set up a Keepass 2 database with Yubikey/OTP protection.<br>
<br>
After successful setup you should have the database file, e.g. yubi.kdbx, and the OTP auxiliary file, e.g. yubi.otp.xml, both in the same folder.<br>
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767825"><img title="OTPAuxFile" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767826" alt="OTPAuxFile" width="513" height="40" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<a href="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_2.png"><img title="OTPAuxFile" src="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_thumb.png" alt="OTPAuxFile" width="513" height="40" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p>Make sure you make <strong>both files</strong> available to Keepass2Android, e.g. by placing them both in your Dropbox.</p>
<p>Now you should check your NDEF setup of the Yubikey NEO. Therefore, go to the Tools menu in the Yubico Personalization Utility. Select the same slot as used for OTPs with Keepass 2. The default setting for NDEF type and payload should work. If you experience
problems, you may use the configuration as shown in this screenshot or simply press the &ldquo;Reset&rdquo; button:</p>
<p><a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767911"><img title="image" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767912" alt="image" width="760" height="622" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p><a href="How to use Keepass2Android with YubiKey NEO_image_2.png"><img title="image" src="How to use Keepass2Android with YubiKey NEO_image_thumb.png" alt="image" width="760" height="622" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p><br>
<br>
In Keepass2Android, select &quot;Open file&quot; and locate your database file, e.g. yubi.kdbx.<br>
<br>
In the password screen under &quot;Select master key type&quot; select &quot;Password &#43; OTP&quot;.</p>
<p><a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767913"><img title="Screenshot_2013-12-13-06-38-50" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767914" alt="Screenshot_2013-12-13-06-38-50" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p><a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_2.png"><img title="Screenshot_2013-12-13-06-38-50" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_thumb.png" alt="Screenshot_2013-12-13-06-38-50" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p>Click &quot;Load auxiliary OTP file&quot;. This is required to load the information how many OTPs must be entered. As loading the file might require user action in some cases, this is not performed automatically.<br>
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767915"><img title="Screenshot_2013-12-13-06-38-12" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767916" alt="Screenshot_2013-12-13-06-38-12" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_2.png"><img title="Screenshot_2013-12-13-06-38-12" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_thumb.png" alt="Screenshot_2013-12-13-06-38-12" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
After loading the OTP auxiliary file, you should see a few text fields for entering the OTPs. Now swipe your YubiKey NEO at the back of your Android device. If you have multiple apps which can handle NFC actions, you might be prompted to select which app to
use. Select Keepass2Android in this case. Swipe your YubiKey again until all OTP fields are filled. Note: You don't need to select the next text field, this is done automatically!<br>
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767917"><img title="Screenshot_2013-12-13-06-38-36" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767918" alt="Screenshot_2013-12-13-06-38-36" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_2.png"><img title="Screenshot_2013-12-13-06-38-36" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_thumb.png" alt="Screenshot_2013-12-13-06-38-36" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
Don't forget to also enter your password and click OK. You will see the &ldquo;Saving auxiliary OTP file&hellip;&rdquo; dialog. Note that there is some encryption envolved which is probably fast on your PC but might take some time on your mobile device. You
can reduce the look-ahead window length to speed this up.<br>
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767919"><img title="Screenshot_2013-12-13-06-39-47" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767920" alt="Screenshot_2013-12-13-06-39-47" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_2.png"><img title="Screenshot_2013-12-13-06-39-47" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_thumb.png" alt="Screenshot_2013-12-13-06-39-47" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<h2>&nbsp;</h2>
<h2>A note about offline access</h2>
<p>If your database is stored in the cloud or on the web, you can still access it if you have enabled file caching (which is on by default). With OTPs, this becomes a little bit more complicated: If you repeatedly open your datbase while being offline, the
OTP counter stored on the Yubikey will be increased. Don&rsquo;t forget to synchronize the database (which will also synchronize the OTP auxiliary file) as soon as possible to avoid problems with accessing your database on other devices! If you often need
to open the database while you&rsquo;re offline, consider increasing the look-ahead window length!</p>
</div><div class="ClearBoth"></div>
</div><div class="ClearBoth"></div>

View File

@@ -12,7 +12,7 @@ As of January 2018, the following browsers are known to have Android Autofill su
These browsers do not (yet) have autofill support:
* Google Chrome
* Firefox for Android
* Firefox for Android ([bugzilla entry](https://bugzilla.mozilla.org/show_bug.cgi?id=1352011))
* Brave-Browser
* Opera

View File

@@ -1,12 +1,11 @@
# What is Keepass2Android?
Keepass2Android is a password manager app. It allows to store and retrieve passwords and other sensitive information in a file called "database". This database is secured with a so-called master password. The master password typically is a strong password and can be complemented with a second factor for additional security.
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KepassX on Linux.
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KeepassX on Linux.
# Where to get it?
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android). Please join the [Beta tester group](https://plus.google.com/communities/107293657110547776032) for news and discussions about the latest beta releases.
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android) or [Beta testing channel for Keepass2Android Offline](https://play.google.com/apps/testing/keepass2android.keepass2android_nonet). Please join the [Beta tester group](https://plus.google.com/communities/107293657110547776032) for news and discussions about the latest beta releases.
# How can I contribute?
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](http://crowdin.net/project/keepass2android)

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 353 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 800 800"
enable-background="new 0 0 800 800"
xml:space="preserve"
sodipodi:docname="Logo-green-foreground.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"><metadata
id="metadata4969"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs4967" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview4965"
showgrid="false"
inkscape:zoom="0.75130096"
inkscape:cx="413.59403"
inkscape:cy="332.90312"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 318.7,232 c 13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4 z m 134.8,24.4 c 0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4 z M 399.8,177.7 M 140.2,600.6 v 47 h 517.3 v -47 z m 0,-249.7 v 47 h 517.3 v -47 z m -0.1,130.3 h 191.8 c -0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6 H 140.1 Z m 517.4,0 v -47 H 454.9 c 6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4 z m -517.4,36.2 v 47 h 186.6 l 14.3,-47 z m 314.2,0 14.4,47 h 188.8 v -47 z m -21.6,48.4 -21,-68.9 2.7,-1.6 c 10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6 l 2.7,1.6 -21.1,68.9 z m 74.8,-407.3 0.2,-0.3 35.6,-51.3 c 2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4 l -37.2,53.5 -0.1,0.3 c -29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19 L 261.8,99 c -2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3 l 36.2,52.2 c -66.8,32.2 -111.9,92.4 -111.9,161.3 h 42.9 c 0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5 h 42.9 c 0.2,-69.3 -45.4,-129.8 -113,-161.9 z"
id="path4962"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 353 KiB

View File

@@ -10,7 +10,7 @@
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

View File

@@ -26,6 +26,7 @@
android:hint="@string/http_auth_dialog_password"
android:inputType="textPassword"
android:paddingTop="10dp"
android:paddingBottom="20dp" />
android:paddingBottom="20dp"
android:importantForAccessibility="no" />
</LinearLayout>

Binary file not shown.

View File

@@ -11,7 +11,7 @@
<AssemblyName>JavaFileStorageBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -60,6 +60,7 @@
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
<LibraryProjectZip Include="Jars\adal-1.14.0.aar" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
@@ -92,9 +93,6 @@
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\onedrive-sdk-android-1.2.2\classes-onedrive-sdk.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\adal-1.1.19\classes-adal.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\gdrive\commons-logging-1.1.1.jar" />
</ItemGroup>

View File

@@ -10,7 +10,7 @@
<RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
<AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

View File

@@ -55,7 +55,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
get { return "AES-KDF"; }
}
public AesKdf()
public override byte[] GetSeed(KdfParameters p)
{ return p.GetByteArray(ParamSeed); }
public AesKdf()
{
}

View File

@@ -68,7 +68,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
get { return "Argon2"; }
}
public Argon2Kdf()
public override byte[] GetSeed(KdfParameters p)
{ return p.GetByteArray(ParamSalt); }
public Argon2Kdf()
{
}

View File

@@ -36,7 +36,9 @@ namespace KeePassLib.Cryptography.KeyDerivation
get;
}
public virtual KdfParameters GetDefaultParameters()
public abstract byte[] GetSeed(KdfParameters p);
public virtual KdfParameters GetDefaultParameters()
{
return new KdfParameters(this.Uuid);
}

View File

@@ -12,7 +12,7 @@
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<AssemblyName>KeePassLib2Android</AssemblyName>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
</PropertyGroup>

View File

@@ -20,11 +20,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using KeePassLib.Cryptography;
using KeePassLib.Cryptography.KeyDerivation;
using KeePassLib.Native;
using KeePassLib.Resources;
using KeePassLib.Security;
using KeePassLib.Utility;
@@ -168,7 +165,7 @@ namespace KeePassLib.Keys
/// Creates the composite key from the supplied user key sources (password,
/// key file, user account, computer ID, etc.).
/// </summary>
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed)
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed, byte[] mPbKdfSeed)
{
ValidateUserKeys();
@@ -178,7 +175,7 @@ namespace KeePassLib.Keys
foreach(IUserKey pKey in m_vUserKeys)
{
if (pKey is ISeedBasedUserKey)
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed);
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed, mPbKdfSeed);
ProtectedBinary b = pKey.KeyData;
if(b != null)
{
@@ -211,15 +208,17 @@ namespace KeePassLib.Keys
{
if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed);
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
if (kdf == null) // CryptographicExceptions are translated to "file corrupted"
throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
"UUID: " + p.KdfUuid.ToHexString() + ".");
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed, kdf.GetSeed(p));
if((pbRaw32 == null) || (pbRaw32.Length != 32))
{ Debug.Assert(false); return null; }
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
if(kdf == null) // CryptographicExceptions are translated to "file corrupted"
throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
"UUID: " + p.KdfUuid.ToHexString() + ".");
byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
if(pbTrf32 == null) { Debug.Assert(false); return null; }
@@ -256,7 +255,7 @@ namespace KeePassLib.Keys
public interface ISeedBasedUserKey
{
void SetParams(byte[] masterSeed);
void SetParams(byte[] masterSeed, byte[] mPbKdfSeed);
}
public sealed class InvalidCompositeKeyException : Exception

View File

@@ -100,7 +100,8 @@ namespace keepass2android
int count = 0;
while (File.Exists(LogFilename + "." + count))
count++;
File.Move(LogFilename, LogFilename + "." + count);
if (count > 0)
File.Move(LogFilename, LogFilename + "." + count);
}

View File

@@ -52,7 +52,7 @@ namespace keepass2android
/// <summary>
/// Tell the app that the file from ioc was opened with keyfile.
/// </summary>
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile);
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, string displayName = "");
/// <summary>
/// Creates a new database and returns it

View File

@@ -2,11 +2,16 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using Android;
using Android.Content;
using Android.Database;
using Android.OS;
using Android.Provider;
using Java.IO;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using Console = System.Console;
namespace keepass2android.Io
{
@@ -28,7 +33,12 @@ namespace keepass2android.Io
get { yield return "content"; }
}
public void Delete(IOConnectionInfo ioc)
public bool UserShouldBackup
{
get { return true; }
}
public void Delete(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
@@ -45,7 +55,20 @@ namespace keepass2android.Io
public Stream OpenFileForRead(IOConnectionInfo ioc)
{
return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
try
{
return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
}
catch (Exception e)
{
if (e.Message.Contains("requires that you obtain access using ACTION_OPEN_DOCUMENT"))
{
//looks like permission was revoked.
throw new DocumentAccessRevokedException();
}
throw;
}
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
@@ -55,8 +78,9 @@ namespace keepass2android.Io
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
{
return "";
}
return UrlUtil.StripExtension(
UrlUtil.GetFileName(ioc.Path));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
@@ -261,7 +285,26 @@ namespace keepass2android.Io
}
class AndroidContentWriteTransaction : IWriteTransaction
public class DocumentAccessRevokedException : Exception
{
public DocumentAccessRevokedException()
{
}
public DocumentAccessRevokedException(string message) : base(message)
{
}
public DocumentAccessRevokedException(string message, Exception innerException) : base(message, innerException)
{
}
protected DocumentAccessRevokedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
class AndroidContentWriteTransaction : IWriteTransaction
{
private readonly string _path;
private readonly Context _ctx;
@@ -286,11 +329,15 @@ namespace keepass2android.Io
public void CommitWrite()
{
using (Stream outputStream = _ctx.ContentResolver.OpenOutputStream(Android.Net.Uri.Parse(_path)))
ParcelFileDescriptor fileDescriptor = _ctx.ContentResolver.OpenFileDescriptor(Android.Net.Uri.Parse(_path), "w");
using (var outputStream = new FileOutputStream(fileDescriptor.FileDescriptor))
{
byte[] data = _memoryStream.ToArray();
outputStream.Write(data, 0, data.Length);
outputStream.Close();
}
fileDescriptor.Close();
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security;
@@ -10,10 +11,14 @@ using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Preferences;
using Android.Support.V13.App;
using Android.Support.V4.App;
using Java.IO;
using Java.Util;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using ActivityCompat = Android.Support.V13.App.ActivityCompat;
using File = System.IO.File;
using FileNotFoundException = System.IO.FileNotFoundException;
using IOException = System.IO.IOException;
@@ -59,7 +64,12 @@ namespace keepass2android.Io
public abstract IEnumerable<string> SupportedProtocols { get; }
public void Delete(IOConnectionInfo ioc)
public bool UserShouldBackup
{
get { return true; }
}
public void Delete(IOConnectionInfo ioc)
{
//todo check if directory
IOConnection.DeleteFile(ioc);
@@ -253,10 +263,14 @@ namespace keepass2android.Io
if (requiresPermission && (Build.VERSION.SdkInt >= BuildVersionCodes.M))
{
if (activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
if ((activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
Permission.Denied)
{
activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
||
(activity.Activity.CheckSelfPermission(Manifest.Permission.ReadExternalStorage) ==
Permission.Denied))
{
activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
return;
}
}
@@ -274,7 +288,7 @@ namespace keepass2android.Io
public void OnCreate(IFileStorageSetupActivity fileStorageSetupActivity, Bundle savedInstanceState)
{
((Activity)fileStorageSetupActivity).RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 0);
Android.Support.V4.App.ActivityCompat.RequestPermissions(((Activity)fileStorageSetupActivity), new[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 0);
}
public void OnResume(IFileStorageSetupActivity activity)
@@ -367,7 +381,14 @@ namespace keepass2android.Io
{
if (ioc.IsLocalFile())
{
if (IsLocalFileFlaggedReadOnly(ioc))
if (IsLocalBackup(ioc))
{
if (reason != null)
reason.Result = UiStringKey.ReadOnlyReason_LocalBackup;
return true;
}
if (IsLocalFileFlaggedReadOnly(ioc))
{
if (reason != null)
reason.Result = UiStringKey.ReadOnlyReason_ReadOnlyFlag;
@@ -388,7 +409,22 @@ namespace keepass2android.Io
return false;
}
private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
private readonly Dictionary<string, bool> _isLocalBackupCache = new Dictionary<string, bool>();
public bool IsLocalBackup(IOConnectionInfo ioc)
{
if (!ioc.IsLocalFile())
return false;
bool result;
if (_isLocalBackupCache.TryGetValue(ioc.Path, out result))
return result;
result = (PreferenceManager.GetDefaultSharedPreferences(Application.Context)
.GetBoolean(IoUtil.GetIocPrefKey(ioc, "is_local_backup"), false));
_isLocalBackupCache[ioc.Path] = result;
return result;
}
private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
{
//see http://stackoverflow.com/a/33292700/292233
try
@@ -412,7 +448,7 @@ namespace keepass2android.Io
public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
string[] permissions, Permission[] grantResults)
{
fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults[0] == Permission.Granted);
fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults.All(res => res == Permission.Granted));
}
}

View File

@@ -84,7 +84,12 @@ namespace keepass2android.Io
public IEnumerable<string> SupportedProtocols { get { return _cachedStorage.SupportedProtocols; } }
public void DeleteFile(IOConnectionInfo ioc)
public bool UserShouldBackup
{
get { return _cachedStorage.UserShouldBackup; }
}
public void DeleteFile(IOConnectionInfo ioc)
{
if (IsCached(ioc))
{
@@ -340,57 +345,7 @@ namespace keepass2android.Io
private class CachedWriteTransaction: IWriteTransaction
{
private class CachedWriteMemoryStream : MemoryStream
{
private readonly IOConnectionInfo ioc;
private readonly CachingFileStorage _cachingFileStorage;
private readonly bool _useFileTransaction;
private bool _closed;
public CachedWriteMemoryStream(IOConnectionInfo ioc, CachingFileStorage cachingFileStorage, bool useFileTransaction)
{
this.ioc = ioc;
_cachingFileStorage = cachingFileStorage;
_useFileTransaction = useFileTransaction;
}
public override void Close()
{
if (_closed) return;
//write file to cache:
//(note: this might overwrite local changes. It's assumed that a sync operation or check was performed before
string hash;
using (var hashingStream = new HashingStreamEx(File.Create(_cachingFileStorage.CachedFilePath(ioc)), true, new SHA256Managed()))
{
Position = 0;
CopyTo(hashingStream);
hashingStream.Close();
hash = MemUtil.ByteArrayToHexString(hashingStream.Hash);
}
File.WriteAllText(_cachingFileStorage.VersionFilePath(ioc), hash);
//update file on remote. This might overwrite changes there as well, see above.
Position = 0;
if (_cachingFileStorage.IsCached(ioc))
{
//if the file already is in the cache, it's ok if writing to remote fails.
_cachingFileStorage.TryUpdateRemoteFile(this, ioc, _useFileTransaction, hash);
}
else
{
//if not, we don't accept a failure (e.g. invalid credentials would always remain a problem)
_cachingFileStorage.UpdateRemoteFile(this, ioc, _useFileTransaction, hash);
}
base.Close();
_closed = true;
}
}
private readonly IOConnectionInfo _ioc;
private readonly bool _useFileTransaction;
@@ -424,17 +379,48 @@ namespace keepass2android.Io
public Stream OpenFile()
{
_memoryStream = new CachedWriteMemoryStream(_ioc, _cachingFileStorage, _useFileTransaction);
_memoryStream = new MemoryStream();
return _memoryStream;
}
public void CommitWrite()
{
//the transaction is committed in the stream's Close
_committed = true;
_memoryStream.Close();
//write file to cache:
//(note: this might overwrite local changes. It's assumed that a sync operation or check was performed before
byte[] output = _memoryStream.ToArray();
string hash;
using (var hashingStream = new HashingStreamEx(File.Create(_cachingFileStorage.CachedFilePath(_ioc)), true, new SHA256Managed()))
{
hashingStream.Write(output, 0, output.Length);
hashingStream.Close();
hash = MemUtil.ByteArrayToHexString(hashingStream.Hash);
}
File.WriteAllText(_cachingFileStorage.VersionFilePath(_ioc), hash);
//create another memory stream which is open for reading again
MemoryStream openMemStream = new MemoryStream(output);
//update file on remote. This might overwrite changes there as well, see above.
if (_cachingFileStorage.IsCached(_ioc))
{
//if the file already is in the cache, it's ok if writing to remote fails.
_cachingFileStorage.TryUpdateRemoteFile(openMemStream, _ioc, _useFileTransaction, hash);
}
else
{
//if not, we don't accept a failure (e.g. invalid credentials would always remain a problem)
_cachingFileStorage.UpdateRemoteFile(openMemStream, _ioc, _useFileTransaction, hash);
}
openMemStream.Dispose();
}
}
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)

View File

@@ -10,7 +10,11 @@ namespace keepass2android.Io
{
}
public override bool UserShouldBackup
{
get { return false; }
}
}
public partial class DropboxAppFolderFileStorage: JavaFileStorage
@@ -20,8 +24,12 @@ namespace keepass2android.Io
{
}
}
public override bool UserShouldBackup
{
get { return false; }
}
}
}
#endif

View File

@@ -22,6 +22,10 @@ namespace keepass2android.Io
}
public override bool UserShouldBackup
{
get { return false; }
}
}
}
#endif

View File

@@ -46,9 +46,14 @@ namespace keepass2android.Io
/// <summary>
/// returns the protocol ids supported by this FileStorage. Can return pseudo-protocols like "dropbox" or real protocols like "ftp"
/// </summary>
IEnumerable<string> SupportedProtocols { get; }
IEnumerable<string> SupportedProtocols { get; }
/// <summary>
/// <summary>
/// returns true if users should backup files on this file storage (if the file is important). Can be false for cloud providers with built-in versioning or backups.
/// </summary>
bool UserShouldBackup { get; }
/// <summary>
/// Deletes the given file or directory.
/// </summary>
void Delete(IOConnectionInfo ioc);

View File

@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Android.Content;
using Android.OS;
using Java.IO;
using KeePassLib.Serialization;
using KeePassLib.Utility;
namespace keepass2android.Io
{
@@ -125,5 +127,53 @@ namespace keepass2android.Io
return ctx.FilesDir;
}
}
//creates a local ioc where the sourceIoc can be stored to
public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx)
{
Java.IO.File internalDirectory = IoUtil.GetInternalDirectory(ctx);
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
if (targetPath == "")
targetPath = "internal";
if (new File(internalDirectory, targetPath).Exists())
{
int c = 1;
var ext = UrlUtil.GetExtension(targetPath);
var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
do
{
c++;
targetPath = filenameWithoutExt + c;
if (!String.IsNullOrEmpty(ext))
targetPath += "." + ext;
} while (new File(internalDirectory, targetPath).Exists());
}
return IOConnectionInfo.FromPath(new File(internalDirectory, targetPath).CanonicalPath);
}
public static IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app)
{
var targetIoc = GetInternalIoc(sourceIoc, ctx);
IoUtil.Copy(targetIoc, sourceIoc, app);
return targetIoc;
}
public static string GetIocPrefKey(IOConnectionInfo ioc, string suffix)
{
var iocAsHexString = IocAsHexString(ioc);
return "kp2a_ioc_key_" + iocAsHexString + suffix;
}
public static string IocAsHexString(IOConnectionInfo ioc)
{
SHA256Managed sha256 = new SHA256Managed();
string iocAsHexString =
MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
return iocAsHexString;
}
}
}

View File

@@ -22,9 +22,10 @@ namespace keepass2android.Io
protected string Protocol { get { return _jfs.ProtocolId; } }
public virtual IEnumerable<string> SupportedProtocols { get { yield return Protocol; } }
public abstract bool UserShouldBackup { get; }
private readonly IJavaFileStorage _jfs;
private readonly IJavaFileStorage _jfs;
private readonly IKp2aApp _app;
public JavaFileStorage(IJavaFileStorage jfs, IKp2aApp app)

View File

@@ -161,7 +161,12 @@ namespace keepass2android.Io
}
}
public void Delete(IOConnectionInfo ioc)
public bool UserShouldBackup
{
get { return true; }
}
public void Delete(IOConnectionInfo ioc)
{
try
{
@@ -226,7 +231,7 @@ namespace keepass2android.Io
internal Uri IocToUri(IOConnectionInfo ioc)
public static Uri IocToUri(IOConnectionInfo ioc)
{
if (!string.IsNullOrEmpty(ioc.UserName))
{
@@ -570,7 +575,7 @@ namespace keepass2android.Io
{
_client = _fileStorage.GetClient(_ioc, false);
_stream = _client.OpenWrite(_fileStorage.IocToUri(_iocTemp).PathAndQuery);
_stream = _client.OpenWrite(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery);
return _stream;
}
catch (FtpCommandException ex)
@@ -590,8 +595,8 @@ namespace keepass2android.Io
//make sure target file does not exist:
//try
{
if (_client.FileExists(_fileStorage.IocToUri(_ioc).PathAndQuery))
_client.DeleteFile(_fileStorage.IocToUri(_ioc).PathAndQuery);
if (_client.FileExists(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery))
_client.DeleteFile(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
}
//catch (FtpCommandException)
@@ -599,8 +604,8 @@ namespace keepass2android.Io
//TODO get a new clien? might be stale
}
_client.Rename(_fileStorage.IocToUri(_iocTemp).PathAndQuery,
_fileStorage.IocToUri(_ioc).PathAndQuery);
_client.Rename(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery,
NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
}
catch (FtpCommandException ex)

View File

@@ -32,7 +32,12 @@ namespace keepass2android.Io
get { return _baseStorage.SupportedProtocols; }
}
public void Delete(IOConnectionInfo ioc)
public bool UserShouldBackup
{
get { return _baseStorage.UserShouldBackup; }
}
public void Delete(IOConnectionInfo ioc)
{
_baseStorage.Delete(ioc);
}

View File

@@ -33,6 +33,11 @@ namespace keepass2android.Io
yield return "onedrive";
}
}
public override bool UserShouldBackup
{
get { return false; }
}
}
}
#endif

View File

@@ -10,7 +10,11 @@ namespace keepass2android.Io
{
}
public override bool UserShouldBackup
{
get { return true; }
}
}

View File

@@ -33,7 +33,12 @@ namespace keepass2android.Io
}
}
public static string Owncloud2Webdav(string owncloudUrl)
public override bool UserShouldBackup
{
get { return true; }
}
public static string Owncloud2Webdav(string owncloudUrl)
{
string owncloudPrefix = "owncloud://";
if (owncloudUrl.StartsWith(owncloudPrefix))

View File

@@ -12,9 +12,10 @@
<FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>06ffb71c</NuGetPackageImportStamp>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -55,6 +56,36 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Core.Common.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Arch.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Annotations.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Compat.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Core.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.UI.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.Utils.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Fragment.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Media.Compat.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.v13, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.v13.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.v13.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="database\CheckDatabaseForChanges.cs" />
@@ -148,7 +179,35 @@
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets'))" />
</Target>
<Import Project="..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" />
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" />
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -30,8 +30,12 @@ namespace keepass2android
readonly IKp2aApp _app;
private readonly Handler _handler;
private string _message = "";
private string _submessage;
public ProgressDialogStatusLogger() {
public String SubMessage => _submessage;
public String Message => _message;
public ProgressDialogStatusLogger() {
}
@@ -56,6 +60,7 @@ namespace keepass2android
public void UpdateSubMessage(String submessage)
{
_submessage = submessage;
if (_app != null && _progressDialog != null && _handler != null)
{
_handler.Post(() =>

View File

@@ -25,39 +25,107 @@ namespace keepass2android
/// <summary>
/// Class to run a task while a progress dialog is shown
/// </summary>
public class ProgressTask {
private readonly Handler _handler;
public class ProgressTask
{
//for handling Activity recreation situations, we need access to the currently active task. It must hold that there is no more than one active task.
private static ProgressTask _currentTask = null;
public static void SetNewActiveActivity(Activity activeActivity)
{
if (_currentTask != null)
{
_currentTask.ActiveActivity = activeActivity;
}
}
public static void RemoveActiveActivity(Activity activity)
{
if ((_currentTask != null) && (_currentTask._activeActivity == activity))
_currentTask.ActiveActivity = null;
}
public Activity ActiveActivity
{
get { return _activeActivity; }
private set
{
_activeActivity = value;
if (_task != null)
_task.ActiveActivity = _activeActivity;
if (_activeActivity != null)
{
SetupProgressDialog(_app);
_progressDialog.Show();
}
}
}
private readonly Handler _handler;
private readonly RunnableOnFinish _task;
private readonly IProgressDialog _progressDialog;
private IProgressDialog _progressDialog;
private readonly IKp2aApp _app;
private Thread _thread;
private Activity _activeActivity;
private ProgressDialogStatusLogger _progressDialogStatusLogger;
public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task) {
public ProgressTask(IKp2aApp app, Activity activity, RunnableOnFinish task)
{
_activeActivity = activity;
_task = task;
_handler = app.UiThreadHandler;
_app = app;
// Show process dialog
_progressDialog = app.CreateProgressDialog(ctx);
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
_progressDialog.SetMessage("Initializing...");
// Set code to run when this is finished
_task.OnFinishToRun = new AfterTask(task.OnFinishToRun, _handler, _progressDialog);
_task.SetStatusLogger(new ProgressDialogStatusLogger(_app, _handler, _progressDialog));
SetupProgressDialog(app);
// Set code to run when this is finished
_task.OnFinishToRun = new AfterTask(activity, task.OnFinishToRun, _handler, this);
_task.SetStatusLogger(_progressDialogStatusLogger);
}
public void Run() {
// Show process dialog
_progressDialog.Show();
private void SetupProgressDialog(IKp2aApp app)
{
string currentMessage = "Initializing...";
string currentSubmessage = "";
if (_progressDialogStatusLogger != null)
{
currentMessage = _progressDialogStatusLogger.Message;
currentSubmessage = _progressDialogStatusLogger.SubMessage;
}
if (_progressDialog != null)
{
var pd = _progressDialog;
app.UiThreadHandler.Post(() =>
{
pd.Dismiss();
});
}
// Show process dialog
_progressDialog = app.CreateProgressDialog(_activeActivity);
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
_progressDialogStatusLogger = new ProgressDialogStatusLogger(_app, _handler, _progressDialog);
_progressDialogStatusLogger.UpdateMessage(currentMessage);
_progressDialogStatusLogger.UpdateSubMessage(currentSubmessage);
}
public void Run(bool allowOverwriteCurrentTask = false)
{
if ((!allowOverwriteCurrentTask) && (_currentTask != null))
throw new Exception("Cannot start another ProgressTask while ProgressTask is already running! " + _task.GetType().Name + "/" + _currentTask._task.GetType().Name);
_currentTask = this;
// Show process dialog
_progressDialog.Show();
// Start Thread to Run task
_thread = new Thread(_task.Run);
_thread.Start();
}
public void JoinWorkerThread()
@@ -66,11 +134,11 @@ namespace keepass2android
}
private class AfterTask : OnFinish {
readonly IProgressDialog _progressDialog;
readonly ProgressTask _progressTask;
public AfterTask (OnFinish finish, Handler handler, IProgressDialog pd): base(finish, handler)
public AfterTask (Activity activity, OnFinish finish, Handler handler, ProgressTask pt): base(activity, finish, handler)
{
_progressDialog = pd;
_progressTask = pt;
}
public override void Run() {
@@ -79,17 +147,22 @@ namespace keepass2android
if (Handler != null) //can be null in tests
{
// Remove the progress dialog
Handler.Post(delegate { _progressDialog.Dismiss(); });
Handler.Post(delegate
{
_progressTask._progressDialog.Dismiss();
});
}
else
{
_progressDialog.Dismiss();
_progressTask._progressDialog.Dismiss();
}
_currentTask = null;
}
}
}
}

View File

@@ -63,7 +63,8 @@ namespace keepass2android
AskDeletePermanentlyItems,
AskDeletePermanentlyItemsNoRecycle,
InOfflineMode,
DuplicateTitle,
DocumentAccessRevoked,
DuplicateTitle,
TemplateTitle_IdCard,
TemplateField_IdCard_Name,
TemplateField_IdCard_PlaceOfIssue,
@@ -84,6 +85,7 @@ namespace keepass2android
AskAddTemplatesMessage,
ReadOnlyReason_PreKitKat,
ReadOnlyReason_ReadOnlyFlag,
ReadOnlyReason_ReadOnlyKitKat
ReadOnlyReason_ReadOnlyKitKat,
ReadOnlyReason_LocalBackup
}
}

View File

@@ -18,8 +18,8 @@ namespace keepass2android
private readonly IKp2aApp _app;
public CheckDatabaseForChanges(Context context, IKp2aApp app, OnFinish finish)
: base(finish)
public CheckDatabaseForChanges(Activity context, IKp2aApp app, OnFinish finish)
: base(context, finish)
{
_context = context;
_app = app;

View File

@@ -21,7 +21,6 @@ using System.IO;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using Android.Content;
using Java.Lang;
using KeePassLib;
using KeePassLib.Keys;
@@ -152,27 +151,20 @@ namespace keepass2android
set { _databaseFormat = value; }
}
public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
{
var iocAsHexString = IocAsHexString(ioc);
public string IocAsHexString()
{
return IoUtil.IocAsHexString(Ioc);
}
return "kp2a_ioc_" + iocAsHexString;
}
public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
{
var iocAsHexString = IoUtil.IocAsHexString(ioc);
public string IocAsHexString()
{
return IocAsHexString(Ioc);
}
return "kp2a_ioc_" + iocAsHexString;
}
private static string IocAsHexString(IOConnectionInfo ioc)
{
SHA256Managed sha256 = new SHA256Managed();
string iocAsHexString =
MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
return iocAsHexString;
}
public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
{
return GetFingerprintPrefKey(ioc) + "_mode";
}
@@ -225,7 +217,7 @@ namespace keepass2android
}
public void SaveData(Context ctx) {
public void SaveData() {
KpDatabase.UseFileTransactions = _app.GetBooleanPreference(PreferenceKey.UseFileTransactions);
using (IWriteTransaction trans = _app.GetFileStorage(Ioc).OpenWriteTransaction(Ioc, KpDatabase.UseFileTransactions))

View File

@@ -11,12 +11,12 @@ namespace keepass2android
{
public class SynchronizeCachedDatabase: RunnableOnFinish
{
private readonly Context _context;
private readonly Activity _context;
private readonly IKp2aApp _app;
private SaveDb _saveDb;
public SynchronizeCachedDatabase(Context context, IKp2aApp app, OnFinish finish)
: base(finish)
public SynchronizeCachedDatabase(Activity context, IKp2aApp app, OnFinish finish)
: base(context, finish)
{
_context = context;
_app = app;
@@ -59,7 +59,7 @@ namespace keepass2android
if (cachingFileStorage.HasLocalChanges(ioc))
{
//conflict! need to merge
_saveDb = new SaveDb(_context, _app, new ActionOnFinish((success, result) =>
_saveDb = new SaveDb(_context, _app, new ActionOnFinish(ActiveActivity, (success, result, activity) =>
{
if (!success)
{

View File

@@ -16,41 +16,37 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
*/
using System;
using Android.App;
using Android.OS;
namespace keepass2android
{
public class ActionOnFinish: OnFinish
{
public delegate void ActionToPerformOnFinsh(bool success, String message);
public delegate void ActionToPerformOnFinsh(bool success, String message, Activity activeActivity);
readonly ActionToPerformOnFinsh _actionToPerform;
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform) : base(null, null)
public ActionOnFinish(Activity activity, ActionToPerformOnFinsh actionToPerform) : base(activity, null, null)
{
_actionToPerform = actionToPerform;
}
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, OnFinish finish) : base(finish)
public ActionOnFinish(Activity activity, ActionToPerformOnFinsh actionToPerform, OnFinish finish) : base(activity, finish)
{
_actionToPerform = actionToPerform;
}
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, Handler handler) : base(handler)
{
_actionToPerform = actionToPerform;
}
public override void Run()
{
if (Message == null)
Message = "";
if (Handler != null)
{
Handler.Post(() => {_actionToPerform(Success, Message);});
Handler.Post(() => {_actionToPerform(Success, Message, ActiveActivity);});
}
else
_actionToPerform(Success, Message);
_actionToPerform(Success, Message, ActiveActivity);
base.Run();
}
}

View File

@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using Android.App;
using Android.Content;
using KeePassLib;
@@ -29,20 +30,20 @@ namespace keepass2android
private readonly IKp2aApp _app;
private readonly PwEntry _entry;
private readonly PwGroup _parentGroup;
private readonly Context _ctx;
private readonly Activity _ctx;
public static AddEntry GetInstance(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) {
public static AddEntry GetInstance(Activity ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) {
return new AddEntry(ctx, app, entry, parentGroup, finish);
}
protected AddEntry(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(finish) {
protected AddEntry(Activity ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(ctx, finish) {
_ctx = ctx;
_parentGroup = parentGroup;
_app = app;
_entry = entry;
_onFinishToRun = new AfterAdd(app.GetDb(), entry, OnFinishToRun);
_onFinishToRun = new AfterAdd(ctx, app.GetDb(), entry, OnFinishToRun);
}
@@ -68,7 +69,7 @@ namespace keepass2android
private readonly Database _db;
private readonly PwEntry _entry;
public AfterAdd(Database db, PwEntry entry, OnFinish finish):base(finish) {
public AfterAdd(Activity activity, Database db, PwEntry entry, OnFinish finish):base(activity, finish) {
_db = db;
_entry = entry;

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
using Android.App;
using Android.Content;
using KeePassLib;
@@ -34,16 +35,16 @@ namespace keepass2android
internal PwGroup Group;
internal PwGroup Parent;
protected bool DontSave;
readonly Context _ctx;
readonly Activity _ctx;
public static AddGroup GetInstance(Context ctx, IKp2aApp app, string name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave) {
public static AddGroup GetInstance(Activity ctx, IKp2aApp app, string name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave) {
return new AddGroup(ctx, app, name, iconid, groupCustomIconId, parent, finish, dontSave);
}
private AddGroup(Context ctx, IKp2aApp app, String name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave)
: base(finish)
private AddGroup(Activity ctx, IKp2aApp app, String name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave)
: base(ctx, finish)
{
_ctx = ctx;
_name = name;
@@ -53,7 +54,7 @@ namespace keepass2android
DontSave = dontSave;
_app = app;
_onFinishToRun = new AfterAdd(this, OnFinishToRun);
_onFinishToRun = new AfterAdd(ctx, this, OnFinishToRun);
}
@@ -76,7 +77,7 @@ namespace keepass2android
private class AfterAdd : OnFinish {
readonly AddGroup _addGroup;
public AfterAdd(AddGroup addGroup,OnFinish finish): base(finish) {
public AfterAdd(Activity activity, AddGroup addGroup,OnFinish finish): base(activity, finish) {
_addGroup = addGroup;
}

View File

@@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2016 Philipp Crocoll. This file
using System;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Security;
@@ -128,10 +129,10 @@ namespace keepass2android
}
private readonly IKp2aApp _app;
private readonly Context _ctx;
private readonly Activity _ctx;
public AddTemplateEntries(Context ctx, IKp2aApp app, OnFinish finish)
: base(finish)
public AddTemplateEntries(Activity ctx, IKp2aApp app, OnFinish finish)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
@@ -358,7 +359,7 @@ namespace keepass2android
private readonly Database _db;
private readonly List<PwEntry> _entries;
public AfterAdd(Database db, List<PwEntry> entries, OnFinish finish):base(finish) {
public AfterAdd(Activity activity, Database db, List<PwEntry> entries, OnFinish finish):base(activity, finish) {
_db = db;
_entries = entries;

View File

@@ -16,7 +16,7 @@ namespace keepass2android.database.edit
{
public class CopyEntry: AddEntry
{
public CopyEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish)
public CopyEntry(Activity ctx, IKp2aApp app, PwEntry entry, OnFinish finish)
: base(ctx, app, CreateCopy(entry, app), entry.ParentGroup, finish)
{
}

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System.Collections.Generic;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Cryptography.KeyDerivation;
@@ -31,19 +32,19 @@ namespace keepass2android
private readonly IOConnectionInfo _ioc;
private readonly bool _dontSave;
private readonly Context _ctx;
private readonly Activity _ctx;
private readonly IKp2aApp _app;
private CompositeKey _key;
public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(finish) {
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(ctx, finish) {
_ctx = ctx;
_ioc = ioc;
_dontSave = dontSave;
_app = app;
}
public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key)
: base(finish)
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key)
: base(ctx, finish)
{
_ctx = ctx;
_ioc = ioc;

View File

@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Interfaces;
@@ -28,8 +29,8 @@ namespace keepass2android
private readonly PwEntry _entry;
private UiStringKey _statusMessage;
public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish):base(finish, app) {
Ctx = ctx;
public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) {
Ctx = activiy;
Db = app.GetDb();
_entry = entry;

View File

@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using KeePassLib;
@@ -28,10 +29,10 @@ namespace keepass2android
private PwGroup _group;
protected bool DontSave;
public DeleteGroup(Context ctx, IKp2aApp app, PwGroup group, OnFinish finish)
: base(finish, app)
public DeleteGroup(Activity activity, IKp2aApp app, PwGroup group, OnFinish finish)
: base(activity, finish, app)
{
SetMembers(ctx, app, group, false);
SetMembers(activity, app, group, false);
}
/*
public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave)
@@ -44,9 +45,9 @@ namespace keepass2android
SetMembers(ctx, db, group, null, dontSave);
}
*/
private void SetMembers(Context ctx, IKp2aApp app, PwGroup group, bool dontSave)
private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave)
{
base.SetMembers(ctx, app.GetDb());
base.SetMembers(activity, app.GetDb());
_group = group;
DontSave = dontSave;

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Interfaces;
@@ -11,11 +12,11 @@ namespace keepass2android
private readonly List<IStructureItem> _elementsToDelete;
private readonly bool _canRecycle;
public DeleteMultipleItems(Context ctx, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
: base(finish, app)
public DeleteMultipleItems(Activity activity, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
: base(activity, finish, app)
{
_elementsToDelete = elementsToDelete;
SetMembers(ctx, db);
SetMembers(activity, db);
//determine once. The property is queried for each delete operation, but might return false
//after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using KeePassLib;
@@ -7,8 +8,8 @@ namespace keepass2android
{
public abstract class DeleteRunnable : RunnableOnFinish
{
protected DeleteRunnable(OnFinish finish, IKp2aApp app)
: base(finish)
protected DeleteRunnable(Activity activity, OnFinish finish, IKp2aApp app)
: base(activity, finish)
{
App = app;
}
@@ -17,11 +18,11 @@ namespace keepass2android
protected Database Db;
protected Context Ctx;
protected Activity Ctx;
protected void SetMembers(Context ctx, Database db)
protected void SetMembers(Activity activity, Database db)
{
Ctx = ctx;
Ctx = activity;
Db = db;
}
@@ -209,7 +210,7 @@ namespace keepass2android
Android.Util.Log.Debug("KP2A", "Calling PerformDelete..");
PerformDelete(touchedGroups, permanentlyDeletedGroups);
_onFinishToRun = new ActionOnFinish((success, message) =>
_onFinishToRun = new ActionOnFinish(ActiveActivity,(success, message, activity) =>
{
if (success)
{

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
using Android.App;
using Android.Content;
using KeePassLib;
@@ -32,10 +33,10 @@ namespace keepass2android
private readonly PwIcon _iconId;
private readonly PwUuid _customIconId;
internal PwGroup Group;
readonly Context _ctx;
readonly Activity _ctx;
public EditGroup(Context ctx, IKp2aApp app, String name, PwIcon iconid, PwUuid customIconId, PwGroup group, OnFinish finish)
: base(finish)
public EditGroup(Activity ctx, IKp2aApp app, String name, PwIcon iconid, PwUuid customIconId, PwGroup group, OnFinish finish)
: base(ctx, finish)
{
_ctx = ctx;
_name = name;
@@ -44,7 +45,7 @@ namespace keepass2android
_customIconId = customIconId;
_app = app;
_onFinishToRun = new AfterEdit(this, OnFinishToRun);
_onFinishToRun = new AfterEdit(ctx, this, OnFinishToRun);
}
@@ -64,8 +65,8 @@ namespace keepass2android
private class AfterEdit : OnFinish {
readonly EditGroup _editGroup;
public AfterEdit(EditGroup editGroup, OnFinish finish)
: base(finish)
public AfterEdit(Activity ctx, EditGroup editGroup, OnFinish finish)
: base(ctx, finish)
{
_editGroup = editGroup;
}

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
using Android.App;
namespace keepass2android
{
@@ -23,7 +24,7 @@ namespace keepass2android
public abstract class FileOnFinish : OnFinish {
private String _filename = "";
protected FileOnFinish(FileOnFinish finish):base(finish) {
protected FileOnFinish(Activity activity, FileOnFinish finish):base(activity, finish) {
}
public string Filename

View File

@@ -18,7 +18,9 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
@@ -34,7 +36,7 @@ namespace keepass2android
private readonly bool _rememberKeyfile;
IDatabaseFormat _format;
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(finish)
public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(activity, finish)
{
_app = app;
_ioc = ioc;
@@ -53,9 +55,11 @@ namespace keepass2android
{
try
{
//make sure the file data is stored in the recent files list even if loading fails
SaveFileData(_ioc, _keyfileOrProvider);
StatusLogger.UpdateMessage(UiStringKey.loading_database);
StatusLogger.UpdateMessage(UiStringKey.loading_database);
//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not:
MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result;
MemoryStream databaseStream;
@@ -134,10 +138,14 @@ namespace keepass2android
//now let's go:
try
{
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
SaveFileData(_ioc, _keyfileOrProvider);
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
Kp2aLog.Log("LoadDB OK");
Finish(true, _format.SuccessMessage);
//make sure the stored access time for the actual file is more recent than that of its backup
Thread.Sleep(10);
SaveFileData(_ioc, _keyfileOrProvider);
Finish(true, _format.SuccessMessage);
}
catch (OldFormatException)
{

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Interfaces;
@@ -12,10 +13,10 @@ namespace keepass2android.database.edit
{
private readonly List<IStructureItem> _elementsToMove;
private readonly PwGroup _targetGroup;
private readonly Context _ctx;
private readonly Activity _ctx;
private readonly IKp2aApp _app;
public MoveElements(List<IStructureItem> elementsToMove, PwGroup targetGroup, Context ctx, IKp2aApp app, OnFinish finish) : base(finish)
public MoveElements(List<IStructureItem> elementsToMove, PwGroup targetGroup, Activity ctx, IKp2aApp app, OnFinish finish) : base(ctx, finish)
{
_elementsToMove = elementsToMove;
_targetGroup = targetGroup;
@@ -82,7 +83,7 @@ namespace keepass2android.database.edit
}
_onFinishToRun = new ActionOnFinish((success, message) =>
_onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
{
if (!success)
{ // Let's not bother recovering from a failure.

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
@@ -31,27 +32,47 @@ namespace keepass2android
protected OnFinish BaseOnFinish;
protected Handler Handler;
private ProgressDialogStatusLogger _statusLogger = new ProgressDialogStatusLogger(); //default: no logging but not null -> can be used whenever desired
private Activity _activeActivity;
public ProgressDialogStatusLogger StatusLogger
public ProgressDialogStatusLogger StatusLogger
{
get { return _statusLogger; }
set { _statusLogger = value; }
}
public Activity ActiveActivity
{
get { return _activeActivity; }
set
{
_activeActivity = value;
if (BaseOnFinish != null)
{
BaseOnFinish.ActiveActivity = value;
}
}
}
protected OnFinish(Handler handler) {
protected OnFinish(Activity activeActivity, Handler handler)
{
ActiveActivity = activeActivity;
BaseOnFinish = null;
Handler = handler;
}
protected OnFinish(OnFinish finish, Handler handler) {
protected OnFinish(Activity activeActivity, OnFinish finish, Handler handler)
{
ActiveActivity = activeActivity;
BaseOnFinish = finish;
Handler = handler;
}
protected OnFinish(OnFinish finish) {
protected OnFinish(Activity activeActivity, OnFinish finish)
{
ActiveActivity = activeActivity;
BaseOnFinish = finish;
Handler = null;
}
@@ -86,7 +107,7 @@ namespace keepass2android
{
if ( !String.IsNullOrEmpty(message) ) {
Kp2aLog.Log("OnFinish message: "+message);
Toast.MakeText(ctx, message, ToastLength.Long).Show();
Toast.MakeText(ctx ?? Application.Context, message, ToastLength.Long).Show();
}
}
}

View File

@@ -15,6 +15,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using Android.App;
using Android.Content;
namespace keepass2android
{
@@ -23,8 +25,11 @@ namespace keepass2android
protected OnFinish _onFinishToRun;
public ProgressDialogStatusLogger StatusLogger = new ProgressDialogStatusLogger(); //default: empty but not null
private Activity _activeActivity;
protected RunnableOnFinish(OnFinish finish) {
protected RunnableOnFinish(Activity activeActivity, OnFinish finish)
{
_activeActivity = activeActivity;
_onFinishToRun = finish;
}
@@ -34,7 +39,18 @@ namespace keepass2android
set { _onFinishToRun = value; }
}
protected void Finish(bool result, String message, Exception exception = null) {
public Activity ActiveActivity
{
get { return _activeActivity; }
set
{
_activeActivity = value;
if (_onFinishToRun != null)
_onFinishToRun.ActiveActivity = _activeActivity;
}
}
protected void Finish(bool result, String message, Exception exception = null) {
if ( OnFinishToRun != null ) {
OnFinishToRun.SetResult(result, message, exception);
OnFinishToRun.Run();
@@ -56,7 +72,7 @@ namespace keepass2android
StatusLogger = status;
}
abstract public void Run();
public abstract void Run();
}
}

View File

@@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using System.IO;
using System.Security.Cryptography;
using Android.App;
using Android.Content;
using Android.OS;
using Java.Lang;
@@ -42,8 +43,8 @@ namespace keepass2android
private readonly Context _ctx;
private Thread _workerThread;
public SaveDb(Context ctx, IKp2aApp app, OnFinish finish, bool dontSave)
: base(finish)
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish, bool dontSave)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
@@ -58,8 +59,8 @@ namespace keepass2android
/// <param name="finish"></param>
/// <param name="dontSave"></param>
/// <param name="streamForOrigFile">Stream for reading the data from the (changed) original location</param>
public SaveDb(Context ctx, IKp2aApp app, OnFinish finish, bool dontSave, Stream streamForOrigFile)
: base(finish)
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish, bool dontSave, Stream streamForOrigFile)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
@@ -67,8 +68,8 @@ namespace keepass2android
_streamForOrigFile = streamForOrigFile;
}
public SaveDb(Context ctx, IKp2aApp app, OnFinish finish)
: base(finish)
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
@@ -248,7 +249,7 @@ namespace keepass2android
private void PerformSaveWithoutCheck(IFileStorage fileStorage, IOConnectionInfo ioc)
{
StatusLogger.UpdateSubMessage("");
_app.GetDb().SaveData(_ctx);
_app.GetDb().SaveData();
_app.GetDb().LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc);
}

View File

@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using Android.App;
using Android.Content;
using KeePassLib;
using KeePassLib.Keys;
@@ -27,9 +28,9 @@ namespace keepass2android
private readonly String _keyfile;
private readonly IKp2aApp _app;
private readonly bool _dontSave;
private readonly Context _ctx;
private readonly Activity _ctx;
public SetPassword(Context ctx, IKp2aApp app, String password, String keyfile, OnFinish finish): base(finish) {
public SetPassword(Activity ctx, IKp2aApp app, String password, String keyfile, OnFinish finish): base(ctx, finish) {
_ctx = ctx;
_app = app;
_password = password;
@@ -37,8 +38,8 @@ namespace keepass2android
_dontSave = false;
}
public SetPassword(Context ctx, IKp2aApp app, String password, String keyfile, OnFinish finish, bool dontSave)
: base(finish)
public SetPassword(Activity ctx, IKp2aApp app, String password, String keyfile, OnFinish finish, bool dontSave)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
@@ -72,7 +73,7 @@ namespace keepass2android
pm.MasterKey = newKey;
// Save Database
_onFinishToRun = new AfterSave(previousKey, previousMasterKeyChanged, pm, OnFinishToRun);
_onFinishToRun = new AfterSave(ActiveActivity, previousKey, previousMasterKeyChanged, pm, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, _dontSave);
save.SetStatusLogger(StatusLogger);
save.Run();
@@ -83,7 +84,7 @@ namespace keepass2android
private readonly DateTime _previousKeyChanged;
private readonly PwDatabase _db;
public AfterSave(CompositeKey backup, DateTime previousKeyChanged, PwDatabase db, OnFinish finish): base(finish) {
public AfterSave(Activity activity, CompositeKey backup, DateTime previousKeyChanged, PwDatabase db, OnFinish finish): base(activity, finish) {
_previousKeyChanged = previousKeyChanged;
_backup = backup;
_db = db;

View File

@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using Android.App;
using Android.Content;
using KeePassLib;
@@ -23,13 +24,13 @@ namespace keepass2android
public class UpdateEntry : RunnableOnFinish {
private readonly IKp2aApp _app;
private readonly Context _ctx;
private readonly Activity _ctx;
public UpdateEntry(Context ctx, IKp2aApp app, PwEntry oldE, PwEntry newE, OnFinish finish):base(finish) {
public UpdateEntry(Activity ctx, IKp2aApp app, PwEntry oldE, PwEntry newE, OnFinish finish):base(ctx, finish) {
_ctx = ctx;
_app = app;
_onFinishToRun = new AfterUpdate(oldE, newE, app, finish);
_onFinishToRun = new AfterUpdate(ctx, oldE, newE, app, finish);
}
@@ -45,7 +46,7 @@ namespace keepass2android
private readonly PwEntry _updatedEntry;
private readonly IKp2aApp _app;
public AfterUpdate(PwEntry backup, PwEntry updatedEntry, IKp2aApp app, OnFinish finish):base(finish) {
public AfterUpdate(Activity activity, PwEntry backup, PwEntry updatedEntry, IKp2aApp app, OnFinish finish):base(activity, finish) {
_backup = backup;
_updatedEntry = updatedEntry;
_app = app;

View File

@@ -1,4 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Xamarin.Android.Arch.Core.Common" version="1.0.0" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Arch.Lifecycle.Common" version="1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Arch.Lifecycle.Runtime" version="1.0.0" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Annotations" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Core.UI" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Core.Utils" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Fragment" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Media.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.v13" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.v4" version="23.1.1.0" targetFramework="MonoAndroid50" />
</packages>

View File

@@ -11,7 +11,7 @@
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<AssemblyName>Kp2aKeyboardBinding</AssemblyName>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>

View File

@@ -10,8 +10,8 @@
<RootNamespace>PluginSdkBinding</RootNamespace>
<AssemblyName>PluginSdkBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -13,7 +13,7 @@
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -13,7 +13,7 @@
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<AssemblyName>ZlibAndroid</AssemblyName>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -32,11 +32,11 @@ dependencies {
compile 'com.google.apis:google-api-services-drive:v2-rev102-1.16.0-rc'
compile 'com.dropbox.core:dropbox-core-sdk:3.0.3'
//onedrive:
compile('com.onedrive.sdk:onedrive-sdk-android:1.2+') {
compile('com.onedrive.sdk:onedrive-sdk-android:1.2.0') {
transitive = false
}
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.microsoft.services.msa:msa-auth:0.8.+'
compile 'com.microsoft.aad:adal:1.1.+'
compile 'com.microsoft.services.msa:msa-auth:0.8.6'
compile 'com.microsoft.aad:adal:1.14.0'
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -213,8 +213,11 @@ public class Buffer{
}
void checkFreeSize(int n){
if(buffer.length<index+n){
byte[] tmp = new byte[buffer.length*2];
int size = index+n+Session.buffer_margin;
if(buffer.length<size){
int i = buffer.length*2;
if(i<size) i = size;
byte[] tmp = new byte[i];
System.arraycopy(buffer, 0, tmp, 0, index);
buffer = tmp;
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -192,29 +192,38 @@ public abstract class Channel implements Runnable{
io.setExtOutputStream(out, dontclose);
}
public InputStream getInputStream() throws IOException {
PipedInputStream in=
int max_input_buffer_size = 32*1024;
try {
max_input_buffer_size =
Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
}
catch(Exception e){}
PipedInputStream in =
new MyPipedInputStream(
32*1024 // this value should be customizable.
32*1024, // this value should be customizable.
max_input_buffer_size
);
io.setOutputStream(new PassiveOutputStream(in), false);
boolean resizable = 32*1024<max_input_buffer_size;
io.setOutputStream(new PassiveOutputStream(in, resizable), false);
return in;
}
public InputStream getExtInputStream() throws IOException {
PipedInputStream in=
int max_input_buffer_size = 32*1024;
try {
max_input_buffer_size =
Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
}
catch(Exception e){}
PipedInputStream in =
new MyPipedInputStream(
32*1024 // this value should be customizable.
32*1024, // this value should be customizable.
max_input_buffer_size
);
io.setExtOutputStream(new PassiveOutputStream(in), false);
boolean resizable = 32*1024<max_input_buffer_size;
io.setExtOutputStream(new PassiveOutputStream(in, resizable), false);
return in;
}
public OutputStream getOutputStream() throws IOException {
/*
PipedOutputStream out=new PipedOutputStream();
io.setInputStream(new PassiveInputStream(out
, 32*1024
), false);
return out;
*/
final Channel channel=this;
OutputStream out=new OutputStream(){
@@ -317,15 +326,24 @@ public abstract class Channel implements Runnable{
}
class MyPipedInputStream extends PipedInputStream{
private int BUFFER_SIZE = 1024;
private int max_buffer_size = BUFFER_SIZE;
MyPipedInputStream() throws IOException{ super(); }
MyPipedInputStream(int size) throws IOException{
super();
buffer=new byte[size];
BUFFER_SIZE = size;
max_buffer_size = size;
}
MyPipedInputStream(int size, int max_buffer_size) throws IOException{
this(size);
this.max_buffer_size = max_buffer_size;
}
MyPipedInputStream(PipedOutputStream out) throws IOException{ super(out); }
MyPipedInputStream(PipedOutputStream out, int size) throws IOException{
super(out);
buffer=new byte[size];
BUFFER_SIZE=size;
}
/*
@@ -343,12 +361,66 @@ public abstract class Channel implements Runnable{
buffer[in++] = 0;
read();
}
private int freeSpace(){
int size = 0;
if(out < in) {
size = buffer.length-in;
}
else if(in < out){
if(in == -1) size = buffer.length;
else size = out - in;
}
return size;
}
synchronized void checkSpace(int len) throws IOException {
int size = freeSpace();
if(size<len){
int datasize=buffer.length-size;
int foo = buffer.length;
while((foo - datasize) < len){
foo*=2;
}
if(foo > max_buffer_size){
foo = max_buffer_size;
}
if((foo - datasize) < len) return;
byte[] tmp = new byte[foo];
if(out < in) {
System.arraycopy(buffer, 0, tmp, 0, buffer.length);
}
else if(in < out){
if(in == -1) {
}
else {
System.arraycopy(buffer, 0, tmp, 0, in);
System.arraycopy(buffer, out,
tmp, tmp.length-(buffer.length-out),
(buffer.length-out));
out = tmp.length-(buffer.length-out);
}
}
else if(in == out){
System.arraycopy(buffer, 0, tmp, 0, buffer.length);
in=buffer.length;
}
buffer=tmp;
}
else if(buffer.length == size && size > BUFFER_SIZE) {
int i = size/2;
if(i<BUFFER_SIZE) i = BUFFER_SIZE;
byte[] tmp = new byte[i];
buffer=tmp;
}
}
}
void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; }
void setLocalWindowSize(int foo){ this.lwsize=foo; }
void setLocalPacketSize(int foo){ this.lmpsize=foo; }
synchronized void setRemoteWindowSize(long foo){ this.rwsize=foo; }
synchronized void addRemoteWindowSize(int foo){
synchronized void addRemoteWindowSize(long foo){
this.rwsize+=foo;
if(notifyme>0)
notifyAll();
@@ -384,12 +456,15 @@ public abstract class Channel implements Runnable{
if(eof_local)return;
eof_local=true;
int i = getRecipient();
if(i == -1) return;
try{
Buffer buf=new Buffer(100);
Packet packet=new Packet(buf);
packet.reset();
buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF);
buf.putInt(getRecipient());
buf.putInt(i);
synchronized(this){
if(!close)
getSession().write(packet);
@@ -445,12 +520,15 @@ public abstract class Channel implements Runnable{
close=true;
eof_local=eof_remote=true;
int i = getRecipient();
if(i == -1) return;
try{
Buffer buf=new Buffer(100);
Packet packet=new Packet(buf);
packet.reset();
buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE);
buf.putInt(getRecipient());
buf.putInt(i);
synchronized(this){
getSession().write(packet);
}
@@ -561,8 +639,25 @@ public abstract class Channel implements Runnable{
}
}
class PassiveOutputStream extends PipedOutputStream{
PassiveOutputStream(PipedInputStream in) throws IOException{
private MyPipedInputStream _sink=null;
PassiveOutputStream(PipedInputStream in,
boolean resizable_buffer) throws IOException{
super(in);
if(resizable_buffer && (in instanceof MyPipedInputStream)) {
this._sink=(MyPipedInputStream)in;
}
}
public void write(int b) throws IOException {
if(_sink != null) {
_sink.checkSpace(1);
}
super.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
if(_sink != null) {
_sink.checkSpace(len);
}
super.write(b, off, len);
}
}
@@ -636,7 +731,7 @@ public abstract class Channel implements Runnable{
Packet packet = genChannelOpenPacket();
_session.write(packet);
int retry=10;
int retry=2000;
long start=System.currentTimeMillis();
long timeout=connectTimeout;
if(timeout!=0L) retry = 1;
@@ -651,7 +746,7 @@ public abstract class Channel implements Runnable{
}
}
try{
long t = timeout==0L ? 5000L : timeout;
long t = timeout==0L ? 10L : timeout;
this.notifyme=1;
wait(t);
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2006-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -120,7 +120,16 @@ public class ChannelDirectTCPIP extends Channel{
}
}
catch(Exception e){
// Whenever an exception is thrown by sendChannelOpen(),
// 'connected' is false.
if(!connected){
connected=true;
}
disconnect();
return;
}
eof();
disconnect();
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -648,7 +648,6 @@ public class ChannelSftp extends ChannelSession{
if((seq-1)==startid ||
((seq-startid)-ackcount)>=bulk_requests){
while(((seq-startid)-ackcount)>=bulk_requests){
if(this.rwsize>=foo) break;
if(checkStatus(ackid, header)){
int _ackid = ackid[0];
if(startid>_ackid || _ackid>seq-1){
@@ -666,7 +665,16 @@ public class ChannelSftp extends ChannelSession{
}
}
}
foo-=sendWRITE(handle, offset, data, 0, foo);
if(dontcopy){
foo-=sendWRITE(handle, offset, data, 0, foo);
if(data!=obuf.buffer){
data=obuf.buffer;
_datalen=obuf.buffer.length-_s-Session.buffer_margin;
}
}
else {
foo-=sendWRITE(handle, offset, data, _s, foo);
}
}
offset+=count;
if(monitor!=null && !monitor.count(count)){
@@ -736,6 +744,12 @@ public class ChannelSftp extends ChannelSession{
}
}
if(monitor!=null){
monitor.init(SftpProgressMonitor.PUT,
"-", dst,
SftpProgressMonitor.UNKNOWN_SIZE);
}
if(mode==OVERWRITE){ sendOPENW(dstb); }
else{ sendOPENA(dstb); }
@@ -923,6 +937,15 @@ public class ChannelSftp extends ChannelSession{
if(i==-1) dstsb.append(_src);
else dstsb.append(_src.substring(i + 1));
_dst=dstsb.toString();
if(_dst.indexOf("..")!=-1){
String dstc = (new java.io.File(dst)).getCanonicalPath();
String _dstc = (new java.io.File(_dst)).getCanonicalPath();
if(!(_dstc.length()>dstc.length() &&
_dstc.substring(0, dstc.length()+1).equals(dstc+file_separator))){
throw new SftpException(SSH_FX_FAILURE,
"writing to an unexpected file "+_src);
}
}
dstsb.delete(dst.length(), _dst.length());
}
else{
@@ -1375,7 +1398,10 @@ public class ChannelSftp extends ChannelSession{
len=1024;
}
if(rq.count()==0) {
if(rq.count()==0
|| true // working around slow transfer speed for
// some sftp servers including Titan FTP.
) {
int request_len = buf.buffer.length-13;
if(server_version==0){ request_len=1024; }
@@ -1782,10 +1808,17 @@ public class ChannelSftp extends ChannelSession{
try{
((MyPipedInputStream)io_in).updateReadSide();
oldpath=remoteAbsolutePath(oldpath);
String _oldpath=remoteAbsolutePath(oldpath);
newpath=remoteAbsolutePath(newpath);
oldpath=isUnique(oldpath);
_oldpath=isUnique(_oldpath);
if(oldpath.charAt(0)!='/'){ // relative path
String cwd=getCwd();
oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith("/")?0:1));
}
else {
oldpath=_oldpath;
}
if(isPattern(newpath)){
throw new SftpException(SSH_FX_FAILURE, newpath);
@@ -1827,10 +1860,17 @@ public class ChannelSftp extends ChannelSession{
try{
((MyPipedInputStream)io_in).updateReadSide();
oldpath=remoteAbsolutePath(oldpath);
String _oldpath=remoteAbsolutePath(oldpath);
newpath=remoteAbsolutePath(newpath);
oldpath=isUnique(oldpath);
_oldpath=isUnique(_oldpath);
if(oldpath.charAt(0)!='/'){ // relative path
String cwd=getCwd();
oldpath=_oldpath.substring(cwd.length()+(cwd.endsWith("/")?0:1));
}
else {
oldpath=_oldpath;
}
if(isPattern(newpath)){
throw new SftpException(SSH_FX_FAILURE, newpath);

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2005-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2013 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2013-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -36,4 +36,8 @@ public interface DH{
byte[] getE() throws Exception;
void setF(byte[] f);
byte[] getK() throws Exception;
// checkRange() will check if e and f are in [1,p-1]
// as defined at https://tools.ietf.org/html/rfc4253#section-8
void checkRange() throws Exception;
}

View File

@@ -0,0 +1,37 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2015-2016 ymnk, JCraft,Inc. 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.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
*/
package com.jcraft.jsch;
public class DHEC256 extends DHECN {
public DHEC256(){
sha_name="sha-256";
key_size=256;
}
}

View File

@@ -0,0 +1,37 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2015-2016 ymnk, JCraft,Inc. 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.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
*/
package com.jcraft.jsch;
public class DHEC384 extends DHECN {
public DHEC384(){
sha_name="sha-384";
key_size=384;
}
}

View File

@@ -0,0 +1,37 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2015-2016 ymnk, JCraft,Inc. 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.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
*/
package com.jcraft.jsch;
public class DHEC521 extends DHECN {
public DHEC521(){
sha_name="sha-512";
key_size=521;
}
}

View File

@@ -0,0 +1,187 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2015-2016 ymnk, JCraft,Inc. 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.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
*/
package com.jcraft.jsch;
public abstract class DHECN extends KeyExchange{
private static final int SSH_MSG_KEX_ECDH_INIT = 30;
private static final int SSH_MSG_KEX_ECDH_REPLY= 31;
private int state;
byte[] Q_C;
byte[] V_S;
byte[] V_C;
byte[] I_S;
byte[] I_C;
byte[] e;
private Buffer buf;
private Packet packet;
private ECDH ecdh;
protected String sha_name;
protected int key_size;
public void init(Session session,
byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
this.session=session;
this.V_S=V_S;
this.V_C=V_C;
this.I_S=I_S;
this.I_C=I_C;
try{
Class c=Class.forName(session.getConfig(sha_name));
sha=(HASH)(c.newInstance());
sha.init();
}
catch(Exception e){
System.err.println(e);
}
buf=new Buffer();
packet=new Packet(buf);
packet.reset();
buf.putByte((byte)SSH_MSG_KEX_ECDH_INIT);
try{
Class c=Class.forName(session.getConfig("ecdh-sha2-nistp"));
ecdh=(ECDH)(c.newInstance());
ecdh.init(key_size);
Q_C = ecdh.getQ();
buf.putString(Q_C);
}
catch(Exception e){
if(e instanceof Throwable)
throw new JSchException(e.toString(), (Throwable)e);
throw new JSchException(e.toString());
}
if(V_S==null){ // This is a really ugly hack for Session.checkKexes ;-(
return;
}
session.write(packet);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"SSH_MSG_KEX_ECDH_INIT sent");
JSch.getLogger().log(Logger.INFO,
"expecting SSH_MSG_KEX_ECDH_REPLY");
}
state=SSH_MSG_KEX_ECDH_REPLY;
}
public boolean next(Buffer _buf) throws Exception{
int i,j;
switch(state){
case SSH_MSG_KEX_ECDH_REPLY:
// The server responds with:
// byte SSH_MSG_KEX_ECDH_REPLY
// string K_S, server's public host key
// string Q_S, server's ephemeral public key octet string
// string the signature on the exchange hash
j=_buf.getInt();
j=_buf.getByte();
j=_buf.getByte();
if(j!=31){
System.err.println("type: must be 31 "+j);
return false;
}
K_S=_buf.getString();
byte[] Q_S=_buf.getString();
byte[][] r_s = KeyPairECDSA.fromPoint(Q_S);
// RFC 5656,
// 4. ECDH Key Exchange
// All elliptic curve public keys MUST be validated after they are
// received. An example of a validation algorithm can be found in
// Section 3.2.2 of [SEC1]. If a key fails validation,
// the key exchange MUST fail.
if(!ecdh.validate(r_s[0], r_s[1])){
return false;
}
K = ecdh.getSecret(r_s[0], r_s[1]);
K=normalize(K);
byte[] sig_of_H=_buf.getString();
//The hash H is computed as the HASH hash of the concatenation of the
//following:
// string V_C, client's identification string (CR and LF excluded)
// string V_S, server's identification string (CR and LF excluded)
// string I_C, payload of the client's SSH_MSG_KEXINIT
// string I_S, payload of the server's SSH_MSG_KEXINIT
// string K_S, server's public host key
// string Q_C, client's ephemeral public key octet string
// string Q_S, server's ephemeral public key octet string
// mpint K, shared secret
// This value is called the exchange hash, and it is used to authenti-
// cate the key exchange.
buf.reset();
buf.putString(V_C); buf.putString(V_S);
buf.putString(I_C); buf.putString(I_S);
buf.putString(K_S);
buf.putString(Q_C); buf.putString(Q_S);
buf.putMPInt(K);
byte[] foo=new byte[buf.getLength()];
buf.getByte(foo);
sha.update(foo, 0, foo.length);
H=sha.digest();
i=0;
j=0;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
String alg=Util.byte2str(K_S, i, j);
i+=j;
boolean result = verify(alg, K_S, i, sig_of_H);
state=STATE_END;
return result;
}
return false;
}
public int getState(){return state; }
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -55,25 +55,15 @@ public class DHG1 extends KeyExchange{
private static final int SSH_MSG_KEXDH_INIT= 30;
private static final int SSH_MSG_KEXDH_REPLY= 31;
static final int RSA=0;
static final int DSS=1;
private int type=0;
private int state;
DH dh;
// HASH sha;
// byte[] K;
// byte[] H;
byte[] V_S;
byte[] V_C;
byte[] I_S;
byte[] I_C;
// byte[] K_S;
byte[] e;
private Buffer buf;
@@ -87,8 +77,6 @@ public class DHG1 extends KeyExchange{
this.I_S=I_S;
this.I_C=I_C;
// sha=new SHA1();
// sha.init();
try{
Class c=Class.forName(session.getConfig("sha-1"));
sha=(HASH)(c.newInstance());
@@ -155,24 +143,14 @@ public class DHG1 extends KeyExchange{
}
K_S=_buf.getString();
// K_S is server_key_blob, which includes ....
// string ssh-dss
// impint p of dsa
// impint q of dsa
// impint g of dsa
// impint pub_key of dsa
//System.err.print("K_S: "); //dump(K_S, 0, K_S.length);
byte[] f=_buf.getMPInt();
byte[] sig_of_H=_buf.getString();
/*
for(int ii=0; ii<sig_of_H.length;ii++){
System.err.print(Integer.toHexString(sig_of_H[ii]&0xff));
System.err.print(": ");
}
System.err.println("");
*/
dh.setF(f);
dh.checkRange();
K=normalize(dh.getK());
//The hash H is computed as the HASH hash of the concatenation of the
@@ -206,105 +184,13 @@ System.err.println("");
String alg=Util.byte2str(K_S, i, j);
i+=j;
boolean result=false;
boolean result = verify(alg, K_S, i, sig_of_H);
if(alg.equals("ssh-rsa")){
byte[] tmp;
byte[] ee;
byte[] n;
type=RSA;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
ee=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
n=tmp;
// SignatureRSA sig=new SignatureRSA();
// sig.init();
SignatureRSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.rsa"));
sig=(SignatureRSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(ee, n);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_rsa_verify: signature "+result);
}
}
else if(alg.equals("ssh-dss")){
byte[] q=null;
byte[] tmp;
byte[] p;
byte[] g;
type=DSS;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
p=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
q=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
g=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
f=tmp;
// SignatureDSA sig=new SignatureDSA();
// sig.init();
SignatureDSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.dss"));
sig=(SignatureDSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(f, p, q, g);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_dss_verify: signature "+result);
}
}
else{
System.err.println("unknown alg");
}
state=STATE_END;
return result;
}
return false;
}
public String getKeyType(){
if(type==DSS) return "DSA";
return "RSA";
}
public int getState(){return state; }
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -71,10 +71,6 @@ public class DHG14 extends KeyExchange{
private static final int SSH_MSG_KEXDH_INIT= 30;
private static final int SSH_MSG_KEXDH_REPLY= 31;
static final int RSA=0;
static final int DSS=1;
private int type=0;
private int state;
DH dh;
@@ -166,17 +162,14 @@ public class DHG14 extends KeyExchange{
}
K_S=_buf.getString();
// K_S is server_key_blob, which includes ....
// string ssh-dss
// impint p of dsa
// impint q of dsa
// impint g of dsa
// impint pub_key of dsa
//System.err.print("K_S: "); //dump(K_S, 0, K_S.length);
byte[] f=_buf.getMPInt();
byte[] sig_of_H=_buf.getString();
dh.setF(f);
dh.checkRange();
K=normalize(dh.getK());
//The hash H is computed as the HASH hash of the concatenation of the
@@ -210,101 +203,13 @@ public class DHG14 extends KeyExchange{
String alg=Util.byte2str(K_S, i, j);
i+=j;
boolean result=false;
boolean result = verify(alg, K_S, i, sig_of_H);
if(alg.equals("ssh-rsa")){
byte[] tmp;
byte[] ee;
byte[] n;
type=RSA;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
ee=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
n=tmp;
SignatureRSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.rsa"));
sig=(SignatureRSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(ee, n);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_rsa_verify: signature "+result);
}
}
else if(alg.equals("ssh-dss")){
byte[] q=null;
byte[] tmp;
byte[] p;
byte[] g;
type=DSS;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
p=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
q=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
g=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
f=tmp;
SignatureDSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.dss"));
sig=(SignatureDSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(f, p, q, g);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_dss_verify: signature "+result);
}
}
else{
System.err.println("unknown alg");
}
state=STATE_END;
return result;
}
return false;
}
public String getKeyType(){
if(type==DSS) return "DSA";
return "RSA";
}
public int getState(){return state; }
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -37,21 +37,11 @@ public class DHGEX extends KeyExchange{
private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
static int min=1024;
// static int min=512;
static int preferred=1024;
static int max=1024;
// static int preferred=1024;
// static int max=2000;
static final int RSA=0;
static final int DSS=1;
private int type=0;
int max=1024;
private int state;
// com.jcraft.jsch.DH dh;
DH dh;
byte[] V_S;
@@ -65,7 +55,8 @@ public class DHGEX extends KeyExchange{
private byte[] p;
private byte[] g;
private byte[] e;
//private byte[] f;
protected String hash="sha-1";
public void init(Session session,
byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
@@ -76,7 +67,7 @@ public class DHGEX extends KeyExchange{
this.I_C=I_C;
try{
Class c=Class.forName(session.getConfig("sha-1"));
Class c=Class.forName(session.getConfig(hash));
sha=(HASH)(c.newInstance());
sha.init();
}
@@ -89,11 +80,13 @@ public class DHGEX extends KeyExchange{
try{
Class c=Class.forName(session.getConfig("dh"));
// Since JDK8, SunJCE has lifted the keysize restrictions
// from 1024 to 2048 for DH.
preferred = max = check2048(c, max);
dh=(com.jcraft.jsch.DH)(c.newInstance());
dh.init();
}
catch(Exception e){
// System.err.println(e);
throw e;
}
@@ -131,18 +124,9 @@ public class DHGEX extends KeyExchange{
p=_buf.getMPInt();
g=_buf.getMPInt();
/*
for(int iii=0; iii<p.length; iii++){
System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
}
System.err.println("");
for(int iii=0; iii<g.length; iii++){
System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
}
*/
dh.setP(p);
dh.setG(g);
// The client responds with:
// byte SSH_MSG_KEX_DH_GEX_INIT(32)
// mpint e <- g^x mod p
@@ -181,18 +165,14 @@ System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
}
K_S=_buf.getString();
// K_S is server_key_blob, which includes ....
// string ssh-dss
// impint p of dsa
// impint q of dsa
// impint g of dsa
// impint pub_key of dsa
//System.err.print("K_S: "); dump(K_S, 0, K_S.length);
byte[] f=_buf.getMPInt();
byte[] sig_of_H=_buf.getString();
dh.setF(f);
dh.checkRange();
K=normalize(dh.getK());
//The hash H is computed as the HASH hash of the concatenation of the
@@ -236,105 +216,30 @@ System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
String alg=Util.byte2str(K_S, i, j);
i+=j;
boolean result=false;
if(alg.equals("ssh-rsa")){
byte[] tmp;
byte[] ee;
byte[] n;
type=RSA;
boolean result = verify(alg, K_S, i, sig_of_H);
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
ee=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
n=tmp;
// SignatureRSA sig=new SignatureRSA();
// sig.init();
SignatureRSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.rsa"));
sig=(SignatureRSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(ee, n);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_rsa_verify: signature "+result);
}
}
else if(alg.equals("ssh-dss")){
byte[] q=null;
byte[] tmp;
type=DSS;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
p=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
q=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
g=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
f=tmp;
// SignatureDSA sig=new SignatureDSA();
// sig.init();
SignatureDSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.dss"));
sig=(SignatureDSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(f, p, q, g);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_dss_verify: signature "+result);
}
}
else{
System.err.println("unknown alg");
}
state=STATE_END;
return result;
}
return false;
}
public String getKeyType(){
if(type==DSS) return "DSA";
return "RSA";
}
public int getState(){return state; }
protected int check2048(Class c, int _max) throws Exception {
DH dh=(com.jcraft.jsch.DH)(c.newInstance());
dh.init();
byte[] foo = new byte[257];
foo[1]=(byte)0xdd;
foo[256]=0x73;
dh.setP(foo);
byte[] bar = {(byte)0x02};
dh.setG(bar);
try {
dh.getE();
_max=2048;
}
catch(Exception e){ }
return _max;
}
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -29,312 +29,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.jcraft.jsch;
public class DHGEX256 extends KeyExchange{
private static final int SSH_MSG_KEX_DH_GEX_GROUP= 31;
private static final int SSH_MSG_KEX_DH_GEX_INIT= 32;
private static final int SSH_MSG_KEX_DH_GEX_REPLY= 33;
private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34;
static int min=1024;
// static int min=512;
static int preferred=1024;
static int max=1024;
// static int preferred=1024;
// static int max=2000;
static final int RSA=0;
static final int DSS=1;
private int type=0;
private int state;
// com.jcraft.jsch.DH dh;
DH dh;
byte[] V_S;
byte[] V_C;
byte[] I_S;
byte[] I_C;
private Buffer buf;
private Packet packet;
private byte[] p;
private byte[] g;
private byte[] e;
//private byte[] f;
public void init(Session session,
byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{
this.session=session;
this.V_S=V_S;
this.V_C=V_C;
this.I_S=I_S;
this.I_C=I_C;
try{
Class c=Class.forName(session.getConfig("sha-256"));
sha=(HASH)(c.newInstance());
sha.init();
}
catch(Exception e){
System.err.println(e);
}
buf=new Buffer();
packet=new Packet(buf);
try{
Class c=Class.forName(session.getConfig("dh"));
dh=(com.jcraft.jsch.DH)(c.newInstance());
dh.init();
}
catch(Exception e){
// System.err.println(e);
throw e;
}
packet.reset();
buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST);
buf.putInt(min);
buf.putInt(preferred);
buf.putInt(max);
session.write(packet);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent");
JSch.getLogger().log(Logger.INFO,
"expecting SSH_MSG_KEX_DH_GEX_GROUP");
}
state=SSH_MSG_KEX_DH_GEX_GROUP;
public class DHGEX256 extends DHGEX {
DHGEX256(){
hash="sha-256";
}
public boolean next(Buffer _buf) throws Exception{
int i,j;
switch(state){
case SSH_MSG_KEX_DH_GEX_GROUP:
// byte SSH_MSG_KEX_DH_GEX_GROUP(31)
// mpint p, safe prime
// mpint g, generator for subgroup in GF (p)
_buf.getInt();
_buf.getByte();
j=_buf.getByte();
if(j!=SSH_MSG_KEX_DH_GEX_GROUP){
System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j);
return false;
}
p=_buf.getMPInt();
g=_buf.getMPInt();
/*
for(int iii=0; iii<p.length; iii++){
System.err.println("0x"+Integer.toHexString(p[iii]&0xff)+",");
}
System.err.println("");
for(int iii=0; iii<g.length; iii++){
System.err.println("0x"+Integer.toHexString(g[iii]&0xff)+",");
}
*/
dh.setP(p);
dh.setG(g);
// The client responds with:
// byte SSH_MSG_KEX_DH_GEX_INIT(32)
// mpint e <- g^x mod p
// x is a random number (1 < x < (p-1)/2)
e=dh.getE();
packet.reset();
buf.putByte((byte)SSH_MSG_KEX_DH_GEX_INIT);
buf.putMPInt(e);
session.write(packet);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"SSH_MSG_KEX_DH_GEX_INIT sent");
JSch.getLogger().log(Logger.INFO,
"expecting SSH_MSG_KEX_DH_GEX_REPLY");
}
state=SSH_MSG_KEX_DH_GEX_REPLY;
return true;
//break;
case SSH_MSG_KEX_DH_GEX_REPLY:
// The server responds with:
// byte SSH_MSG_KEX_DH_GEX_REPLY(33)
// string server public host key and certificates (K_S)
// mpint f
// string signature of H
j=_buf.getInt();
j=_buf.getByte();
j=_buf.getByte();
if(j!=SSH_MSG_KEX_DH_GEX_REPLY){
System.err.println("type: must be SSH_MSG_KEX_DH_GEX_REPLY "+j);
return false;
}
K_S=_buf.getString();
// K_S is server_key_blob, which includes ....
// string ssh-dss
// impint p of dsa
// impint q of dsa
// impint g of dsa
// impint pub_key of dsa
//System.err.print("K_S: "); dump(K_S, 0, K_S.length);
byte[] f=_buf.getMPInt();
byte[] sig_of_H=_buf.getString();
dh.setF(f);
K=normalize(dh.getK());
//The hash H is computed as the HASH hash of the concatenation of the
//following:
// string V_C, the client's version string (CR and NL excluded)
// string V_S, the server's version string (CR and NL excluded)
// string I_C, the payload of the client's SSH_MSG_KEXINIT
// string I_S, the payload of the server's SSH_MSG_KEXINIT
// string K_S, the host key
// uint32 min, minimal size in bits of an acceptable group
// uint32 n, preferred size in bits of the group the server should send
// uint32 max, maximal size in bits of an acceptable group
// mpint p, safe prime
// mpint g, generator for subgroup
// mpint e, exchange value sent by the client
// mpint f, exchange value sent by the server
// mpint K, the shared secret
// This value is called the exchange hash, and it is used to authenti-
// cate the key exchange.
buf.reset();
buf.putString(V_C); buf.putString(V_S);
buf.putString(I_C); buf.putString(I_S);
buf.putString(K_S);
buf.putInt(min); buf.putInt(preferred); buf.putInt(max);
buf.putMPInt(p); buf.putMPInt(g); buf.putMPInt(e); buf.putMPInt(f);
buf.putMPInt(K);
byte[] foo=new byte[buf.getLength()];
buf.getByte(foo);
sha.update(foo, 0, foo.length);
H=sha.digest();
// System.err.print("H -> "); dump(H, 0, H.length);
i=0;
j=0;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
String alg=Util.byte2str(K_S, i, j);
i+=j;
boolean result=false;
if(alg.equals("ssh-rsa")){
byte[] tmp;
byte[] ee;
byte[] n;
type=RSA;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
ee=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
n=tmp;
// SignatureRSA sig=new SignatureRSA();
// sig.init();
SignatureRSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.rsa"));
sig=(SignatureRSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(ee, n);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_rsa_verify: signature "+result);
}
}
else if(alg.equals("ssh-dss")){
byte[] q=null;
byte[] tmp;
type=DSS;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
p=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
q=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
g=tmp;
j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)|
((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff);
tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j;
f=tmp;
// SignatureDSA sig=new SignatureDSA();
// sig.init();
SignatureDSA sig=null;
try{
Class c=Class.forName(session.getConfig("signature.dss"));
sig=(SignatureDSA)(c.newInstance());
sig.init();
}
catch(Exception e){
System.err.println(e);
}
sig.setPubKey(f, p, q, g);
sig.update(H);
result=sig.verify(sig_of_H);
if(JSch.getLogger().isEnabled(Logger.INFO)){
JSch.getLogger().log(Logger.INFO,
"ssh_dss_verify: signature "+result);
}
}
else{
System.err.println("unknown alg");
}
state=STATE_END;
return result;
}
return false;
}
public String getKeyType(){
if(type==DSS) return "DSA";
return "RSA";
}
public int getState(){return state; }
}

View File

@@ -0,0 +1,37 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2015-2016 ymnk, JCraft,Inc. 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.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE 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.
*/
package com.jcraft.jsch;
public interface ECDH {
void init(int size) throws Exception;
byte[] getSecret(byte[] r, byte[] s) throws Exception;
byte[] getQ() throws Exception;
boolean validate(byte[] r, byte[] s) throws Exception;
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2004-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2004-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -30,13 +30,22 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.jcraft.jsch;
public class HostKey{
private static final byte[] sshdss=Util.str2byte("ssh-dss");
private static final byte[] sshrsa=Util.str2byte("ssh-rsa");
private static final byte[][] names = {
Util.str2byte("ssh-dss"),
Util.str2byte("ssh-rsa"),
Util.str2byte("ecdsa-sha2-nistp256"),
Util.str2byte("ecdsa-sha2-nistp384"),
Util.str2byte("ecdsa-sha2-nistp521")
};
protected static final int GUESS=0;
public static final int SSHDSS=1;
public static final int SSHRSA=2;
static final int UNKNOWN=3;
public static final int ECDSA256=3;
public static final int ECDSA384=4;
public static final int ECDSA521=5;
static final int UNKNOWN=6;
protected String marker;
protected String host;
@@ -60,6 +69,9 @@ public class HostKey{
if(type==GUESS){
if(key[8]=='d'){ this.type=SSHDSS; }
else if(key[8]=='r'){ this.type=SSHRSA; }
else if(key[8]=='a' && key[20]=='2'){ this.type=ECDSA256; }
else if(key[8]=='a' && key[20]=='3'){ this.type=ECDSA384; }
else if(key[8]=='a' && key[20]=='5'){ this.type=ECDSA521; }
else { throw new JSchException("invalid key type");}
}
else{
@@ -71,10 +83,23 @@ public class HostKey{
public String getHost(){ return host; }
public String getType(){
if(type==SSHDSS){ return Util.byte2str(sshdss); }
if(type==SSHRSA){ return Util.byte2str(sshrsa);}
if(type==SSHDSS ||
type==SSHRSA ||
type==ECDSA256 ||
type==ECDSA384 ||
type==ECDSA521){
return Util.byte2str(names[type-1]);
}
return "UNKNOWN";
}
protected static int name2type(String name){
for(int i = 0; i < names.length; i++){
if(Util.byte2str(names[i]).equals(name)){
return i + 1;
}
}
return UNKNOWN;
}
public String getKey(){
return Util.byte2str(Util.toBase64(key, 0, key.length));
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2004-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2004-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -34,11 +34,61 @@ public interface HostKeyRepository{
final int NOT_INCLUDED=1;
final int CHANGED=2;
/**
* Checks if <code>host</code> is included with the <code>key</code>.
*
* @return #NOT_INCLUDED, #OK or #CHANGED
* @see #NOT_INCLUDED
* @see #OK
* @see #CHANGED
*/
int check(String host, byte[] key);
/**
* Adds a host key <code>hostkey</code>
*
* @param hostkey a host key to be added
* @param ui a user interface for showing messages or promping inputs.
* @see UserInfo
*/
void add(HostKey hostkey, UserInfo ui);
/**
* Removes a host key if there exists mached key with
* <code>host</code>, <code>type</code>.
*
* @see #remove(String host, String type, byte[] key)
*/
void remove(String host, String type);
/**
* Removes a host key if there exists a matched key with
* <code>host</code>, <code>type</code> and <code>key</code>.
*/
void remove(String host, String type, byte[] key);
/**
* Returns id of this repository.
*
* @return identity in String
*/
String getKnownHostsRepositoryID();
/**
* Retuns a list for host keys managed in this repository.
*
* @see #getHostKey(String host, String type)
*/
HostKey[] getHostKey();
/**
* Retuns a list for host keys managed in this repository.
*
* @param host a hostname used in searching host keys.
* If <code>null</code> is given, every host key will be listed.
* @param type a key type used in searching host keys,
* and it should be "ssh-dss" or "ssh-rsa".
* If <code>null</code> is given, a key type type will not be ignored.
*/
HostKey[] getHostKey(String host, String type);
}

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

View File

@@ -1,6 +1,6 @@
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/*
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

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