import java.io.*; import java.text.*; import java.util.*; import sun.misc.*; import java.security.*; import java.security.spec.*; import java.security.interfaces.*; import java.security.cert.*; /** * @author Tore Halset */ public class SSOclient { protected Hashtable loginvalues; /** A String containing the local path to the public key */ protected String crtfile = "/etc/innsida.crt"; protected boolean verifies; protected boolean oktime; protected boolean okipnumber; protected boolean oktarget; protected boolean checkipnumper; // true if we should check clientip /** A String containing the reasen why the authentication failed */ protected String reason; /** * @param data A comma-seperated String containg key-value pairs * @param sign64 A base64-encoded String containing a SHA1withRSA * digital signature of data. * @param clientip A String containing the ip-number of the client * @param target A String containing the target. This is a constant * value spesific the application. */ public SSOclient(String data, String sign64, String clientip, String target){ // set initial values loginvalues = new Hashtable(); verifies = false; oktime = false; okipnumber = false; oktarget = false; checkipnumper = true; // the default is to check for persistant ip number reason = ""; // initial argumentcheck if ((data == null) || (sign64 == null)){ reason = "missing logindata"; return; } // parse the data-field try { StringTokenizer st = new StringTokenizer(data, ","); while (st.hasMoreTokens()) { loginvalues.put(st.nextToken(), st.nextToken()); } } catch (Exception e) { reason = "not correct data-argument"; return; } // check the timestamp int tdif = Integer.parseInt((String)loginvalues.get("time")) - (int)(System.currentTimeMillis() / 1000); if((tdif > -10) && (tdif < 10)){ oktime = true; } else { reason = "to old timestamp"; return; } // check the target if (target.compareTo((String)loginvalues.get("target")) != 0){ reason = "wrong target (" + ((String)loginvalues.get("target")) + " != " + target + ")"; return; } else { oktarget = true; } // check the ip-number. if ((clientip != null) && (clientip.compareTo((String)loginvalues.get("remoteaddr")) != 0)){ reason = "wrong ip-number (" + ((String)loginvalues.get("remoteaddr")) + " != " + clientip + ")"; return; } else { okipnumber = true; } // base64-decode the sig try { byte sign[]; BASE64Decoder base64 = new BASE64Decoder(); sign = base64.decodeBuffer(sign64); // get the public key FileInputStream fis = new FileInputStream(crtfile); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate)cf.generateCertificate(fis); fis.close(); PublicKey pubk = cert.getPublicKey(); // verify the sig Signature dsa = Signature.getInstance("SHA1withRSA"); dsa.initVerify(pubk); dsa.update(data.getBytes()); verifies = dsa.verify(sign); } catch (Exception e) { reason = "could not verify signature (" + e.toString() + ")"; } } /** * @param newCheckipnumper A boolean value that is true if we should check the * ip-number of the client */ public void setcheckipnumper(boolean newCheckipnumper){ checkipnumper = newCheckipnumper; } /** * @return true if we should check for the ip-number of the client */ public boolean getCheckipnumper(){ return checkipnumper; } /** * @return Returns true if the login is ok. */ public boolean oklogin(){ boolean okip; if(getCheckipnumper()){ okip = okipnumber(); } else { okip = true; } if((loginvalues() != null) && okip && oktarget() && oktime() && verifies()) return true; else return false; } /** * @return Returns a hashtable containg the information from * this login. */ public Hashtable loginvalues(){ return loginvalues; } /** * @return true if the value of time is ok */ public boolean oktime(){ return oktime; } /** * @return true if the signature is correct */ public boolean verifies(){ return verifies; } /** * @return true if the ip-number is ok */ public boolean okipnumber(){ return okipnumber; } /** * return true if the target is ok */ public boolean oktarget(){ return oktarget; } /** * return the errormessage. only for debugging. */ public String reason(){ return reason; } } // class SSOclient