2222import ch .cyberduck .core .exception .LocalAccessDeniedException ;
2323import ch .cyberduck .core .exception .LoginCanceledException ;
2424import ch .cyberduck .core .exception .LoginFailureException ;
25+ import ch .cyberduck .core .ssl .X509KeyManager ;
2526import ch .cyberduck .core .threading .CancelCallback ;
2627
2728import org .apache .commons .lang3 .StringUtils ;
@@ -44,75 +45,88 @@ public KeychainLoginService(final HostPasswordStore keychain) {
4445 }
4546
4647 @ Override
47- public void validate (final Host bookmark , final LoginCallback prompt , final LoginOptions options ) throws ConnectionCanceledException , LoginFailureException {
48- log .debug ("Validate login credentials for {}" , bookmark );
49- final Credentials credentials = bookmark .getCredentials ();
48+ public void validate (final Session <?> session , final LoginCallback prompt , final LoginOptions options ) throws ConnectionCanceledException , LoginFailureException {
49+ log .debug ("Validate login credentials for {}" , session );
50+ final Host host = session .getHost ();
51+ final Credentials credentials = host .getCredentials ();
5052 if (credentials .isPublicKeyAuthentication ()) {
5153 if (!credentials .getIdentity ().attributes ().getPermission ().isReadable ()) {
5254 log .warn ("Prompt to select identity file not readable {}" , credentials .getIdentity ());
5355 credentials .setIdentity (prompt .select (credentials .getIdentity ()));
5456 }
5557 }
5658 if (options .keychain ) {
57- log .debug ("Lookup credentials in keychain for {}" , bookmark );
59+ log .debug ("Lookup credentials in keychain for {}" , host );
5860 if (options .password ) {
5961 if (StringUtils .isBlank (credentials .getPassword ())) {
60- final String password = keychain .findLoginPassword (bookmark );
62+ final String password = keychain .findLoginPassword (host );
6163 if (StringUtils .isNotBlank (password )) {
62- log .info ("Fetched password from keychain for {}" , bookmark );
64+ log .info ("Fetched password from keychain for {}" , host );
6365 // No need to reinsert found password to the keychain.
6466 credentials .setPassword (password ).setSaved (false );
6567 }
6668 }
6769 }
6870 if (options .token ) {
6971 if (StringUtils .isBlank (credentials .getToken ())) {
70- final String token = keychain .findLoginToken (bookmark );
72+ final String token = keychain .findLoginToken (host );
7173 if (StringUtils .isNotBlank (token )) {
72- log .info ("Fetched token from keychain for {}" , bookmark );
74+ log .info ("Fetched token from keychain for {}" , host );
7375 // No need to reinsert found token to the keychain.
7476 credentials .setToken (token ).setSaved (false );
7577 }
7678 }
7779 }
7880 if (options .publickey ) {
79- final String passphrase = keychain .findPrivateKeyPassphrase (bookmark );
81+ final String passphrase = keychain .findPrivateKeyPassphrase (host );
8082 if (StringUtils .isNotBlank (passphrase )) {
81- log .info ("Fetched private key passphrase from keychain for {}" , bookmark );
83+ log .info ("Fetched private key passphrase from keychain for {}" , host );
8284 // No need to reinsert found token to the keychain.
8385 credentials .setIdentityPassphrase (passphrase ).setSaved (false );
8486 }
8587 }
8688 if (options .oauth ) {
87- final OAuthTokens tokens = keychain .findOAuthTokens (bookmark );
89+ final OAuthTokens tokens = keychain .findOAuthTokens (host );
8890 if (tokens .validate ()) {
89- log .info ("Fetched OAuth tokens {} from keychain for {}" , tokens , bookmark );
91+ log .info ("Fetched OAuth tokens {} from keychain for {}" , tokens , host );
9092 // No need to reinsert found token to the keychain.
9193 credentials .setOauth (tokens ).setSaved (tokens .isExpired ());
9294 }
9395 }
96+ if (options .certificate ) {
97+ final String alias = host .getCredentials ().getCertificate ();
98+ if (StringUtils .isNotBlank (alias )) {
99+ final X509KeyManager manager = session .getFeature (X509KeyManager .class );
100+ if (manager != null ) {
101+ if (null == manager .getPrivateKey (alias )) {
102+ log .warn ("No private key found for alias {} in keychain" , alias );
103+ throw new LoginFailureException (LocaleFactory .localizedString ("Provide additional login credentials" , "Credentials" ));
104+ }
105+ }
106+ }
107+ }
94108 }
95- if (!credentials .validate (bookmark .getProtocol (), options )) {
109+ if (!credentials .validate (host .getProtocol (), options )) {
96110 log .warn ("Failed validation of credentials {} with options {}" , credentials , options );
97- final CredentialsConfigurator configurator = CredentialsConfiguratorFactory .get (bookmark .getProtocol ());
111+ final CredentialsConfigurator configurator = CredentialsConfiguratorFactory .get (host .getProtocol ());
98112 log .debug ("Auto configure credentials with {}" , configurator );
99- final Credentials configuration = configurator .configure (bookmark );
100- if (configuration .validate (bookmark .getProtocol (), options )) {
101- bookmark .setCredentials (configuration );
102- log .info ("Auto configured credentials {} for {}" , configuration , bookmark );
113+ final Credentials configuration = configurator .configure (host );
114+ if (configuration .validate (host .getProtocol (), options )) {
115+ host .setCredentials (configuration );
116+ log .info ("Auto configured credentials {} for {}" , configuration , host );
103117 return ;
104118 }
105119 final StringAppender message = new StringAppender ();
106120 if (options .password ) {
107121 message .append (MessageFormat .format (LocaleFactory .localizedString (
108- "Login {0} with username and password" , "Credentials" ), BookmarkNameProvider .toString (bookmark )));
122+ "Login {0} with username and password" , "Credentials" ), BookmarkNameProvider .toString (host )));
109123 }
110124 if (options .publickey ) {
111125 message .append (LocaleFactory .localizedString (
112126 "Select the private key in PEM or PuTTY format" , "Credentials" ));
113127 }
114128 message .append (LocaleFactory .localizedString ("No login credentials could be found in the Keychain" , "Credentials" ));
115- this .prompt (bookmark , message .toString (), prompt , options );
129+ this .prompt (host , message .toString (), prompt , options );
116130 }
117131 log .debug ("Validated credentials {} with options {}" , credentials , options );
118132 }
0 commit comments