Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.
/jdk17Public archive

8268775: Password is being converted to String in AccessibleJPasswordField#127

Closed
wants to merge 2 commits into from
Closed

Conversation

azuev-java
Copy link
Member

@azuev-javaazuev-java commented Jun 23, 2021


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8268775: Password is being converted to String in AccessibleJPasswordField

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk17 pull/127/head:pull/127
$ git checkout pull/127

Update a local copy of the PR:
$ git checkout pull/127
$ git pull https://git.openjdk.java.net/jdk17 pull/127/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 127

View PR using the GUI difftool:
$ git pr show -t 127

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk17/pull/127.diff

…Field Removed unneeded String internal variables in a number of methods.
@bridgekeeper
Copy link

👋 Welcome back kizune! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdkbot commented Jun 23, 2021

@azuev-java The following label will be automatically applied to this pull request:

  • swing

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdkopenjdkbot added swing client-libs-dev@openjdk.java.net rfr Pull request is ready for review labels Jun 23, 2021
@mlbridge
Copy link

mlbridgebot commented Jun 23, 2021

Webrevs

@victordyakov
Copy link
Contributor

@prrace
Copy link
Contributor

There's code but not a single word of description of the fix.
What is the problem, what are the changes here, why do they fix it, and what are the risks / consequences and why is there no test ?
It is not very kind to reviewers to offer no explanation.

if (part == AccessibleText.CHARACTER) {
str = super.getAtIndex(part, index);
return getEchoString(super.getAtIndex(part, index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how removing the local variable changes anything. Explanation ??

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it is just a slight code cleanup. We do not need additional variable for passing value from one method to another. It serves no other purpose at all. It was used before on the second leg of the if but the usage was removed so it became useless.

Copy link

@VestVestJun 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is about security, I don’t see how it might help. There is a chance that the heap dump might capture the content of the local variable. If you submit your heap dump to someone, whom you do not trust, I have bad news for you.

The probability of the heap dump to capture a local variable is more than zero. True, but less than probable.

I don’t know if calling same methods in a single line makes this control more secure (if we take the situation that the heap dump pauses an execution of the thread exactly at our „moment of time“). I am not a member of the project JDK, but I doubt that this PR solves something.

To me, an additional local variable adds better supportability (debugging) to this code. Otherwise everything should be put into a single fat method.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t know if calling same methods in a single line makes this control more secure

As i said above this exact change is not about making code more secure - it is just to eliminate additional variable that has no purpose after the second half of the method is changed. I would say that it would add to the supportability if we do anything with this information - but we don't.

@@ -544,8 +543,7 @@ public String getAtIndex(int part, int index) {
*/
public String getAfterIndex(int part, int index) {
if (part == AccessibleText.CHARACTER) {
String str = super.getAfterIndex(part, index);
return getEchoString(str);
return getEchoString(super.getAfterIndex(part, index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how removing the local variable changes anything. Explanation ??

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it is just a slight code cleanup. We do not need additional variable for passing value from one method to another. It serves no other purpose at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me ask it this way.
Does super.getAfterIndex(part, index) return a String with any of the password in clear text ?
It seems to me like it might.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For CHARACTER it will return String with a single character in the corresponding position. There is a possibility that someone will iterate the entirety of the password text and get all the characters in the password as a separate strings but digging it from the memory dump is much more difficult than the singular string with the whole password.
For anything but character we do not use this method - we get password as an array of characters and - after the fix - immediately overriding them with the same number of echo characters.

@azuev-java
Copy link
MemberAuthor

The problem here is that if someone uses the accessibility methods on JPasswordField it will lead to unencrypted password being stored in the local String variable and that in turn can lead to it being recorded in, say, crash tump file where it can be found amongst the string literals. This is highly improbable scenario but it can be done so we better to not do it. And there are only two places where it happens - because in other methods we only serving the AccessibleText.CHARACTER retrieval which means that we are getting one password character at a time in a separate String variable which is Ok. These two places are at methods getAtIndex and getTextSequenceAt where we requesting something other than AccessibleText.CHARACTER. There we were converting password from the array of chars to the String only to pass this string to the method that generates string of echo characters of the same length. Instead i am doing conversion myself filling in the returned array with echo characters and returning constructed string. The rest of the changes is just a slight code cleanup - getting rid of the local variable that is used only to store some value before passing it to another method.

String text = new String(password);
return new AccessibleTextSequence(0, password.length - 1,
getEchoString(text));
return new AccessibleTextSequence(0, password.length - 1, text);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the accessible text is just the right number of "echo" chars.
And you are still calling getPassword() just so you can find out the length.
Then it is over-written. There's a really tiny window after getPassword() and before Arrays.fill() when the clear password is still there.
The number of "char"s isn't the same as the number of "characters" if there's a non-BMP code point in there .. perhaps these are not allowed by this class .. but it makes me wonder how much if having the exact number of echo chars as the actual password is important. I wonder how many text-to-speech readers can say "bullet" for a unicode bullet character ?

If it weren't for all of this (the class and the getPassword() method being non-final I'd suggest you look into a way to pull just the length rather than the actual chars.

Copy link
MemberAuthor

@azuev-javaazuev-javaJun 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the accessible text is just the right number of "echo" chars.
Yes.
And you are still calling getPassword() just so you can find out the length.
Then it is over-written. There's a really tiny window after getPassword() and before Arrays.fill() when the clear password is still there.

Yes. But not as a string - and the window of opportunity to get the characters before they are overwritten by the echo characters is minimal.

The number of "char"s isn't the same as the number of "characters" if there's a non-BMP code point in there ..

Since in order to enter non-BPM characters you have to have an input methods helper which should be disabled on password fields for obvious reason - it would pretty much disclose the typed password in the IM helper window - the only way to enter such symbols would b copy/paste and in this case i do not expect it to be edited within password field.

perhaps these are not allowed by this class .. but it makes me wonder how much if having the exact number of echo chars as the actual password is important. I wonder how many text-to-speech readers can say "bullet" for a unicode bullet character ?

Well, accessibility is not only about text to speech - it is also about easier navigation so having exact number of the bullets is preferable. There are limitations - like some non-BPM text can be pasted into the password field and then navigating within it might be broken but since there will be no IM engaged fixing it would be equally problematic.

If it weren't for all of this (the class and the getPassword() method being non-final I'd suggest you look into a way to pull just the length rather than the actual chars.

That would be preferable but under the current circumstances i would say that my fix makes things better without adding incompatible changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the "getDocument().getLength()"?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the "getDocument().getLength()"?

We can surely do that. Fixed.

@@ -544,8 +543,7 @@ public String getAtIndex(int part, int index) {
*/
public String getAfterIndex(int part, int index) {
if (part == AccessibleText.CHARACTER) {
String str = super.getAfterIndex(part, index);
return getEchoString(str);
return getEchoString(super.getAfterIndex(part, index));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me ask it this way.
Does super.getAfterIndex(part, index) return a String with any of the password in clear text ?
It seems to me like it might.

@victordyakov
Copy link
Contributor

@mrserb please review

@openjdk
Copy link

openjdkbot commented Jul 2, 2021

@azuev-java This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8268775: Password is being converted to String in AccessibleJPasswordField Reviewed-by: prr 

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 73 new commits pushed to the master branch:

  • 1c18f91: 8269768: JFR Terminology Refresh
  • 6f0e8e7: 8269775: compiler/codegen/ClearArrayTest.java failed with "assert(false) failed: bad AD file"
  • c4ea13e: 8269543: The warning for System::setSecurityManager should only appear once for each caller
  • 2db9005: 8262017: C2: assert(n != __null) failed: Bad immediate dominator info.
  • 7bc96db: 8269771: assert(tmp == _callprojs.fallthrough_catchproj) failed: allocation control projection
  • 5644c4f: 8265132: C2 compilation fails with assert "missing precedence edge"
  • a4d2a9a: 8269745: [JVMCI] restore original qualified exports to Graal
  • e377397: 8268566: java/foreign/TestResourceScope.java timed out
  • 6c76e77: 8260684: vmTestbase/gc/gctests/PhantomReference/phantom002/TestDescription.java timed out
  • 4bbf11d: 8269580: assert(is_valid()) failed: invalid register (-1)
  • ... and 63 more: https://git.openjdk.java.net/jdk17/compare/1323be54d26833d261ef5b53ae0ee9b58a96aabb...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdkopenjdkbot added the ready Pull request is ready to be integrated label Jul 2, 2021
@azuev-java
Copy link
MemberAuthor

/integrate

@openjdk
Copy link

openjdkbot commented Jul 2, 2021

Going to push as commit 97e0e9e.
Since your change was applied there have been 73 commits pushed to the master branch:

  • 1c18f91: 8269768: JFR Terminology Refresh
  • 6f0e8e7: 8269775: compiler/codegen/ClearArrayTest.java failed with "assert(false) failed: bad AD file"
  • c4ea13e: 8269543: The warning for System::setSecurityManager should only appear once for each caller
  • 2db9005: 8262017: C2: assert(n != __null) failed: Bad immediate dominator info.
  • 7bc96db: 8269771: assert(tmp == _callprojs.fallthrough_catchproj) failed: allocation control projection
  • 5644c4f: 8265132: C2 compilation fails with assert "missing precedence edge"
  • a4d2a9a: 8269745: [JVMCI] restore original qualified exports to Graal
  • e377397: 8268566: java/foreign/TestResourceScope.java timed out
  • 6c76e77: 8260684: vmTestbase/gc/gctests/PhantomReference/phantom002/TestDescription.java timed out
  • 4bbf11d: 8269580: assert(is_valid()) failed: invalid register (-1)
  • ... and 63 more: https://git.openjdk.java.net/jdk17/compare/1323be54d26833d261ef5b53ae0ee9b58a96aabb...master

Your commit was automatically rebased without conflicts.

@openjdkopenjdkbot closed this Jul 2, 2021
@openjdkopenjdkbot added integrated Pull request has been integrated and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Jul 2, 2021
@openjdk
Copy link

openjdkbot commented Jul 2, 2021

@azuev-java Pushed as commit 97e0e9e.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
integratedPull request has been integratedswingclient-libs-dev@openjdk.java.net
5 participants
@azuev-java@victordyakov@prrace@Vest@mrserb
close