package org.vpac.grix.model.myproxy;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Date;
import org.apache.log4j.Logger;
import org.globus.gsi.CertUtil;
import org.globus.gsi.GSIConstants;
import org.globus.gsi.GlobusCredential;
import org.globus.gsi.OpenSSLKey;
import org.globus.gsi.bc.BouncyCastleCertProcessingFactory;
import org.globus.gsi.bc.BouncyCastleOpenSSLKey;
import org.globus.gsi.gssapi.GlobusGSSCredentialImpl;
import org.globus.myproxy.CredentialInfo;
import org.globus.myproxy.InitParams;
import org.globus.myproxy.MyProxy;
import org.globus.myproxy.MyProxyException;
import org.gridforum.jgss.ExtendedGSSManager;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.vpac.common.model.GlobusLocations;
import org.vpac.grix.control.utils.GrixProperty;
import org.vpac.grix.control.utils.UserProperty;
/**
* MyProxy related tasks. Have to rewrite that.
*
* @author Markus Binsteiner
*
*/
public class MyProxyCred {
static final Logger myLogger = Logger
.getLogger(MyProxyCred.class.getName());
static public final String myProxyHost = GrixProperty
.getString("myproxy.server");
static public final int myProxyPort = GrixProperty.getInt("myproxy.port");
static public final int myProxyKeylength = GrixProperty
.getInt("myproxy.keysize");
private String username = null;
private char[] myProxyPassphrase = null;
private String retrievers = null;
private String renewers = null;
private Date expires = null;
private String credential_name = "";
private File privateKey = null;
private File certificate = null;
private boolean isLoaded = false;
/**
* This creates a MyProxyCred without a password. You can use it for getting
* info about the credential (lifetime, etc) if you have a valid grid proxy.
*
* @param username
* the username of the MyProxy credentials (on the MyProxy
* server).
*/
public MyProxyCred(String username) {
this.username = username;
this.myProxyPassphrase = "DUMMY_DUMMY".toCharArray();
this.privateKey = GlobusLocations.defaultLocations().getUserKey();
this.certificate = GlobusLocations.defaultLocations().getUserCert();
this.expires = null;
this.renewers = "n/a";
this.retrievers = "n/a";
try {
getInfo();
} catch (MyProxyException mpe) {
// does not matter here
// mpe.printStackTrace();
}
}
/**
* This is used for uploading real MyProxy credentials to the server. It
* uses the default certificate and private key (in .globus directory)
*
* @param username
* the username
* @param myProxyPassphrase
* the myProxyPassphrase
*/
public MyProxyCred(String username, char[] myProxyPassphrase) {
this.privateKey = GlobusLocations.defaultLocations().getUserKey();
this.certificate = GlobusLocations.defaultLocations().getUserCert();
this.username = username;
this.myProxyPassphrase = myProxyPassphrase;
this.expires = null;
this.renewers = "n/a";
this.retrievers = "n/a";
try {
getInfo();
} catch (MyProxyException e) {
// does not matter here
}
Arrays.fill(myProxyPassphrase, 'x');
}
public GlobusCredential createGlobusCredential(char[] key_passphrase,
int lifetime) throws IOException, GeneralSecurityException {
// TODO check whether proxy already exists?
CertUtil.init();
BouncyCastleCertProcessingFactory factory = BouncyCastleCertProcessingFactory
.getDefault();
GlobusCredential globusCred = null;
X509Certificate cert = null;
OpenSSLKey key = null;
InputStream inCert;
inCert = new FileInputStream(certificate);
InputStream inKey = new FileInputStream(privateKey);
cert = CertUtil.loadCertificate(inCert);
key = new BouncyCastleOpenSSLKey(inKey);
key.decrypt(new String(key_passphrase));
myLogger.debug("Decrypted key.");
// myLogger.debug("Could not decrypt private key. Most likely wrong myProxyPassphrase.");
Arrays.fill(key_passphrase, 'x');
globusCred = factory.createCredential(new X509Certificate[] { cert },
key.getPrivateKey(), myProxyKeylength, lifetime,
GSIConstants.GSI_3_IMPERSONATION_PROXY);
// lifetime, GSIConstants.GSI_3_IMPERSONATION_PROXY);
myLogger.debug("Created credentials.");
return globusCred;
}
public boolean equals(MyProxyCred other) {
if (other.getUsername().equals(this.username)) {
return true;
}
return false;
}
public Date getExpires() {
// System.out.println ("Expires: "+ expires.toLocaleString());
return expires;
}
/**
* Loads information about the proxy (renewers, retrievers, lifetime)
*
* @throws GSSException
* if you don't have a credential file (/tmp/x509up_u...) to
* authenticate against the myproxy server on your computer
* @throws MyProxyException
* Not sure when this occurs.
*/
public void getInfo() throws MyProxyException {
isLoaded = false;
MyProxy myProxy = new MyProxy(myProxyHost, myProxyPort);
GSSManager manager = ExtendedGSSManager.getInstance();
GSSCredential cred = null;
try {
cred = manager.createCredential(GSSCredential.INITIATE_ONLY);
} catch (GSSException e) {
// should I throw an exception here?
return;
}
CredentialInfo info = myProxy.info(cred, username, new String(
myProxyPassphrase));
expires = info.getEndTimeAsDate();
retrievers = info.getRetrievers();
if ("".equals(retrievers)) {
retrievers = GrixProperty.getString("myproxy.default.retriever");
} else if ("*".equals(retrievers)) {
retrievers = "anonymous";
}
renewers = info.getRenewers();
if ("".equals(renewers)) {
renewers = GrixProperty.getString("myproxy.default.renewer");
} else if ("*".equals(renewers)) {
renewers = "anonymous";
}
isLoaded = true;
}
public String getRenewers() {
return renewers;
}
public String getRetrievers() {
return retrievers;
}
public String getUsername() {
return username;
}
/**
* Uploads Proxy credentials to a MyProxy server. If there are already
* credentials with the same username on the server (created with the same
* certificate, of course) then they will be overwritten.
*
* @param anonymous
* whether you want the credentials to be anonymously
* renewable/retrievable or not
* @param lifetime
* the lifetime of the credentials
* @param myProxyPassphrase
* the myProxyPassphrase of your private key
* @param myProxyPassphrase
* the myProxyPassphrase for the credentials on the server
* @throws GeneralSecurityException
* if you provide the wrong private key myProxyPassphrase
* @throws MyProxyException
* if the credential could not be created. (maybe the
* myProxyPassphrase for the MyProxy credential is too short or
* not complex enough, or the username already exists for
* another certificate, or...
* @throws IOException
* if the certificate / private key are not readable
* @throws GSSException
* I have not figured that out yet.
*/
public void init(GlobusCredential globusCred, boolean anonymous,
char[] myProxyPassphrase, int credentials_lifetime_in_hours)
throws GeneralSecurityException, MyProxyException, IOException,
GSSException {
if (myProxyPassphrase.length < GrixProperty
.getInt("myproxy.minimal.password.length")) {
throw new MyProxyException(
"Passphrase must be at least 6 characters long.");
}
GSSCredential gssCred = null;
gssCred = new GlobusGSSCredentialImpl(globusCred,
GSSCredential.INITIATE_AND_ACCEPT);
myLogger.debug("Created gss_credentials.");
InitParams initRequest = new InitParams();
initRequest.setUserName(username);
// this is the lifetime of credentials after a user downloads them
// TODO
initRequest.setLifetime(60 * 60 * credentials_lifetime_in_hours);
// TEST
// anonymous = true;
// initRequest.setLifetime(60);
// TODO what are the following things good for?
// initRequest.setCredentialDescription( "createdWithGrix" );
if (!"".equals(credential_name)) {
initRequest.setCredentialName(credential_name);
}
if (anonymous) {
initRequest.setRenewer("*");
initRequest.setRetriever("*");
// initRequest.setCredentialName("test");
} else {
// check if properties contain server, if not, set renewer/retriever
// accordingly. else server defaults are used.
if (!GrixProperty.getString("myproxy.default.renewer")
.toLowerCase().equals("server")) {
initRequest.setRenewer(GrixProperty
.getString("myproxy.default.renewer"));
}
if (!"server".equals(GrixProperty.getString(
"myproxy.default.retriever").toLowerCase())) {
initRequest.setRetriever(GrixProperty
.getString("myproxy.default.retriever"));
}
}
initRequest.setPassphrase(new String(myProxyPassphrase));
Arrays.fill(myProxyPassphrase, 'x');
MyProxy myProxy = new MyProxy(myProxyHost, myProxyPort);
myLogger.debug("Created myproxy.");
// myProxy.put( gssCred, myProxyUsername, new String(myProxyPassphrase),
// lifetime );
myProxy.put(gssCred, initRequest);
UserProperty.addToList("MYPROXY_USERNAMES", username);
myLogger.debug("Put myproxy credentials on server.");
// very important to dispose the long-live credential after storage!
gssCred.dispose();
myLogger.debug("Disposed gss_credentials.");
// MyProxyCred cred = new MyProxyCred(username, "DUMMY_DUMMY"
// .toCharArray());
// getInfo();
}
public boolean isLoaded() {
return isLoaded;
}
public void setCredentialName(String name) {
this.credential_name = name;
}
}