/*
* Copyright (c) 2012-2015 iWave Software LLC
* All Rights Reserved
*/
package com.iwave.ext.kerberos;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.Checksum;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.log4j.Logger;
/**
* The kerberos config krb5File (krb5.conf) contains all of the configuration for
* kerberos realms. It would be great if you could programmatically set the
* realms before access but you cannot. Everything is set through system properties
* and in the krb5.conf krb5File.
*
* http://docs.oracle.com/javase/1.4.2/docs/guide/security/jgss/tutorials/KerberosReq.html
*
* This class provides a wrapper around this mechanism to allow the application
* to provide a dynamic list of realms. These are then written to the krb5.conf
* krb5File which is set up for Kerberos.
*
* @author Chris Dail
*/
public class KerberosConfig {
private static final Logger LOG = Logger.getLogger(KerberosConfig.class);
public static final String FILE_PREFIX = "krb5";
public static final String FILE_SUFFIX = ".conf.tmp";
private static KerberosConfig instance = new KerberosConfig();
public static KerberosConfig getInstance() {
return instance;
}
private File krb5File;
private long checksum = 0;
private KerberosConfig() {
}
public synchronized void initialize(String krb5Conf) throws IOException {
if (krb5Conf == null) {
return;
}
if (krb5File == null) {
krb5File = File.createTempFile(FILE_PREFIX, FILE_SUFFIX);
krb5File.deleteOnExit();
FileUtils.writeStringToFile(krb5File, krb5Conf);
System.setProperty("java.security.krb5.conf", krb5File.getAbsolutePath());
LOG.debug("Kerberos KRB5 configuration written to " + krb5File.getAbsolutePath());
checksum = FileUtils.checksumCRC32(krb5File);
return;
}
long newChecksum = checksumCRC32(krb5Conf);
// There is an existing krb5File, check the checksum is different
if (newChecksum != checksum) {
FileUtils.writeStringToFile(krb5File, krb5Conf);
LOG.debug("Updated Kerberos KRB5 configuration");
checksum = newChecksum;
}
}
public File getKrb5File() {
return krb5File;
}
private long checksumCRC32(String string) throws IOException {
Checksum sum = new CRC32();
InputStream in = null;
try {
in = new CheckedInputStream(new ByteArrayInputStream(string.getBytes()), sum);
IOUtils.copy(in, new NullOutputStream());
} finally {
IOUtils.closeQuietly(in);
}
return sum.getValue();
}
}