org.mariadb.jdbc.internal.com.send.authentication.gssapi.StandardGssapiAuthentication Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mariadb-java-client Show documentation
Show all versions of mariadb-java-client Show documentation
JDBC driver for MariaDB and MySQL
/*
*
* MariaDB Client for Java
*
* Copyright (c) 2012-2014 Monty Program Ab.
* Copyright (c) 2015-2020 MariaDB Corporation Ab.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, write to Monty Program Ab [email protected].
*
* This particular MariaDB Client for Java file is work
* derived from a Drizzle-JDBC. Drizzle-JDBC file which is covered by subject to
* the following copyright and notice provisions:
*
* Copyright (c) 2009-2011, Marcus Eriksson
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* Neither the name of the driver nor the names of its contributors may not be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
*/
package org.mariadb.jdbc.internal.com.send.authentication.gssapi;
import java.io.*;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.ietf.jgss.*;
import org.mariadb.jdbc.internal.com.read.Buffer;
import org.mariadb.jdbc.internal.io.input.PacketInputStream;
import org.mariadb.jdbc.internal.io.output.PacketOutputStream;
public class StandardGssapiAuthentication implements GssapiAuth {
/**
* Process default GSS plugin authentication.
*
* @param out out stream
* @param in in stream
* @param sequence packet sequence
* @param servicePrincipalName service principal name
* @param mechanisms gssapi mechanism
* @throws IOException if socket error
* @throws SQLException in any Exception occur
*/
public void authenticate(
final PacketOutputStream out,
final PacketInputStream in,
final AtomicInteger sequence,
final String servicePrincipalName,
String mechanisms)
throws SQLException, IOException {
if ("".equals(servicePrincipalName)) {
throw new SQLException(
"No principal name defined on server. "
+ "Please set server variable \"gssapi-principal-name\" or set option \"servicePrincipalName\"",
"28000");
}
if (System.getProperty("java.security.auth.login.config") == null) {
final File jaasConfFile;
try {
jaasConfFile = File.createTempFile("jaas.conf", null);
try (PrintStream bos = new PrintStream(new FileOutputStream(jaasConfFile))) {
bos.print(
"Krb5ConnectorContext {\n"
+ "com.sun.security.auth.module.Krb5LoginModule required "
+ "useTicketCache=true "
+ "debug=true "
+ "renewTGT=true "
+ "doNotPrompt=true; };");
}
jaasConfFile.deleteOnExit();
} catch (final IOException ex) {
throw new UncheckedIOException(ex);
}
System.setProperty("java.security.auth.login.config", jaasConfFile.getCanonicalPath());
}
try {
LoginContext loginContext = new LoginContext("Krb5ConnectorContext");
// attempt authentication
loginContext.login();
final Subject mySubject = loginContext.getSubject();
if (!mySubject.getPrincipals().isEmpty()) {
try {
PrivilegedExceptionAction action =
() -> {
try {
Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
GSSManager manager = GSSManager.getInstance();
GSSName peerName = manager.createName(servicePrincipalName, GSSName.NT_USER_NAME);
GSSContext context =
manager.createContext(
peerName, krb5Mechanism, null, GSSContext.DEFAULT_LIFETIME);
context.requestMutualAuth(true);
byte[] inToken = new byte[0];
byte[] outToken;
while (!context.isEstablished()) {
outToken = context.initSecContext(inToken, 0, inToken.length);
// Send a token to the peer if one was generated by acceptSecContext
if (outToken != null) {
out.startPacket(sequence.incrementAndGet());
out.write(outToken);
out.flush();
}
if (!context.isEstablished()) {
Buffer buffer = in.getPacket(true);
sequence.set(in.getLastPacketSeq());
inToken = buffer.readRawBytes(buffer.remaining());
}
}
} catch (GSSException le) {
throw new SQLException("GSS-API authentication exception", "28000", 1045, le);
}
return null;
};
Subject.doAs(mySubject, action);
} catch (PrivilegedActionException exception) {
throw new SQLException("GSS-API authentication exception", "28000", 1045, exception);
}
} else {
throw new SQLException(
"GSS-API authentication exception : no credential cache not found.", "28000", 1045);
}
} catch (LoginException le) {
throw new SQLException("GSS-API authentication exception", "28000", 1045, le);
}
}
}