feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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 General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
*
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
* ===========================================================================
|
||||
*
|
||||
*/
|
||||
package sun.security.krb5.internal.ccache;
|
||||
|
||||
import sun.security.krb5.*;
|
||||
import sun.security.krb5.internal.*;
|
||||
import sun.security.util.SecurityProperties;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Vector;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* CredentialsCache stores credentials(tickets, session keys, etc) in a
|
||||
* semi-permanent store
|
||||
* for later use by different program.
|
||||
*
|
||||
* @author Yanni Zhang
|
||||
* @author Ram Marti
|
||||
*/
|
||||
|
||||
public class FileCredentialsCache extends CredentialsCache
|
||||
implements FileCCacheConstants {
|
||||
public int version;
|
||||
public Tag tag; // optional
|
||||
public PrincipalName primaryPrincipal;
|
||||
private Vector<Credentials> credentialsList;
|
||||
private static String dir;
|
||||
private static boolean DEBUG = Krb5.DEBUG;
|
||||
|
||||
public static synchronized FileCredentialsCache acquireInstance(
|
||||
PrincipalName principal, String cache) {
|
||||
try {
|
||||
FileCredentialsCache fcc = new FileCredentialsCache();
|
||||
if (cache == null) {
|
||||
cacheName = FileCredentialsCache.getDefaultCacheName();
|
||||
} else {
|
||||
cacheName = FileCredentialsCache.checkValidation(cache);
|
||||
}
|
||||
if ((cacheName == null) || !(new File(cacheName)).exists()) {
|
||||
// invalid cache name or the file doesn't exist
|
||||
return null;
|
||||
}
|
||||
if (principal != null) {
|
||||
fcc.primaryPrincipal = principal;
|
||||
}
|
||||
fcc.load(cacheName);
|
||||
return fcc;
|
||||
} catch (IOException e) {
|
||||
// we don't handle it now, instead we return a null at the end.
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (KrbException e) {
|
||||
// we don't handle it now, instead we return a null at the end.
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FileCredentialsCache acquireInstance() {
|
||||
return acquireInstance(null, null);
|
||||
}
|
||||
|
||||
static synchronized FileCredentialsCache New(PrincipalName principal,
|
||||
String name) {
|
||||
try {
|
||||
FileCredentialsCache fcc = new FileCredentialsCache();
|
||||
cacheName = FileCredentialsCache.checkValidation(name);
|
||||
if (cacheName == null) {
|
||||
// invalid cache name or the file doesn't exist
|
||||
return null;
|
||||
}
|
||||
fcc.init(principal, cacheName);
|
||||
return fcc;
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
catch (KrbException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static synchronized FileCredentialsCache New(PrincipalName principal) {
|
||||
try {
|
||||
FileCredentialsCache fcc = new FileCredentialsCache();
|
||||
cacheName = FileCredentialsCache.getDefaultCacheName();
|
||||
fcc.init(principal, cacheName);
|
||||
return fcc;
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (KrbException e) {
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private FileCredentialsCache() {
|
||||
}
|
||||
|
||||
boolean exists(String cache) {
|
||||
File file = new File(cache);
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
synchronized void init(PrincipalName principal, String name)
|
||||
throws IOException, KrbException {
|
||||
primaryPrincipal = principal;
|
||||
try (FileOutputStream fos = new FileOutputStream(name);
|
||||
CCacheOutputStream cos = new CCacheOutputStream(fos)) {
|
||||
version = KRB5_FCC_FVNO_3;
|
||||
cos.writeHeader(primaryPrincipal, version);
|
||||
}
|
||||
load(name);
|
||||
}
|
||||
|
||||
synchronized void load(String name) throws IOException, KrbException {
|
||||
PrincipalName p;
|
||||
try (FileInputStream fis = new FileInputStream(name);
|
||||
CCacheInputStream cis = new CCacheInputStream(fis)) {
|
||||
version = cis.readVersion();
|
||||
if (version == KRB5_FCC_FVNO_4) {
|
||||
tag = cis.readTag();
|
||||
} else {
|
||||
tag = null;
|
||||
if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) {
|
||||
cis.setNativeByteOrder();
|
||||
}
|
||||
}
|
||||
p = cis.readPrincipal(version);
|
||||
|
||||
if (primaryPrincipal != null) {
|
||||
if (!(primaryPrincipal.match(p))) {
|
||||
throw new IOException("Primary principals don't match.");
|
||||
}
|
||||
} else
|
||||
primaryPrincipal = p;
|
||||
credentialsList = new Vector<Credentials>();
|
||||
while (cis.available() > 0) {
|
||||
Object cred = cis.readCred(version);
|
||||
if (cred != null) {
|
||||
if (cred instanceof Credentials) {
|
||||
credentialsList.addElement((Credentials)cred);
|
||||
} else {
|
||||
addConfigEntry((CredentialsCache.ConfigEntry)cred);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the credentials list. If the specified credentials for the
|
||||
* service is new, add it to the list. If there is an entry in the list,
|
||||
* replace the old credentials with the new one.
|
||||
* @param c the credentials.
|
||||
*/
|
||||
|
||||
public synchronized void update(Credentials c) {
|
||||
if (credentialsList != null) {
|
||||
if (credentialsList.isEmpty()) {
|
||||
credentialsList.addElement(c);
|
||||
} else {
|
||||
Credentials tmp = null;
|
||||
boolean matched = false;
|
||||
|
||||
for (int i = 0; i < credentialsList.size(); i++) {
|
||||
tmp = credentialsList.elementAt(i);
|
||||
if (match(c.sname.getNameStrings(),
|
||||
tmp.sname.getNameStrings()) &&
|
||||
((c.sname.getRealmString()).equalsIgnoreCase(
|
||||
tmp.sname.getRealmString()))) {
|
||||
matched = true;
|
||||
if (c.endtime.getTime() >= tmp.endtime.getTime()) {
|
||||
if (DEBUG) {
|
||||
System.out.println(" >>> FileCredentialsCache "
|
||||
+ "Ticket matched, overwrite "
|
||||
+ "the old one.");
|
||||
}
|
||||
credentialsList.removeElementAt(i);
|
||||
credentialsList.addElement(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matched == false) {
|
||||
if (DEBUG) {
|
||||
System.out.println(" >>> FileCredentialsCache Ticket "
|
||||
+ "not exactly matched, "
|
||||
+ "add new one into cache.");
|
||||
}
|
||||
|
||||
credentialsList.addElement(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized PrincipalName getPrimaryPrincipal() {
|
||||
return primaryPrincipal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves the credentials cache file to the disk.
|
||||
*/
|
||||
public synchronized void save() throws IOException, Asn1Exception {
|
||||
try (FileOutputStream fos = new FileOutputStream(cacheName);
|
||||
CCacheOutputStream cos = new CCacheOutputStream(fos)) {
|
||||
cos.writeHeader(primaryPrincipal, version);
|
||||
Credentials[] tmp = null;
|
||||
if ((tmp = getCredsList()) != null) {
|
||||
for (int i = 0; i < tmp.length; i++) {
|
||||
cos.addCreds(tmp[i]);
|
||||
}
|
||||
}
|
||||
for (ConfigEntry e : getConfigEntries()) {
|
||||
cos.addConfigEntry(primaryPrincipal, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean match(String[] s1, String[] s2) {
|
||||
if (s1.length != s2.length) {
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 0; i < s1.length; i++) {
|
||||
if (!(s1[i].equalsIgnoreCase(s2[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of credentials entries in the cache file.
|
||||
*/
|
||||
public synchronized Credentials[] getCredsList() {
|
||||
if ((credentialsList == null) || (credentialsList.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
Credentials[] tmp = new Credentials[credentialsList.size()];
|
||||
for (int i = 0; i < credentialsList.size(); i++) {
|
||||
tmp[i] = credentialsList.elementAt(i);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Credentials getCreds(LoginOptions options, PrincipalName sname) {
|
||||
if (options == null) {
|
||||
return getCreds(sname);
|
||||
} else {
|
||||
Credentials[] list = getCredsList();
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
if (sname.match(list[i].sname)) {
|
||||
if (list[i].flags.match(options)) {
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ConfigEntry> configEntries = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void addConfigEntry(ConfigEntry e) {
|
||||
configEntries.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigEntry> getConfigEntries() {
|
||||
return Collections.unmodifiableList(configEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a credentials for a specified service.
|
||||
* @param sname service principal name.
|
||||
*/
|
||||
public Credentials getCreds(PrincipalName sname) {
|
||||
Credentials[] list = getCredsList();
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
if (sname.match(list[i].sname)) {
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public sun.security.krb5.Credentials getInitialCreds() {
|
||||
|
||||
Credentials defaultCreds = getDefaultCreds();
|
||||
if (defaultCreds == null) {
|
||||
return null;
|
||||
}
|
||||
sun.security.krb5.Credentials tgt = defaultCreds.setKrbCreds();
|
||||
|
||||
CredentialsCache.ConfigEntry entry = getConfigEntry("proxy_impersonator");
|
||||
if (entry == null) {
|
||||
if (DEBUG) {
|
||||
System.out.println("get normal credential");
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
boolean force;
|
||||
String prop = SecurityProperties.privilegedGetOverridable(
|
||||
"jdk.security.krb5.default.initiate.credential");
|
||||
if (prop == null) {
|
||||
prop = "always-impersonate";
|
||||
}
|
||||
switch (prop) {
|
||||
case "no-impersonate": // never try impersonation
|
||||
if (DEBUG) {
|
||||
System.out.println("get normal credential");
|
||||
}
|
||||
return tgt;
|
||||
case "try-impersonate":
|
||||
force = false;
|
||||
break;
|
||||
case "always-impersonate":
|
||||
force = true;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Invalid jdk.security.krb5.default.initiate.credential");
|
||||
}
|
||||
|
||||
try {
|
||||
PrincipalName service = new PrincipalName(
|
||||
new String(entry.getData(), StandardCharsets.UTF_8));
|
||||
if (!tgt.getClient().equals(service)) {
|
||||
if (DEBUG) {
|
||||
System.out.println("proxy_impersonator does not match service name");
|
||||
}
|
||||
return force ? null : tgt;
|
||||
}
|
||||
PrincipalName client = getPrimaryPrincipal();
|
||||
Credentials proxy = null;
|
||||
for (Credentials c : getCredsList()) {
|
||||
if (c.getClientPrincipal().equals(client)
|
||||
&& c.getServicePrincipal().equals(service)) {
|
||||
proxy = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (proxy == null) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Cannot find evidence ticket in ccache");
|
||||
}
|
||||
return force ? null : tgt;
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println("Get proxied credential");
|
||||
}
|
||||
return tgt.setProxy(proxy.setKrbCreds());
|
||||
} catch (KrbException e) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Impersonation with ccache failed");
|
||||
}
|
||||
return force ? null : tgt;
|
||||
}
|
||||
}
|
||||
|
||||
public Credentials getDefaultCreds() {
|
||||
Credentials[] list = getCredsList();
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else {
|
||||
for (int i = list.length-1; i >= 0; i--) {
|
||||
if (list[i].sname.toString().startsWith("krbtgt")) {
|
||||
String[] nameStrings = list[i].sname.getNameStrings();
|
||||
// find the TGT for the current realm krbtgt/realm@realm
|
||||
if (nameStrings[1].equals(list[i].sname.getRealm().toString())) {
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns path name of the credentials cache file.
|
||||
* The path name is searched in the following order:
|
||||
*
|
||||
* 1. KRB5CCNAME (bare file name without FILE:)
|
||||
* 2. /tmp/krb5cc_<uid> on unix systems
|
||||
* 3. <user.home>/krb5cc_<user.name>
|
||||
* 4. <user.home>/krb5cc (if can't get <user.name>)
|
||||
*/
|
||||
|
||||
public static String getDefaultCacheName() {
|
||||
|
||||
String stdCacheNameComponent = "krb5cc";
|
||||
String name;
|
||||
|
||||
// The env var can start with TYPE:, we only support FILE: here.
|
||||
// https://docs.oracle.com/cd/E19082-01/819-2252/6n4i8rtr3/index.html
|
||||
name = java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
String cache = System.getenv("KRB5CCNAME");
|
||||
if (cache != null &&
|
||||
(cache.length() >= 5) &&
|
||||
cache.regionMatches(true, 0, "FILE:", 0, 5)) {
|
||||
cache = cache.substring(5);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
});
|
||||
if (name != null) {
|
||||
if (DEBUG) {
|
||||
System.out.println(">>>KinitOptions cache name is " + name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// get cache name from system.property
|
||||
String osname =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("os.name"));
|
||||
|
||||
/*
|
||||
* For Unix platforms we use the default cache name to be
|
||||
* /tmp/krbcc_uid ; for all other platforms we use
|
||||
* {user_home}/krb5_cc{user_name}
|
||||
* Please note that for Windows 2K we will use LSA to get
|
||||
* the TGT from the the default cache even before we come here;
|
||||
* however when we create cache we will create a cache under
|
||||
* {user_home}/krb5_cc{user_name} for non-Unix platforms including
|
||||
* Windows 2K.
|
||||
*/
|
||||
|
||||
if (osname != null) {
|
||||
String cmd = null;
|
||||
String uidStr = null;
|
||||
long uid = 0;
|
||||
|
||||
if (!osname.startsWith("Windows")) {
|
||||
try {
|
||||
Class<?> c = Class.forName
|
||||
("com.sun.security.auth.module.UnixSystem");
|
||||
Constructor<?> constructor = c.getConstructor();
|
||||
Object obj = constructor.newInstance();
|
||||
Method method = c.getMethod("getUid");
|
||||
uid = ((Long)method.invoke(obj)).longValue();
|
||||
name = File.separator + "tmp" +
|
||||
File.separator + stdCacheNameComponent + "_" + uid;
|
||||
if (DEBUG) {
|
||||
System.out.println(">>>KinitOptions cache name is " +
|
||||
name);
|
||||
}
|
||||
return name;
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Exception in obtaining uid " +
|
||||
"for Unix platforms " +
|
||||
"Using user's home directory");
|
||||
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we did not get the uid;
|
||||
|
||||
|
||||
String user_name =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("user.name"));
|
||||
|
||||
String user_home =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("user.home"));
|
||||
|
||||
if (user_home == null) {
|
||||
user_home =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("user.dir"));
|
||||
}
|
||||
|
||||
if (user_name != null) {
|
||||
name = user_home + File.separator +
|
||||
stdCacheNameComponent + "_" + user_name;
|
||||
} else {
|
||||
name = user_home + File.separator + stdCacheNameComponent;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println(">>>KinitOptions cache name is " + name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String checkValidation(String name) {
|
||||
String fullname = null;
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// get full path name
|
||||
fullname = (new File(name)).getCanonicalPath();
|
||||
File fCheck = new File(fullname);
|
||||
if (!(fCheck.exists())) {
|
||||
// get absolute directory
|
||||
File temp = new File(fCheck.getParent());
|
||||
// test if the directory exists
|
||||
if (!(temp.isDirectory()))
|
||||
fullname = null;
|
||||
temp = null;
|
||||
}
|
||||
fCheck = null;
|
||||
|
||||
} catch (IOException e) {
|
||||
fullname = null; // invalid name
|
||||
}
|
||||
return fullname;
|
||||
}
|
||||
|
||||
|
||||
private static String exec(String c) {
|
||||
StringTokenizer st = new StringTokenizer(c);
|
||||
Vector<String> v = new Vector<>();
|
||||
while (st.hasMoreTokens()) {
|
||||
v.addElement(st.nextToken());
|
||||
}
|
||||
final String[] command = new String[v.size()];
|
||||
v.copyInto(command);
|
||||
try {
|
||||
|
||||
Process p =
|
||||
java.security.AccessController.doPrivileged
|
||||
(new java.security.PrivilegedAction<Process> () {
|
||||
public Process run() {
|
||||
try {
|
||||
return (Runtime.getRuntime().exec(command));
|
||||
} catch (java.io.IOException e) {
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (p == null) {
|
||||
// exception occurred during executing the command
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedReader commandResult =
|
||||
new BufferedReader
|
||||
(new InputStreamReader(p.getInputStream(), "8859_1"));
|
||||
String s1 = null;
|
||||
if ((command.length == 1) &&
|
||||
(command[0].equals("/usr/bin/env"))) {
|
||||
while ((s1 = commandResult.readLine()) != null) {
|
||||
if (s1.length() >= 11) {
|
||||
if ((s1.substring(0, 11)).equalsIgnoreCase
|
||||
("KRB5CCNAME=")) {
|
||||
s1 = s1.substring(11);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else s1 = commandResult.readLine();
|
||||
commandResult.close();
|
||||
return s1;
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user