blob: d763bf2127fced7a34afb9225ebfb4f9fb116804 [file] [log] [blame]
/**
* @copyright
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
* @endcopyright
*/
package org.apache.subversion.javahl.callback;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
/**
* <p>The interface for requesting authentication credentials from the
* user. Should the javahl bindings need the matching information,
* these methodes will be called.</p>
*
* <p>This callback can also be used to provide the equivalent of the
* <code>--no-auth-cache</code> and <code>--non-interactive</code>
* arguments accepted by the command-line client.</p>
*
* @since 1.9
*/
public interface AuthnCallback
{
/**
* Abstract base class for callback results.
*/
public abstract class AuthnResult
{
protected boolean save = false; // Allow saving the credentials
protected boolean trust = false; // SSL server cert trust
protected String identity = null; // Username or client cert filename
protected String secret = null; // Password or client cert passphrase
}
/**
* The result type used by {@see #usernamePrompt}.
*/
public static final class UsernameResult
extends AuthnResult
implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* Set the username in the result.
* Assumes the result may not be stored permanently.
* @param username The username.
*/
public UsernameResult(String username)
{
identity = username;
}
/**
* Set the username in the result.
* @param username The username.
* @param maySave Set if the result may be stored permanently.
*/
public UsernameResult(String username, boolean maySave)
{
save = maySave;
identity = username;
}
}
/**
* Ask for a username.
* @param realm The realm from which the question originates.
* @param maySave Indiceates whether saving credentials is allowed;
* if <code>false</code>, the <code>maySave</code> flag
* in the return value will be ignored.
* @return The result, or <code>null</code> if cancelled.
*/
public UsernameResult usernamePrompt(String realm, boolean maySave);
/**
* The result type used by {@see #userPasswordPrompt}.
*/
public static final class UserPasswordResult
extends AuthnResult
implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* Set the username and password in the result.
* Assumes the result may not be stored permanently.
* @param username The username.
* @param password The password.
*/
public UserPasswordResult(String username, String password)
{
identity = username;
secret = password;
}
/**
* Set the username and password in the result.
* @param username The user name.
* @param password The password.
* @param maySave Set if the result may be stored permanently.
*/
public UserPasswordResult(String username, String password,
boolean maySave)
{
save = maySave;
identity = username;
secret = password;
}
}
/**
* Ask for a username and password.
* @param realm The realm from which the question originates.
* @param username The username for the realm, if known; may be <code>null</code>.
* @param maySave Indiceates whether saving credentials is allowed;
* if <code>false</code>, the <code>maySave</code> flag
* in the return value will be ignored.
* @return The result, or <code>null</code> if cancelled.
*/
public UserPasswordResult userPasswordPrompt(String realm, String username,
boolean maySave);
/**
* Information about why parsing a server SSL certificate failed.
*/
public static class SSLServerCertFailures implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* The certificate is not yet valid.
*/
public boolean notYetValid()
{
return ((failures & NOT_YET_VALID) != 0);
}
/**
* The certificate has expired.
*/
public boolean expired()
{
return ((failures & EXPIRED) != 0);
}
/**
* Certificate's CN (hostname) does not match the remote hostname.
*/
public boolean cnMismatch()
{
return ((failures & CN_MISMATCH) != 0);
}
/**
* Certificate authority is unknown (i.e., not trusted).
*/
public boolean unknownCA()
{
return ((failures & UNKNOWN_CA) != 0);
}
/**
* Other failure. This can happen if an unknown failure occurs
* that we do not handle yet.
*/
public boolean other()
{
return ((failures & OTHER) != 0 || (failures & ~ALL_KNOWN) != 0);
}
/** @return the internal bitfield representation of the failures. */
public int getFailures()
{
return failures;
}
private static final int NOT_YET_VALID = 0x00000001;
private static final int EXPIRED = 0x00000002;
private static final int CN_MISMATCH = 0x00000004;
private static final int UNKNOWN_CA = 0x00000008;
private static final int OTHER = 0x40000000;
private static final int ALL_KNOWN = (NOT_YET_VALID | EXPIRED
| CN_MISMATCH | UNKNOWN_CA
| OTHER);
/* This private constructor is used by the native implementation. */
private SSLServerCertFailures(int failures)
{
/* Double-check that we did not forget to map any of the
failure flags, and flag an "other" failure. */
final int missing = (failures & ~ALL_KNOWN);
if (missing != 0) {
Logger log = Logger.getLogger("org.apache.subversion.javahl");
log.warning(String.format("Unknown SSL certificate parsing "
+ "failure flags: %1$x", missing));
}
this.failures = failures;
}
private int failures;
}
/**
* Detailed information about the parsed server SSL certificate.
*/
public static class SSLServerCertInfo implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* @return The subject of the certificate.
*/
public String getSubject()
{
return subject;
}
/**
* @return The certificate issuer.
*/
public String getIssuer()
{
return issuer;
}
/**
* @return The from which the certificate is valid.
*/
public Date getValidFrom()
{
return validFrom;
}
/**
* @return The date after which the certificate is no longer valid.
*/
public Date getValidTo()
{
return validTo;
}
/**
* @return The certificate fingerprint.
*/
public byte[] getFingerprint()
{
return fingerprint;
}
/**
* @return A list of host names that the certificate represents.
*/
public List<String> getHostnames()
{
return hostnames;
}
/**
* @return the Base64-encoded raw certificate data.
*/
public String getCert()
{
return asciiCert;
}
/* This private constructor is used by the native implementation. */
private SSLServerCertInfo(String subject, String issuer,
long validFrom, long validTo,
byte[] fingerprint,
List<String> hostnames,
String asciiCert)
{
this.subject = subject;
this.issuer = issuer;
this.validFrom = new Date(validFrom);
this.validTo = new Date(validTo);
this.fingerprint = fingerprint;
this.hostnames = hostnames;
this.asciiCert = asciiCert;
}
private String subject;
private String issuer;
private Date validFrom;
private Date validTo;
private byte[] fingerprint;
private List<String> hostnames;
private String asciiCert;
}
/**
* The result type used by {@see #sslServerTrustPrompt}.
*/
public static final class SSLServerTrustResult
extends AuthnResult
implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* Create a result that rejects the certificate.
*/
public static SSLServerTrustResult reject()
{
return new SSLServerTrustResult(false, false);
}
/**
* Create a result that temporarily accepts the certificate,
* for the duration of the current connection.
*/
public static SSLServerTrustResult acceptTemporarily()
{
return new SSLServerTrustResult(true, false);
}
/**
* Create a result that permanently accepts the certificate.
*/
public static SSLServerTrustResult acceptPermanently()
{
return new SSLServerTrustResult(true, true);
}
private SSLServerTrustResult(boolean accept, boolean maySave)
{
save = maySave;
trust = accept;
}
}
/**
* Ask if we trust the server certificate.
* @param realm The realm from which the question originates.
* @param failures The result of parsing the certificate;
* if <code>null</code>, there were no failures.
* @param info Information extracted from the certificate.
* @param maySave Indiceates whether saving credentials is allowed;
* if <code>false</code>, the <code>maySave</code> flag
* in the return value will be ignored.
* @return The result, or <code>null</code> if cancelled.
*/
public SSLServerTrustResult
sslServerTrustPrompt(String realm,
SSLServerCertFailures failures,
SSLServerCertInfo info,
boolean maySave);
/**
* The result type used by {@see #sslClientCertPrompt}.
*/
public static final class SSLClientCertResult
extends AuthnResult
implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* Set the absolute path of the cerfiticate file in the result.
* Assumes the result may not be stored permanently.
* @param path The absolute path of the certificate.
*/
public SSLClientCertResult(String path)
{
identity = path;
}
/**
* Set the absolute path of the cerfiticate file in the result.
* @param path The absolute path of the certificate.
* @param maySave Set if the result may be stored permanently.
*/
public SSLClientCertResult(String path, boolean maySave)
{
save = maySave;
identity = path;
}
}
/**
* Ask for the (local) file name of a client SSL certificate.
* @param realm The realm from which the question originates.
* @param maySave Indiceates whether saving credentials is allowed;
* if <code>false</code>, the <code>maySave</code> flag
* in the return value will be ignored.
* @return The result, or <code>null</code> if cancelled.
*/
public SSLClientCertResult
sslClientCertPrompt(String realm, boolean maySave);
/**
* The result type used by {@see #sslClientCertPassphrasePrompt}.
*/
public static final class SSLClientCertPassphraseResult
extends AuthnResult
implements java.io.Serializable
{
// Update the serialVersionUID when there is an incompatible change made to
// this class. See the Java documentation (following link or its counter-
// part in your specific Java release) for when a change is incompatible.
// https://docs.oracle.com/en/java/javase/11/docs/specs/serialization/version.html#type-changes-affecting-serialization
private static final long serialVersionUID = 1L;
/**
* Set the cerfiticate passphrase in the result.
* Assumes the result may not be stored permanently.
* @param passphrase The passphrase for decrypting the certificate.
*/
public SSLClientCertPassphraseResult(String passphrase)
{
secret = passphrase;
}
/**
* Set the cerfiticate passphrase in the result.
* @param passphrase The passphrase for decrypting the certificate.
* @param maySave Set if the result may be stored permanently.
*/
public SSLClientCertPassphraseResult(String passphrase, boolean maySave)
{
save = maySave;
secret = passphrase;
}
}
/**
* Ask for passphrase for decrypting a client SSL certificate.
* @param realm The realm from which the question originates.
* @param maySave Indiceates whether saving credentials is allowed;
* if <code>false</code>, the <code>maySave</code> flag
* in the return value will be ignored.
* @return The result, or <code>null</code> if cancelled.
*/
public SSLClientCertPassphraseResult
sslClientCertPassphrasePrompt(String realm, boolean maySave);
/**
* Ask if a password may be stored on disk in plaintext.
* @param realm The realm from which the question originates.
* @return <code>true</code> if the password may be stored in plaintext.
*/
public boolean allowStorePlaintextPassword(String realm);
/**
* Ask if a certificate passphrase may be stored on disk in plaintext.
* @param realm The realm from which the question originates.
* @return <code>true</code> if the passphrase may be stored in plaintext.
*/
public boolean allowStorePlaintextPassphrase(String realm);
}