mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-5362 Correct password entry bug and refactor PasswordDialog/ClientAuthenticator
This commit is contained in:
parent
99ed1003b5
commit
d0badde92b
12 changed files with 194 additions and 116 deletions
|
@ -418,10 +418,6 @@ public class CreateBsimServerInfoDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
String user = userField.getText().trim();
|
String user = userField.getText().trim();
|
||||||
if (ClientUtil.getUserName().equals(user)) {
|
|
||||||
user = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = nameField.getText().trim();
|
String name = nameField.getText().trim();
|
||||||
String host = hostField.getText().trim();
|
String host = hostField.getText().trim();
|
||||||
|
|
||||||
|
|
|
@ -334,14 +334,16 @@ public class BSimPostgresDBConnectionManager {
|
||||||
throw new SQLException("No registered authenticator");
|
throw new SQLException("No registered authenticator");
|
||||||
}
|
}
|
||||||
NameCallback nameCb = new NameCallback("User ID:", bds.getUsername());
|
NameCallback nameCb = new NameCallback("User ID:", bds.getUsername());
|
||||||
|
boolean allowUserIDEntry = true;
|
||||||
if (!serverInfo.hasDefaultLogin()) {
|
if (!serverInfo.hasDefaultLogin()) {
|
||||||
nameCb.setName(bds.getUsername());
|
nameCb.setName(bds.getUsername());
|
||||||
|
allowUserIDEntry = false;
|
||||||
}
|
}
|
||||||
PasswordCallback passCb = new PasswordCallback(" ", false); // force use of default prompting
|
PasswordCallback passCb = new PasswordCallback(" ", false); // force use of default prompting
|
||||||
try {
|
try {
|
||||||
if (!clientAuthenticator.processPasswordCallbacks(
|
if (!clientAuthenticator.processPasswordCallbacks(
|
||||||
"BSim Database Authentication", "BSim Database Server",
|
"BSim Database Authentication", "BSim DB Server", serverInfo.toString(),
|
||||||
serverInfo.toString(), nameCb, passCb, null, null, loginError)) {
|
allowUserIDEntry, nameCb, passCb, null, null, loginError)) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
bds.setPassword(new String(passCb.getPassword()));
|
bds.setPassword(new String(passCb.getPassword()));
|
||||||
|
|
|
@ -376,7 +376,7 @@ public class BSimServerInfo implements Comparable<BSimServerInfo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine of user info was stipulated during construction
|
* Determine if user info was stipulated during construction
|
||||||
* @return true if user info was stipulated during construction
|
* @return true if user info was stipulated during construction
|
||||||
*/
|
*/
|
||||||
public boolean hasDefaultLogin() {
|
public boolean hasDefaultLogin() {
|
||||||
|
|
|
@ -590,8 +590,8 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||||
if (isRunningHeadless()) {
|
if (isRunningHeadless()) {
|
||||||
// only change client authenticator in headless mode
|
// only change client authenticator in headless mode
|
||||||
try {
|
try {
|
||||||
HeadlessClientAuthenticator.installHeadlessClientAuthenticator(
|
HeadlessClientAuthenticator
|
||||||
ClientUtil.getUserName(), null, false);
|
.installHeadlessClientAuthenticator(ClientUtil.getUserName(), null, false);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException("Unexpected Exception", e);
|
throw new RuntimeException("Unexpected Exception", e);
|
||||||
|
@ -2629,8 +2629,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||||
|
|
||||||
Address choice = doAsk(Integer.class, title, message, existingValue, lastValue -> {
|
Address choice = doAsk(Integer.class, title, message, existingValue, lastValue -> {
|
||||||
|
|
||||||
AskAddrDialog dialog =
|
AskAddrDialog dialog = new AskAddrDialog(title, message, currentProgram, lastValue);
|
||||||
new AskAddrDialog(title, message, currentProgram, lastValue);
|
|
||||||
if (dialog.isCanceled()) {
|
if (dialog.isCanceled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
@ -3158,7 +3157,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||||
throw new ImproperUseException(
|
throw new ImproperUseException(
|
||||||
"The askPassword() method can only be used when running headed Ghidra.");
|
"The askPassword() method can only be used when running headed Ghidra.");
|
||||||
}
|
}
|
||||||
PasswordDialog dialog = new PasswordDialog(title, null, null, prompt, null, null);
|
PasswordDialog dialog = new PasswordDialog(title, null, null, prompt);
|
||||||
try {
|
try {
|
||||||
state.getTool().showDialog(dialog);
|
state.getTool().showDialog(dialog);
|
||||||
if (!dialog.okWasPressed()) {
|
if (!dialog.okWasPressed()) {
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.awt.event.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
import docking.DialogComponentProvider;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
import docking.widgets.combobox.GComboBox;
|
import docking.widgets.combobox.GComboBox;
|
||||||
|
@ -39,26 +41,34 @@ public class PasswordDialog extends DialogComponentProvider {
|
||||||
private JComboBox<String> choiceCB;
|
private JComboBox<String> choiceCB;
|
||||||
private JCheckBox anonymousAccess;
|
private JCheckBox anonymousAccess;
|
||||||
private boolean okPressed = false;
|
private boolean okPressed = false;
|
||||||
private String defaultUserID;
|
private String defaultUserId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new PasswordDialog.
|
* Construct a new PasswordDialog which may include user ID specification/prompt, if either
|
||||||
|
* {@code allowUserIdEntry} is true or a non-null {@code defaultUserId} has been specified, and
|
||||||
|
* other optional elements. The dialog includes a message text area which supports the use
|
||||||
|
* of {@link #setErrorText(String)}.
|
||||||
|
*
|
||||||
* @param title title of the dialog
|
* @param title title of the dialog
|
||||||
* @param serverType 'Server' or 'Key-store' designation
|
* @param serverType 'Server' or 'Key-store' designation
|
||||||
* @param serverName name of server or keystore pathname
|
* @param serverName name of server or keystore pathname
|
||||||
* @param passPrompt password prompt to show in the dialog; may be null, in which case
|
* @param passPrompt password prompt to show in the dialog; may be null/empty, in which case
|
||||||
* "Password:" is displayed next to the password field
|
* "Password:" is displayed next to the password field
|
||||||
* @param userIdPrompt User ID / Name prompt to show in the dialog, if null a name will not be prompted for.
|
* @param allowUserIdEntry if true user ID entry will be supported
|
||||||
* @param defaultUserID default name when prompting for a name
|
* @param userIdPrompt User ID / Name prompt to show in the dialog, if null "User ID:" is prompt
|
||||||
|
* if either {@code allowUserIdEntry} is true or a non-null {@code defaultUserId} has been specified.
|
||||||
|
* @param defaultUserId default name when prompting for a name
|
||||||
* @param choicePrompt namePrompt name prompt to show in the dialog, if null a name will not be prompted for.
|
* @param choicePrompt namePrompt name prompt to show in the dialog, if null a name will not be prompted for.
|
||||||
* @param choices array of choices to present if choicePrompt is not null
|
* @param choices array of choices to present if choicePrompt is not null
|
||||||
* @param defaultChoice default choice index
|
* @param defaultChoice default choice index
|
||||||
* @param includeAnonymousOption true signals to add a checkbox to request anonymous login
|
* @param includeAnonymousOption true signals to add a checkbox to request anonymous login
|
||||||
*/
|
*/
|
||||||
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
||||||
String userIdPrompt, String defaultUserID, String choicePrompt, String[] choices,
|
boolean allowUserIdEntry, String userIdPrompt, String defaultUserId,
|
||||||
int defaultChoice, boolean includeAnonymousOption) {
|
String choicePrompt, String[] choices, int defaultChoice,
|
||||||
this(title, serverType, serverName, passPrompt, userIdPrompt, defaultUserID);
|
boolean includeAnonymousOption) {
|
||||||
|
this(title, serverType, serverName, passPrompt, allowUserIdEntry, userIdPrompt,
|
||||||
|
defaultUserId, true);
|
||||||
if (choicePrompt != null) {
|
if (choicePrompt != null) {
|
||||||
workPanel.add(new GLabel(choicePrompt));
|
workPanel.add(new GLabel(choicePrompt));
|
||||||
choiceCB = new GComboBox<>(choices);
|
choiceCB = new GComboBox<>(choices);
|
||||||
|
@ -89,43 +99,70 @@ public class PasswordDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new PasswordDialog.
|
* Construct a new PasswordDialog which only prompts for a password for a specified server
|
||||||
|
* type and name. The dialog will not include a User ID display, although server fields
|
||||||
|
* may be used for a similar display purpose. The dialog includes a message text area
|
||||||
|
* which supports the use of {@link #setErrorText(String)}.
|
||||||
|
*
|
||||||
* @param title title of the dialog
|
* @param title title of the dialog
|
||||||
* @param serverType 'Server' or 'Key-store' designation
|
* @param serverType 'Server' or 'Key-store' designation
|
||||||
* @param serverName name of server or keystore pathname
|
* @param serverName name of server or keystore pathname
|
||||||
* @param passPrompt password prompt to show in the dialog; may be null, in which case
|
* @param passPrompt password prompt to show in the dialog; may be null, in which case
|
||||||
* "Password:" is displayed next to the password field
|
* "Password:" is prompt.
|
||||||
* @param userIdPrompt User ID / Name prompt to show in the dialog, if null a name will not be prompted for.
|
|
||||||
* @param defaultUserID default name when prompting for a name
|
|
||||||
*/
|
*/
|
||||||
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
public PasswordDialog(String title, String serverType, String serverName, String passPrompt) {
|
||||||
String userIdPrompt, String defaultUserID) {
|
this(title, serverType, serverName, passPrompt, true);
|
||||||
this(title, serverType, serverName, passPrompt, userIdPrompt, defaultUserID, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new PasswordDialog.
|
* Construct a new PasswordDialog which only prompts for a password for a specified server
|
||||||
|
* type and name. The dialog will not include a User ID display, although server fields
|
||||||
|
* may be used for a similar display purpose. The dialog optionally includes a message
|
||||||
|
* text area which supports the use of {@link #setErrorText(String)}.
|
||||||
|
*
|
||||||
* @param title title of the dialog
|
* @param title title of the dialog
|
||||||
* @param serverType 'Server' or 'Key-store' designation
|
* @param serverType 'Server' or 'Key-store' designation
|
||||||
* @param serverName name of server or keystore pathname
|
* @param serverName name of server or keystore pathname
|
||||||
* @param passPrompt password prompt to show in the dialog; may be null, in which case
|
* @param passPrompt password prompt to show in the dialog; may be null, in which case
|
||||||
* "Password:" is displayed next to the password field
|
* "Password:" is displayed next to the password field
|
||||||
* @param userIdPrompt User ID / Name prompt to show in the dialog, if null a name will not be prompted for.
|
* @param hasMessages true if a message text area should be included allowing for use of
|
||||||
* @param defaultUserID default name when prompting for a name
|
* {@link #setErrorText(String)}
|
||||||
* @param hasMessages true if the client will set messages on this dialog. If true, the
|
|
||||||
* dialog's minimum size will be increased
|
|
||||||
*/
|
*/
|
||||||
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
||||||
String userIdPrompt, String defaultUserID, boolean hasMessages) {
|
boolean hasMessages) {
|
||||||
|
this(title, serverType, serverName, passPrompt, false, null, null, hasMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new PasswordDialog which may include user ID specification/prompt if either
|
||||||
|
* {@code allowUserIdEntry} is true or a non-null {@code defaultUserId} has been specified.
|
||||||
|
* The dialog optionally includes a message text area area which supports the use of
|
||||||
|
* {@link #setErrorText(String)}.
|
||||||
|
*
|
||||||
|
* @param title title of the dialog
|
||||||
|
* @param serverType 'Server' or 'Key-store' designation
|
||||||
|
* @param serverName name of server or keystore pathname
|
||||||
|
* @param passPrompt password prompt to show in the dialog; may be null/empty, in which case
|
||||||
|
* "Password:" is displayed next to the password field
|
||||||
|
* @param allowUserIdEntry if true user ID entry will be supported
|
||||||
|
* @param userIdPrompt User ID / Name prompt to show in the dialog, if null "User ID:" is prompt
|
||||||
|
* if either {@code allowUserIdEntry} is true or a non-null {@code defaultUserId} has been specified.
|
||||||
|
* @param defaultUserId default name when prompting for a name
|
||||||
|
* @param hasMessages true if a message text area should be included allowing for use of
|
||||||
|
* {@link #setErrorText(String)}
|
||||||
|
*/
|
||||||
|
public PasswordDialog(String title, String serverType, String serverName, String passPrompt,
|
||||||
|
boolean allowUserIdEntry, String userIdPrompt, String defaultUserId,
|
||||||
|
boolean hasMessages) {
|
||||||
super(title, true);
|
super(title, true);
|
||||||
|
|
||||||
this.defaultUserID = defaultUserID;
|
this.defaultUserId = defaultUserId;
|
||||||
|
|
||||||
setRememberSize(false);
|
setRememberSize(false);
|
||||||
setTransient(true);
|
setTransient(true);
|
||||||
|
|
||||||
if (hasMessages) {
|
if (hasMessages) {
|
||||||
setMinimumSize(300, 150);
|
setMinimumSize(350, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
workPanel = new JPanel(new PairLayout(5, 5));
|
workPanel = new JPanel(new PairLayout(5, 5));
|
||||||
|
@ -136,20 +173,27 @@ public class PasswordDialog extends DialogComponentProvider {
|
||||||
workPanel.add(new GLabel(serverName));
|
workPanel.add(new GLabel(serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userIdPrompt != null) {
|
if (StringUtils.isBlank(userIdPrompt)) {
|
||||||
|
userIdPrompt = "User ID:";
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(passPrompt)) {
|
||||||
|
passPrompt = "Password:";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowUserIdEntry) {
|
||||||
workPanel.add(new GLabel(userIdPrompt));
|
workPanel.add(new GLabel(userIdPrompt));
|
||||||
nameField = new JTextField(defaultUserID, 16);
|
nameField = new JTextField(defaultUserId, 16);
|
||||||
nameField.setName("NAME-ENTRY-COMPONENT");
|
nameField.setName("NAME-ENTRY-COMPONENT");
|
||||||
workPanel.add(nameField);
|
workPanel.add(nameField);
|
||||||
}
|
}
|
||||||
else if (defaultUserID != null) {
|
else if (defaultUserId != null) {
|
||||||
workPanel.add(new GLabel("User ID:"));
|
workPanel.add(new GLabel(userIdPrompt));
|
||||||
JLabel nameLabel = new GLabel(defaultUserID);
|
JLabel nameLabel = new GLabel(defaultUserId);
|
||||||
nameLabel.setName("NAME-COMPONENT");
|
nameLabel.setName("NAME-COMPONENT");
|
||||||
workPanel.add(nameLabel);
|
workPanel.add(nameLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
workPanel.add(new GLabel(passPrompt != null ? passPrompt : "Password:"));
|
workPanel.add(new GLabel(passPrompt));
|
||||||
passwordField = new JPasswordField(16);
|
passwordField = new JPasswordField(16);
|
||||||
passwordField.setName("PASSWORD-ENTRY-COMPONENT");
|
passwordField.setName("PASSWORD-ENTRY-COMPONENT");
|
||||||
workPanel.add(passwordField);
|
workPanel.add(passwordField);
|
||||||
|
@ -245,7 +289,7 @@ public class PasswordDialog extends DialogComponentProvider {
|
||||||
* @return the user ID / Name entered in the password field
|
* @return the user ID / Name entered in the password field
|
||||||
*/
|
*/
|
||||||
public String getUserID() {
|
public String getUserID() {
|
||||||
return nameField != null ? nameField.getText().trim() : defaultUserID;
|
return nameField != null ? nameField.getText().trim() : defaultUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -63,7 +62,7 @@ public class PopupKeyStorePasswordProvider implements KeyStorePasswordProvider {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PasswordDialog pwdDialog =
|
PasswordDialog pwdDialog =
|
||||||
new PasswordDialog("Protected PKI Certificate", "Cert File", file, null, null, null);
|
new PasswordDialog("Protected PKI Certificate", "Cert File", file, null);
|
||||||
if (passwordError) {
|
if (passwordError) {
|
||||||
pwdDialog.setErrorText("Incorrect password");
|
pwdDialog.setErrorText("Incorrect password");
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -139,8 +139,8 @@ public class SplashScreenTest extends AbstractDockingTest {
|
||||||
private DockingDialog showModalPasswordDialog(Frame parentFrame) throws Exception {
|
private DockingDialog showModalPasswordDialog(Frame parentFrame) throws Exception {
|
||||||
|
|
||||||
String dialogTitle = "InfoWindowTest.testSplashScreenPasswordModality() Dialog";
|
String dialogTitle = "InfoWindowTest.testSplashScreenPasswordModality() Dialog";
|
||||||
DialogComponentProvider passwordDialog = runSwing(() -> new PasswordDialog(dialogTitle,
|
DialogComponentProvider passwordDialog =
|
||||||
"Server Type", "Server Name", "Prompt", null, null));
|
runSwing(() -> new PasswordDialog(dialogTitle, "Server Type", "Server Name", "Prompt"));
|
||||||
|
|
||||||
if (parentFrame == null) {
|
if (parentFrame == null) {
|
||||||
// null means to share the parent
|
// null means to share the parent
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -33,10 +33,11 @@ public interface ClientAuthenticator extends KeyStorePasswordProvider {
|
||||||
public Authenticator getAuthenticator();
|
public Authenticator getAuthenticator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process Ghidra Server password authentication callbacks.
|
* Process password authentication callbacks.
|
||||||
* @param title password prompt title if GUI is used
|
* @param title password prompt title if GUI is used
|
||||||
* @param serverType type of server (label associated with serverName)
|
* @param serverType type of server (label associated with serverName)
|
||||||
* @param serverName name of server
|
* @param serverName name of server
|
||||||
|
* @param allowUserNameEntry if true user ID entry will be supported if nameCb is not null.
|
||||||
* @param nameCb provides storage for user login name. A null indicates
|
* @param nameCb provides storage for user login name. A null indicates
|
||||||
* that the default user name will be used, @see ClientUtil#getUserName()
|
* that the default user name will be used, @see ClientUtil#getUserName()
|
||||||
* @param passCb provides storage for user password, @see PasswordCallback#setPassword(char[])
|
* @param passCb provides storage for user password, @see PasswordCallback#setPassword(char[])
|
||||||
|
@ -51,8 +52,8 @@ public interface ClientAuthenticator extends KeyStorePasswordProvider {
|
||||||
* @return true if password provided, false if entry cancelled
|
* @return true if password provided, false if entry cancelled
|
||||||
*/
|
*/
|
||||||
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
||||||
NameCallback nameCb, PasswordCallback passCb, ChoiceCallback choiceCb,
|
boolean allowUserNameEntry, NameCallback nameCb, PasswordCallback passCb,
|
||||||
AnonymousCallback anonymousCb, String loginError);
|
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String loginError);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompt user for reconnect
|
* Prompt user for reconnect
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -425,7 +425,8 @@ public class ClientUtil {
|
||||||
"Unsupported authentication callback: " + callbacks[0].getClass().getName());
|
"Unsupported authentication callback: " + callbacks[0].getClass().getName());
|
||||||
}
|
}
|
||||||
if (!clientAuthenticator.processPasswordCallbacks("Repository Server Authentication",
|
if (!clientAuthenticator.processPasswordCallbacks("Repository Server Authentication",
|
||||||
"Repository Server", serverName, nameCb, passCb, choiceCb, anonymousCb, loginError)) {
|
"Repository Server", serverName, nameCb != null, nameCb, passCb, choiceCb, anonymousCb,
|
||||||
|
loginError)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String name = defaultUserID;
|
String name = defaultUserID;
|
||||||
|
|
|
@ -72,13 +72,14 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
|
|
||||||
if (pwd != null) {
|
if (pwd != null) {
|
||||||
// Requesting URL specified password
|
// Requesting URL specified password
|
||||||
return new PasswordAuthentication(userName, pwd.toCharArray());
|
return new PasswordAuthentication(userName, pwd.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
NameCallback nameCb = new NameCallback("Name: ", userName);
|
NameCallback nameCb = new NameCallback("Name: ", userName);
|
||||||
|
boolean allowUserIDEntry = true;
|
||||||
if (!useDefaultUser) {
|
if (!useDefaultUser) {
|
||||||
// Prevent modification of user name by password prompting
|
|
||||||
nameCb.setName(userName);
|
nameCb.setName(userName);
|
||||||
|
allowUserIDEntry = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt for password
|
// Prompt for password
|
||||||
|
@ -89,10 +90,10 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
PasswordCallback passCb = new PasswordCallback(prompt, false);
|
PasswordCallback passCb = new PasswordCallback(prompt, false);
|
||||||
try {
|
try {
|
||||||
ServerPasswordPrompt pp = new ServerPasswordPrompt("Connection Authentication",
|
ServerPasswordPrompt pp = new ServerPasswordPrompt("Connection Authentication",
|
||||||
"Server", serverName, nameCb, passCb, null, null, null);
|
"Server", serverName, allowUserIDEntry, nameCb, passCb, null, null, null);
|
||||||
SystemUtilities.runSwingNow(pp);
|
SystemUtilities.runSwingNow(pp);
|
||||||
if (pp.okWasPressed()) {
|
if (pp.okWasPressed()) {
|
||||||
return new PasswordAuthentication(nameCb.getName(), passCb.getPassword());
|
return new PasswordAuthentication(nameCb.getName(), passCb.getPassword());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -135,10 +136,10 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
||||||
NameCallback nameCb, PasswordCallback passCb, ChoiceCallback choiceCb,
|
boolean allowUserNameEntry, NameCallback nameCb, PasswordCallback passCb,
|
||||||
AnonymousCallback anonymousCb, String loginError) {
|
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String loginError) {
|
||||||
ServerPasswordPrompt pp = new ServerPasswordPrompt(title, serverType, serverName, nameCb,
|
ServerPasswordPrompt pp = new ServerPasswordPrompt(title, serverType, serverName,
|
||||||
passCb, choiceCb, anonymousCb, loginError);
|
allowUserNameEntry, nameCb, passCb, choiceCb, anonymousCb, loginError);
|
||||||
SystemUtilities.runSwingNow(pp);
|
SystemUtilities.runSwingNow(pp);
|
||||||
return pp.okWasPressed();
|
return pp.okWasPressed();
|
||||||
}
|
}
|
||||||
|
@ -172,6 +173,7 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
private String title;
|
private String title;
|
||||||
private String serverType; // label for serverName field
|
private String serverType; // label for serverName field
|
||||||
private String serverName;
|
private String serverName;
|
||||||
|
private boolean allowUserIDEntry;
|
||||||
private NameCallback nameCb;
|
private NameCallback nameCb;
|
||||||
private PasswordCallback passCb;
|
private PasswordCallback passCb;
|
||||||
private ChoiceCallback choiceCb;
|
private ChoiceCallback choiceCb;
|
||||||
|
@ -180,11 +182,12 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
private boolean okPressed = false;
|
private boolean okPressed = false;
|
||||||
|
|
||||||
ServerPasswordPrompt(String title, String serverType, String serverName,
|
ServerPasswordPrompt(String title, String serverType, String serverName,
|
||||||
NameCallback nameCb, PasswordCallback passCb, ChoiceCallback choiceCb,
|
boolean allowUserIDEntry, NameCallback nameCb, PasswordCallback passCb,
|
||||||
AnonymousCallback anonymousCb, String errorMsg) {
|
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String errorMsg) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.serverType = serverType;
|
this.serverType = serverType;
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
|
this.allowUserIDEntry = allowUserIDEntry && (nameCb != null);
|
||||||
this.nameCb = nameCb;
|
this.nameCb = nameCb;
|
||||||
this.passCb = passCb;
|
this.passCb = passCb;
|
||||||
this.choiceCb = choiceCb;
|
this.choiceCb = choiceCb;
|
||||||
|
@ -225,20 +228,20 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
String defaultUserName = null;
|
String defaultUserName = null;
|
||||||
String namePrompt = null;
|
String namePrompt = null;
|
||||||
if (nameCb != null) {
|
if (nameCb != null) {
|
||||||
|
namePrompt = nameCb.getPrompt();
|
||||||
defaultUserName = nameCb.getName();
|
defaultUserName = nameCb.getName();
|
||||||
if (defaultUserName == null) {
|
if (StringUtils.isBlank(defaultUserName)) {
|
||||||
// Name entry only permitted with name callback where name has not be pre-set
|
|
||||||
defaultUserName = nameCb.getDefaultName();
|
defaultUserName = nameCb.getDefaultName();
|
||||||
namePrompt = nameCb.getPrompt();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defaultUserName == null) {
|
|
||||||
|
if (StringUtils.isBlank(defaultUserName)) {
|
||||||
defaultUserName = getDefaultUserName();
|
defaultUserName = getDefaultUserName();
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordDialog pwdDialog = new PasswordDialog(title, serverType, serverName,
|
PasswordDialog pwdDialog = new PasswordDialog(title, serverType, serverName,
|
||||||
passCb.getPrompt(), namePrompt, defaultUserName, choicePrompt, choices,
|
passCb.getPrompt(), allowUserIDEntry, namePrompt, defaultUserName, choicePrompt,
|
||||||
getDefaultChoice(), anonymousCb != null);
|
choices, getDefaultChoice(), anonymousCb != null);
|
||||||
|
|
||||||
if (errorMsg != null) {
|
if (errorMsg != null) {
|
||||||
pwdDialog.setErrorText(errorMsg);
|
pwdDialog.setErrorText(errorMsg);
|
||||||
|
@ -252,7 +255,7 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
passCb.setPassword(pwdDialog.getPassword());
|
passCb.setPassword(pwdDialog.getPassword());
|
||||||
if (nameCb != null) {
|
if (nameCb != null && allowUserIDEntry) {
|
||||||
String username = pwdDialog.getUserID();
|
String username = pwdDialog.getUserID();
|
||||||
nameCb.setName(username);
|
nameCb.setName(username);
|
||||||
Preferences.setProperty(NAME_PREFERENCE, username);
|
Preferences.setProperty(NAME_PREFERENCE, username);
|
||||||
|
|
|
@ -39,22 +39,25 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
private final static char[] BADPASSWORD = "".toCharArray();
|
private final static char[] BADPASSWORD = "".toCharArray();
|
||||||
|
|
||||||
private static Object sshPrivateKey;
|
private static Object sshPrivateKey;
|
||||||
private static String defaultUserName = ClientUtil.getUserName();
|
private static String preferredName = null;
|
||||||
private static boolean passwordPromptAllowed;
|
private static boolean passwordPromptAllowed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple authentication handler using a default authenticator which may be passed to
|
||||||
|
* {@link Authenticator#setDefault(Authenticator)}. The preferred username must be set by
|
||||||
|
* invoking {@link #installHeadlessClientAuthenticator(String, String, boolean)} or
|
||||||
|
* stipulated by the requesting URL. The {@link ClientUtil#getUserName()} identity is never
|
||||||
|
* used.
|
||||||
|
*/
|
||||||
private Authenticator authenticator = new Authenticator() {
|
private Authenticator authenticator = new Authenticator() {
|
||||||
@Override
|
@Override
|
||||||
protected PasswordAuthentication getPasswordAuthentication() {
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
|
||||||
if (defaultUserName == null) {
|
|
||||||
throw new IllegalStateException("Default user name is unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
String serverName = getRequestingHost();
|
String serverName = getRequestingHost();
|
||||||
URL requestingURL = getRequestingURL(); // may be null
|
URL requestingURL = getRequestingURL(); // may be null
|
||||||
|
|
||||||
String pwd = null;
|
String pwd = null;
|
||||||
String userName = defaultUserName;
|
String name = preferredName;
|
||||||
|
|
||||||
if (requestingURL != null) {
|
if (requestingURL != null) {
|
||||||
String userInfo = requestingURL.getUserInfo();
|
String userInfo = requestingURL.getUserInfo();
|
||||||
|
@ -62,12 +65,12 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
// Use user info from URL
|
// Use user info from URL
|
||||||
int pwdSep = userInfo.indexOf(':');
|
int pwdSep = userInfo.indexOf(':');
|
||||||
if (pwdSep < 0) {
|
if (pwdSep < 0) {
|
||||||
userName = userInfo;
|
name = userInfo;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pwd = userInfo.substring(pwdSep + 1);
|
pwd = userInfo.substring(pwdSep + 1);
|
||||||
if (pwdSep != 0) {
|
if (pwdSep != 0) {
|
||||||
userName = userInfo.substring(0, pwdSep);
|
name = userInfo.substring(0, pwdSep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,20 +80,24 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
serverName = minimalURL.toExternalForm();
|
serverName = minimalURL.toExternalForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg.debug(this, "PasswordAuthentication requested for " + serverName);
|
Msg.debug(this, "PasswordAuthentication requested for " + serverName);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(name)) {
|
||||||
|
throw new IllegalStateException("Connection user name is unknown");
|
||||||
|
}
|
||||||
|
|
||||||
if (pwd != null) {
|
if (pwd != null) {
|
||||||
// Requesting URL specified password
|
// Requesting URL specified password
|
||||||
return new PasswordAuthentication(userName, pwd.toCharArray());
|
return new PasswordAuthentication(name, pwd.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
String usage = "Access password requested for " + serverName;
|
String usage = "Access password requested for " + serverName;
|
||||||
String prompt = getRequestingPrompt();
|
String prompt = getRequestingPrompt();
|
||||||
if (StringUtils.isBlank(prompt) || "security".equals(prompt)) {
|
if (StringUtils.isBlank(prompt) || "security".equals(prompt)) {
|
||||||
prompt = "Password for " + userName +":";
|
prompt = "Password for " + name + ":";
|
||||||
}
|
}
|
||||||
return new PasswordAuthentication(userName, getPassword(usage, prompt));
|
return new PasswordAuthentication(name, getPassword(usage, prompt));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +110,9 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install headless client authenticator for Ghidra Server
|
* Install headless client authenticator for Ghidra Server and when http/https
|
||||||
|
* connections require authentication and have not specified user information.
|
||||||
|
*
|
||||||
* @param username optional username to be used with a Ghidra Server which
|
* @param username optional username to be used with a Ghidra Server which
|
||||||
* allows username to be specified. If null, {@link ClientUtil#getUserName()}
|
* allows username to be specified. If null, {@link ClientUtil#getUserName()}
|
||||||
* will be used.
|
* will be used.
|
||||||
|
@ -118,7 +127,7 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
boolean allowPasswordPrompt) throws IOException {
|
boolean allowPasswordPrompt) throws IOException {
|
||||||
passwordPromptAllowed = allowPasswordPrompt;
|
passwordPromptAllowed = allowPasswordPrompt;
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
defaultUserName = username;
|
preferredName = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear existing key store settings
|
// clear existing key store settings
|
||||||
|
@ -247,45 +256,48 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
||||||
NameCallback nameCb, PasswordCallback passCb, ChoiceCallback choiceCb,
|
boolean allowUserNameEntry, NameCallback nameCb, PasswordCallback passCb,
|
||||||
AnonymousCallback anonymousCb, String loginError) {
|
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String loginError) {
|
||||||
if (anonymousCb != null && !passwordPromptAllowed) {
|
if (anonymousCb != null && !passwordPromptAllowed) {
|
||||||
// Assume that login error will not occur with anonymous login
|
// Assume that login error will not occur with anonymous login
|
||||||
anonymousCb.setAnonymousAccessRequested(true);
|
anonymousCb.setAnonymousAccessRequested(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultUserName == null) {
|
|
||||||
throw new IllegalStateException("Default user name is unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (choiceCb != null) {
|
if (choiceCb != null) {
|
||||||
choiceCb.setSelectedIndex(1);
|
choiceCb.setSelectedIndex(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String userName = null;
|
String userName = null;
|
||||||
if (nameCb != null) {
|
if (nameCb != null) {
|
||||||
userName = nameCb.getName();
|
if (allowUserNameEntry) {
|
||||||
if (userName == null) {
|
// use preferred login name
|
||||||
userName = nameCb.getDefaultName();
|
userName = preferredName;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(userName)) {
|
||||||
|
// check for default login name in order of precedence
|
||||||
|
userName = nameCb.getName();
|
||||||
|
if (StringUtils.isBlank(userName)) {
|
||||||
|
userName = nameCb.getDefaultName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowUserNameEntry) {
|
||||||
|
nameCb.setName(userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (userName == null) {
|
|
||||||
userName = defaultUserName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nameCb != null) {
|
if (!StringUtils.isBlank(userName)) {
|
||||||
nameCb.setName(defaultUserName);
|
userName = ClientUtil.getUserName();
|
||||||
}
|
}
|
||||||
|
|
||||||
String usage = null;
|
String usage = null;
|
||||||
if (serverName != null) {
|
if (serverName != null) {
|
||||||
usage = serverType + ": " + serverName;
|
usage = serverType + ": " + serverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore prompt specified by passCb
|
// Ignore prompt specified by passCb
|
||||||
String prompt = "Password for " + userName +":";
|
String prompt = "Password for " + userName + ":";
|
||||||
|
|
||||||
char[] password = getPassword(usage, prompt);
|
char[] password = getPassword(usage, prompt);
|
||||||
passCb.setPassword(password);
|
passCb.setPassword(password);
|
||||||
return password != null;
|
return password != null;
|
||||||
|
@ -321,7 +333,18 @@ public class HeadlessClientAuthenticator implements ClientAuthenticator {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nameCb != null) {
|
if (nameCb != null) {
|
||||||
nameCb.setName(defaultUserName);
|
// presence of NameCallback implies user is allowed to specify name
|
||||||
|
String userName = preferredName;
|
||||||
|
if (StringUtils.isBlank(userName)) {
|
||||||
|
userName = nameCb.getName();
|
||||||
|
if (StringUtils.isBlank(userName)) {
|
||||||
|
userName = nameCb.getDefaultName();
|
||||||
|
}
|
||||||
|
if (!StringUtils.isBlank(userName)) {
|
||||||
|
userName = ClientUtil.getUserName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nameCb.setName(userName);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
sshCb.sign(sshPrivateKey);
|
sshCb.sign(sshPrivateKey);
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -83,14 +83,24 @@ public class PasswordClientAuthenticator implements ClientAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processPasswordCallbacks(String title, String serverType,
|
public boolean processPasswordCallbacks(String title, String serverType, String serverName,
|
||||||
String serverName, NameCallback nameCb, PasswordCallback passCb,
|
boolean allowUserNameEntry, NameCallback nameCb, PasswordCallback passCb,
|
||||||
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String loginError) {
|
ChoiceCallback choiceCb, AnonymousCallback anonymousCb, String loginError) {
|
||||||
if (choiceCb != null) {
|
if (choiceCb != null) {
|
||||||
choiceCb.setSelectedIndex(1);
|
choiceCb.setSelectedIndex(1);
|
||||||
}
|
}
|
||||||
if (nameCb != null && username != null) {
|
if (nameCb != null && allowUserNameEntry) {
|
||||||
nameCb.setName(username);
|
String name = username;
|
||||||
|
if (name == null) {
|
||||||
|
name = nameCb.getName();
|
||||||
|
}
|
||||||
|
if (name == null) {
|
||||||
|
name = nameCb.getDefaultName();
|
||||||
|
}
|
||||||
|
if (name == null) {
|
||||||
|
name = ClientUtil.getUserName();
|
||||||
|
}
|
||||||
|
nameCb.setName(name);
|
||||||
}
|
}
|
||||||
passCb.setPassword(password.clone());
|
passCb.setPassword(password.clone());
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue