package com.sun.deploy.security;
import com.sun.deploy.config.Config;
import com.sun.deploy.util.Trace;
import sun.net.www.protocol.http.AuthCacheBridge;
import sun.net.www.protocol.http.AuthCacheImpl;
import sun.net.www.protocol.http.AuthCacheValue;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
public class CredentialManager {
public static final long LOGIN_SESSION_INVALID = -1;
protected static CredentialManager instance = null;
private CredentialCache credCache = new CredentialCache();
private CredentialPersistor persistor = new CredentialPersistor();
private Map serverMap;
protected CredentialManager() {
serverMap = persistor.getAllPersistedCredentials();
if (persistor.getSavedCredentialCount() > serverMap.size()) {
persistor.persistAllCredentials(serverMap);
}
AuthCacheValue.setAuthCache(credCache);
}
public static synchronized CredentialManager getInstance() {
if (instance == null) {
instance = new CredentialManager();
}
return instance;
}
protected long getLoginSessionId() {
return LOGIN_SESSION_INVALID;
}
protected boolean isPasswordEncryptionSupported() {
return false;
}
protected byte[] encryptPassword(char[] pass) {
return new byte[0];
}
protected char[] decryptPassword(byte[] pass) {
return new char[0];
}
public void saveCredential(AuthKey key, CredentialInfo info) {
info.setSessionId(getLoginSessionId());
CredentialInfo cred = (CredentialInfo) info.clone();
if (isPasswordEncryptionSupported() && cred.isPasswordSaveApproved()) {
cred.setEncryptedPassword(encryptPassword(info.getPassword()));
} else {
cred.setPassword(null);
}
String keyId = buildConnectionKey(key);
serverMap.put(keyId, cred);
persistor.persistCredential(keyId);
}
public boolean isCredentialValid(CredentialInfo info) {
boolean result = false;
if ((info.getUserName().length() > 0) &&
(info.getPassword().length > 0)) {
if ((info.getSessionId() != LOGIN_SESSION_INVALID) &&
(info.getSessionId() == getLoginSessionId())) {
result = true;
}
}
return result;
}
public static void removePersistantCredentials() {
try {
File f = new File(Config.getUserAuthFile());
if (f.delete() == false) {
f.deleteOnExit();
}
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
public void clearCredentialPassword(AuthKey key) {
String keyId = buildConnectionKey(key);
CredentialInfo info = findServerCredential(keyId);
if (!serverMap.containsKey(keyId) && info != null) {
info.setPassword(null);
saveCredential(key, info);
}
persistor.persistCredential(keyId);
}
protected CredentialInfo getCredential(AuthKey key) {
String keyId = buildConnectionKey(key);
CredentialInfo info = (CredentialInfo) serverMap.get(keyId);
if ((info == null) || ((info != null) && info.isCredentialEmpty())) {
info = findServerCredential(keyId);
if (info != null) {
info.setSessionId(LOGIN_SESSION_INVALID);
} else {
info = new CredentialInfo();
}
}
if (info.getPassword().length == 0) {
byte[] buff = info.getEncryptedPassword();
if (buff.length > 0) {
info.setPassword(decryptPassword(buff));
}
}
return info;
}
private CredentialInfo findServerCredential(String server) {
CredentialInfo info = null;
Set set = serverMap.keySet();
Iterator iter = set.iterator();
while (iter.hasNext() &&
(info == null || info.getEncryptedPassword().length == 0)) {
String key = (String) iter.next();
if (getServerFromKey(server).equals(getServerFromKey(key))) {
CredentialInfo cred = (CredentialInfo) serverMap.get(key);
if (!cred.isCredentialEmpty()) {
info = (CredentialInfo) serverMap.get(key);
}
}
}
return info;
}
private static String getServerFromKey(String conKey) {
StringTokenizer tokenizer = new StringTokenizer(conKey, ":");
return tokenizer.nextToken();
}
public static String buildConnectionKey(AuthKey con) {
StringBuffer buffer = new StringBuffer();
if (con.isProxy()) {
buffer.append("p:");
} else {
buffer.append("s:");
}
buffer.append(con.getProtocolScheme());
buffer.append(':');
buffer.append(con.getHost());
buffer.append(':');
buffer.append(con.getPort());
buffer.append(':');
buffer.append(con.getPath());
return buffer.toString().toLowerCase();
}
private class CredentialCache extends AuthCacheImpl {
HashMap map = new HashMap();
public CredentialCache() {
setMap(map);
}
public void remove(String server, AuthCacheValue value) {
try {
super.remove(server, value);
AuthCacheBridge cacheValue = new AuthCacheBridge(value);
CredentialManager.getInstance().clearCredentialPassword(cacheValue);
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
}
private class CredentialPersistor {
private int credentialCount = 0;
public CredentialPersistor() {
}
private int getSavedCredentialCount() {
return credentialCount;
}
private synchronized void persistCredential(String siteKey) {
ObjectOutputStream outStream = null;
try {
CredentialInfo info = (CredentialInfo) serverMap.get(siteKey);
if (info != null) {
OutputStream fout = openOutputFile(true);
outStream = new ObjectOutputStream(fout);
outStream.writeObject(siteKey);
info.writeExternal(outStream);
outStream.flush();
outStream.close();
fout.flush();
fout.close();
}
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
private synchronized void deleteCredentials() {
try {
File f = new File(Config.getUserAuthFile());
if (f.delete() == false) {
f.deleteOnExit();
}
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
private synchronized void persistAllCredentials(Map map) {
ObjectOutputStream outStream = null;
OutputStream fout = null;
try {
fout = openOutputFile(false);
Set set = map.keySet();
Iterator iter = set.iterator();
while (iter.hasNext()) {
outStream = new ObjectOutputStream(fout);
String key = (String) iter.next();
CredentialInfo info = (CredentialInfo) map.get(key);
outStream.writeObject(key);
info.writeExternal(outStream);
outStream.flush();
}
} catch (Throwable e) {
Trace.securityPrintException(e);
} finally {
try {
if (outStream != null) {
outStream.flush();
}
fout.flush();
fout.close();
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
}
private synchronized void getPersistedCredential(ObjectInputStream in,
String siteKey) {
try {
CredentialInfo info = new CredentialInfo();
info.readExternal(in);
serverMap.put(siteKey, info);
} catch (Exception e) {
Trace.securityPrintException(e);
}
}
private synchronized InputStream openInputStream() {
InputStream instream = null;
try {
final File f = new File(Config.getUserAuthFile());
instream =
(InputStream) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws IOException {
if (!f.exists()) {
f.getParentFile().mkdirs();
f.createNewFile();
}
return new BufferedInputStream(
new FileInputStream(f));
}
});
} catch (Exception e) {
Trace.securityPrintException(e);
}
return instream;
}
private synchronized OutputStream openOutputFile(final boolean append) {
OutputStream out = null;
try {
final File f = new File(Config.getUserAuthFile());
out = (OutputStream) AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws IOException {
if (!f.exists()) {
f.getParentFile().mkdirs();
f.createNewFile();
}
return new BufferedOutputStream(new FileOutputStream(
f, append));
}
});
} catch (Exception e) {
Trace.securityPrintException(e);
}
return out;
}
private synchronized Map getAllPersistedCredentials() {
ObjectInputStream in = null;
InputStream finstream = null;
Map map = null;
try {
map = new HashMap();
finstream = openInputStream();
in = new ObjectInputStream(finstream);
while (in != null) {
String siteKey = (String) in.readObject();
CredentialInfo info = new CredentialInfo();
info.readExternal(in);
map.put(siteKey, info);
++credentialCount;
in = new ObjectInputStream(finstream);
}
finstream.close();
} catch (java.io.EOFException e) {
} catch (Exception e) {
Trace.securityPrintException(e);
try {
finstream.close();
if (credentialCount > 0) {
persistAllCredentials(map);
}
} catch (Exception ex) {
Trace.securityPrintException(e);
}
}
return map;
}
}
}