use of javax.security.sasl.SaslException in project zookeeper by apache.
the class ZooKeeperSaslClient method createSaslClient.
private SaslClient createSaslClient(final String servicePrincipal, final String loginContext) throws LoginException {
try {
if (!initializedLogin) {
synchronized (this) {
if (login == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("JAAS loginContext is: " + loginContext);
}
// note that the login object is static: it's shared amongst all zookeeper-related connections.
// in order to ensure the login is initialized only once, it must be synchronized the code snippet.
login = new Login(loginContext, new ClientCallbackHandler(null), clientConfig);
login.startThreadIfNeeded();
initializedLogin = true;
}
}
}
Subject subject = login.getSubject();
SaslClient saslClient;
// if empty, use DIGEST-MD5; otherwise, use GSSAPI.
if (subject.getPrincipals().isEmpty()) {
// no principals: must not be GSSAPI: use DIGEST-MD5 mechanism instead.
LOG.info("Client will use DIGEST-MD5 as SASL mechanism.");
String[] mechs = { "DIGEST-MD5" };
String username = (String) (subject.getPublicCredentials().toArray()[0]);
String password = (String) (subject.getPrivateCredentials().toArray()[0]);
// "zk-sasl-md5" is a hard-wired 'domain' parameter shared with zookeeper server code (see ServerCnxnFactory.java)
saslClient = Sasl.createSaslClient(mechs, username, "zookeeper", "zk-sasl-md5", null, new ClientCallbackHandler(password));
return saslClient;
} else {
// GSSAPI.
boolean usingNativeJgss = clientConfig.getBoolean(ZKConfig.JGSS_NATIVE);
if (usingNativeJgss) {
// """
try {
GSSManager manager = GSSManager.getInstance();
Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
GSSCredential cred = manager.createCredential(null, GSSContext.DEFAULT_LIFETIME, krb5Mechanism, GSSCredential.INITIATE_ONLY);
subject.getPrivateCredentials().add(cred);
if (LOG.isDebugEnabled()) {
LOG.debug("Added private credential to subject: " + cred);
}
} catch (GSSException ex) {
LOG.warn("Cannot add private credential to subject; " + "authentication at the server may fail", ex);
}
}
final Object[] principals = subject.getPrincipals().toArray();
// determine client principal from subject.
final Principal clientPrincipal = (Principal) principals[0];
final KerberosName clientKerberosName = new KerberosName(clientPrincipal.getName());
// assume that server and client are in the same realm (by default; unless the system property
// "zookeeper.server.realm" is set).
String serverRealm = clientConfig.getProperty(ZKClientConfig.ZOOKEEPER_SERVER_REALM, clientKerberosName.getRealm());
KerberosName serviceKerberosName = new KerberosName(servicePrincipal + "@" + serverRealm);
final String serviceName = serviceKerberosName.getServiceName();
final String serviceHostname = serviceKerberosName.getHostName();
final String clientPrincipalName = clientKerberosName.toString();
try {
saslClient = Subject.doAs(subject, new PrivilegedExceptionAction<SaslClient>() {
public SaslClient run() throws SaslException {
LOG.info("Client will use GSSAPI as SASL mechanism.");
String[] mechs = { "GSSAPI" };
LOG.debug("creating sasl client: client=" + clientPrincipalName + ";service=" + serviceName + ";serviceHostname=" + serviceHostname);
SaslClient saslClient = Sasl.createSaslClient(mechs, clientPrincipalName, serviceName, serviceHostname, null, new ClientCallbackHandler(null));
return saslClient;
}
});
return saslClient;
} catch (Exception e) {
LOG.error("Exception while trying to create SASL client", e);
e.printStackTrace();
return null;
}
}
} catch (LoginException e) {
// We throw LoginExceptions...
throw e;
} catch (Exception e) {
// ..but consume (with a log message) all other types of exceptions.
LOG.error("Exception while trying to create SASL client: " + e);
return null;
}
}
use of javax.security.sasl.SaslException in project zookeeper by apache.
the class ZooKeeperSaslServer method createSaslServer.
private SaslServer createSaslServer(final Login login) {
synchronized (login) {
Subject subject = login.getSubject();
if (subject != null) {
// server is using a JAAS-authenticated subject: determine service principal name and hostname from zk server's subject.
if (subject.getPrincipals().size() > 0) {
try {
final Object[] principals = subject.getPrincipals().toArray();
final Principal servicePrincipal = (Principal) principals[0];
// e.g. servicePrincipalNameAndHostname := "zookeeper/myhost.foo.com@FOO.COM"
final String servicePrincipalNameAndHostname = servicePrincipal.getName();
int indexOf = servicePrincipalNameAndHostname.indexOf("/");
// e.g. serviceHostnameAndKerbDomain := "myhost.foo.com@FOO.COM"
final String serviceHostnameAndKerbDomain = servicePrincipalNameAndHostname.substring(indexOf + 1, servicePrincipalNameAndHostname.length());
int indexOfAt = serviceHostnameAndKerbDomain.indexOf("@");
// Handle Kerberos Service as well as User Principal Names
final String servicePrincipalName, serviceHostname;
if (indexOf > 0) {
// e.g. servicePrincipalName := "zookeeper"
servicePrincipalName = servicePrincipalNameAndHostname.substring(0, indexOf);
// e.g. serviceHostname := "myhost.foo.com"
serviceHostname = serviceHostnameAndKerbDomain.substring(0, indexOfAt);
} else {
servicePrincipalName = servicePrincipalNameAndHostname.substring(0, indexOfAt);
serviceHostname = null;
}
// TODO: should depend on zoo.cfg specified mechs, but if subject is non-null, it can be assumed to be GSSAPI.
final String mech = "GSSAPI";
LOG.debug("serviceHostname is '" + serviceHostname + "'");
LOG.debug("servicePrincipalName is '" + servicePrincipalName + "'");
LOG.debug("SASL mechanism(mech) is '" + mech + "'");
boolean usingNativeJgss = Boolean.getBoolean("sun.security.jgss.native");
if (usingNativeJgss) {
// """
try {
GSSManager manager = GSSManager.getInstance();
Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
GSSName gssName = manager.createName(servicePrincipalName + "@" + serviceHostname, GSSName.NT_HOSTBASED_SERVICE);
GSSCredential cred = manager.createCredential(gssName, GSSContext.DEFAULT_LIFETIME, krb5Mechanism, GSSCredential.ACCEPT_ONLY);
subject.getPrivateCredentials().add(cred);
if (LOG.isDebugEnabled()) {
LOG.debug("Added private credential to subject: " + cred);
}
} catch (GSSException ex) {
LOG.warn("Cannot add private credential to subject; " + "clients authentication may fail", ex);
}
}
try {
return Subject.doAs(subject, new PrivilegedExceptionAction<SaslServer>() {
public SaslServer run() {
try {
SaslServer saslServer;
saslServer = Sasl.createSaslServer(mech, servicePrincipalName, serviceHostname, null, login.callbackHandler);
return saslServer;
} catch (SaslException e) {
LOG.error("Zookeeper Server failed to create a SaslServer to interact with a client during session initiation: " + e);
e.printStackTrace();
return null;
}
}
});
} catch (PrivilegedActionException e) {
// TODO: exit server at this point(?)
LOG.error("Zookeeper Quorum member experienced a PrivilegedActionException exception while creating a SaslServer using a JAAS principal context:" + e);
e.printStackTrace();
}
} catch (IndexOutOfBoundsException e) {
LOG.error("server principal name/hostname determination error: ", e);
}
} else {
// TODO: use 'authMech=' value in zoo.cfg.
try {
SaslServer saslServer = Sasl.createSaslServer("DIGEST-MD5", "zookeeper", "zk-sasl-md5", null, login.callbackHandler);
return saslServer;
} catch (SaslException e) {
LOG.error("Zookeeper Quorum member failed to create a SaslServer to interact with a client during session initiation", e);
}
}
}
}
LOG.error("failed to create saslServer object.");
return null;
}
use of javax.security.sasl.SaslException in project zookeeper by apache.
the class ZooKeeperServer method processSasl.
private Record processSasl(ByteBuffer incomingBuffer, ServerCnxn cnxn) throws IOException {
LOG.debug("Responding to client SASL token.");
GetSASLRequest clientTokenRecord = new GetSASLRequest();
ByteBufferInputStream.byteBuffer2Record(incomingBuffer, clientTokenRecord);
byte[] clientToken = clientTokenRecord.getToken();
LOG.debug("Size of client SASL token: " + clientToken.length);
byte[] responseToken = null;
try {
ZooKeeperSaslServer saslServer = cnxn.zooKeeperSaslServer;
try {
// note that clientToken might be empty (clientToken.length == 0):
// if using the DIGEST-MD5 mechanism, clientToken will be empty at the beginning of the
// SASL negotiation process.
responseToken = saslServer.evaluateResponse(clientToken);
if (saslServer.isComplete()) {
String authorizationID = saslServer.getAuthorizationID();
LOG.info("adding SASL authorization for authorizationID: " + authorizationID);
cnxn.addAuthInfo(new Id("sasl", authorizationID));
}
} catch (SaslException e) {
LOG.warn("Client failed to SASL authenticate: " + e, e);
if ((System.getProperty("zookeeper.allowSaslFailedClients") != null) && (System.getProperty("zookeeper.allowSaslFailedClients").equals("true"))) {
LOG.warn("Maintaining client connection despite SASL authentication failure.");
} else {
LOG.warn("Closing client connection due to SASL authentication failure.");
cnxn.close();
}
}
} catch (NullPointerException e) {
LOG.error("cnxn.saslServer is null: cnxn object did not initialize its saslServer properly.");
}
if (responseToken != null) {
LOG.debug("Size of server SASL response: " + responseToken.length);
}
// wrap SASL response token to client inside a Response object.
return new SetSASLResponse(responseToken);
}
use of javax.security.sasl.SaslException in project Smack by igniterealtime.
the class SASLJavaXMechanism method authenticateInternal.
@Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackException {
String[] mechanisms = { getName() };
Map<String, String> props = getSaslProps();
try {
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
} catch (SaslException e) {
throw new SmackException(e);
}
}
use of javax.security.sasl.SaslException in project Openfire by igniterealtime.
the class DefaultAuthProvider method setPassword.
@Override
public void setPassword(String username, String password) throws UserNotFoundException {
// Determine if the password should be stored as plain text or encrypted.
boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword");
boolean scramOnly = JiveGlobals.getBooleanProperty("user.scramHashedPasswordOnly");
String encryptedPassword = null;
if (username.contains("@")) {
// Check that the specified domain matches the server's domain
int index = username.indexOf("@");
String domain = username.substring(index + 1);
if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
username = username.substring(0, index);
} else {
// Unknown domain.
throw new UserNotFoundException();
}
}
// Store the salt and salted password so SCRAM-SHA-1 SASL auth can be used later.
byte[] saltShaker = new byte[24];
random.nextBytes(saltShaker);
String salt = DatatypeConverter.printBase64Binary(saltShaker);
int iterations = JiveGlobals.getIntProperty("sasl.scram-sha-1.iteration-count", ScramUtils.DEFAULT_ITERATION_COUNT);
byte[] saltedPassword = null, clientKey = null, storedKey = null, serverKey = null;
try {
saltedPassword = ScramUtils.createSaltedPassword(saltShaker, password, iterations);
clientKey = ScramUtils.computeHmac(saltedPassword, "Client Key");
storedKey = MessageDigest.getInstance("SHA-1").digest(clientKey);
serverKey = ScramUtils.computeHmac(saltedPassword, "Server Key");
} catch (SaslException | NoSuchAlgorithmException e) {
Log.warn("Unable to persist values for SCRAM authentication.");
}
if (!scramOnly && !usePlainPassword) {
try {
encryptedPassword = AuthFactory.encryptPassword(password);
// Set password to null so that it's inserted that way.
password = null;
} catch (UnsupportedOperationException uoe) {
// Encryption may fail. In that case, ignore the error and
// the plain password will be stored.
}
}
if (scramOnly) {
encryptedPassword = null;
password = null;
}
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(UPDATE_PASSWORD);
if (password == null) {
pstmt.setNull(1, Types.VARCHAR);
} else {
pstmt.setString(1, password);
}
if (encryptedPassword == null) {
pstmt.setNull(2, Types.VARCHAR);
} else {
pstmt.setString(2, encryptedPassword);
}
if (storedKey == null) {
pstmt.setNull(3, Types.VARCHAR);
} else {
pstmt.setString(3, DatatypeConverter.printBase64Binary(storedKey));
}
if (serverKey == null) {
pstmt.setNull(4, Types.VARCHAR);
} else {
pstmt.setString(4, DatatypeConverter.printBase64Binary(serverKey));
}
pstmt.setString(5, salt);
pstmt.setInt(6, iterations);
pstmt.setString(7, username);
pstmt.executeUpdate();
} catch (SQLException sqle) {
throw new UserNotFoundException(sqle);
} finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
Aggregations