package mit.login;

import krb4.lib.*;
import krb4.lib.crypto.*;
import java.io.*;
import java.net.*;
/**
 * Simple Class with two static methods. Used to Verify if a given Kerberos
 * Username and password are correct. Note: This class is hardwired for MIT
 * Other sites will need to change appropriate constants.
 * 
 * <P>Also Note: An encryption key is included in this class, so it's source
 * and class file must be kept confidential. Code Obsfucators may help but
 * are not a substitute for protecting this implementation. Future versions
 * may store the encryption key in a file which can be separately protected
 * (which is how it should be done!)
 *
 */
public class KVerify {
  private static byte vkey[] = null;
  /**
   * private Constructor to prevent instantiation
   */
  private KVerify() {};
  /**
   * Returns <b>true</b> if username, password are correct, false
   * otherwise.
   *
   * @param user Kerberos Name of user to verify
   * @param instance Kerberos instance portion of name
   * @param password User's password
   * @return <b>true</b> on success <b>false</b> on bad user or password
   * @exception UnknownHostException if kerberos.mit.edu cannot be found
   * @exception IOException if kerberos.mit.edu cannot be reached
   * @exception KVerifyException if cert configfile has a problem
   */
  public static boolean verify (String user, String instance, String password) throws UnknownHostException, KVerifyException, IOException  {
    try {
      byte [] ukey = des.string_to_key_bytes(password);
      byte [] key = getVerificationKey();
      String kdc = Config.getProperty("mit.cert.kdc", "");
      String realm = Config.getProperty("mit.cert.realm", "");
      String sname = Config.getProperty("mit.cert.veriName", "");
      String sinst = Config.getProperty("mit.cert.veriInstance", "");
      Krb4ASReq as_req = new Krb4ASReq(user, instance, realm, realm);
      as_req.send(kdc);
      Krb4ASRep as_rep = as_req.getKrb4ASRep();
      Krb4Creds initial_creds = as_rep.getCreds(ukey);
      Krb4TGSReq tgs_req = new Krb4TGSReq(initial_creds, user, instance,
					  realm, sname, sinst, realm);
      tgs_req.send(kdc);
      Krb4TGSRep tgs_rep = tgs_req.getKrb4TGSRep();
      Krb4Creds creds = tgs_rep.getCreds(initial_creds);
      
      Krb4APReq ap_req = new Krb4APReq(creds, user, instance, realm, false);
      ap_req.authenticate(key, sname, sinst, realm, null);
    } catch (Krb4Exception e) {
      return (false);
    }
    return (true);
  }
  /**
   * Fetches the key needed to verify a user's Kerberos password
   *
   * @return The DES key as a byte array
   */
  private static byte [] getVerificationKey() throws KVerifyException {
    if (vkey != null) return vkey;
    String keyfile = Config.getProperty("mit.cert.verikeyfile", "");
    try {
      FileInputStream input = new FileInputStream(keyfile);
      vkey = new byte[input.available()];
      input.read(vkey);
      input.close();
      return (vkey);
    } catch (FileNotFoundException e) {
      vkey = null;
      throw new KVerifyException("Unable to find DES key file " + keyfile);
    } catch (IOException e) {
      vkey = null;
      throw new KVerifyException("Unable to read DES key file " + keyfile);
    }
  }
    
  /**
   * Returns <b>true</b> if the specified user has an "extra" instance.
   * false otherwise. Note: Will return false if the user is itself
   * unknown.
   *
   * @param user Kerberos user name to check
   * @return <b>true</b> if extra instance available
   * @expection IOException if problems communicating with the network
   */
  public static boolean hasExtra(String user) throws IOException {
    try {
      Krb4ASReq as_req = new Krb4ASReq(user, "extra", "ATHENA.MIT.EDU", "ATHENA.MIT.EDU");
      String kdc = "kerberos.mit.edu";
      as_req.send(kdc);
      Krb4ASRep as_rep = as_req.getKrb4ASRep();
      return (true);
    } catch (Krb4Exception k) {
      return (false);
    }
  }
}
