/** * Constructs a KeyImpl from a password. * * @param principal the principal from which to derive the salt * @param password the password that should be used to compute the key. * @param algorithm the name for the algorithm that this key wil be used for. This parameter may * be null in which case "DES" will be assumed. */ public KeyImpl(KerberosPrincipal principal, char[] password, String algorithm) { try { PrincipalName princ = new PrincipalName(principal.getName()); EncryptionKey key = new EncryptionKey(password, princ.getSalt(), algorithm); this.keyBytes = key.getBytes(); this.keyType = key.getEType(); } catch (KrbException e) { throw new IllegalArgumentException(e.getMessage()); } }
private Krb5InitCredential( Krb5NameElement name, byte[] asn1Encoding, KerberosPrincipal client, KerberosPrincipal server, byte[] sessionKey, int keyType, boolean[] flags, Date authTime, Date startTime, Date endTime, Date renewTill, InetAddress[] clientAddresses) throws GSSException { super( asn1Encoding, client, server, sessionKey, keyType, flags, authTime, startTime, endTime, renewTill, clientAddresses); this.name = name; try { // Cache this for later use by the sun.security.krb5 package. krb5Credentials = new Credentials( asn1Encoding, client.getName(), server.getName(), sessionKey, keyType, flags, authTime, startTime, endTime, renewTill, clientAddresses); } catch (KrbException e) { throw new GSSException(GSSException.NO_CRED, -1, e.getMessage()); } catch (IOException e) { throw new GSSException(GSSException.NO_CRED, -1, e.getMessage()); } }
private static KerberosTicket getTgt(int caller, Krb5NameElement name, int initLifetime) throws GSSException { String realm = null; final String clientPrincipal, tgsPrincipal = null; /* * Find the TGT for the realm that the client is in. If the client * name is not available, then use the default realm. */ if (name != null) { clientPrincipal = (name.getKrb5PrincipalName()).getName(); realm = (name.getKrb5PrincipalName()).getRealmAsString(); } else { clientPrincipal = null; try { Config config = Config.getInstance(); realm = config.getDefaultRealm(); } catch (KrbException e) { GSSException ge = new GSSException( GSSException.NO_CRED, -1, "Attempt to obtain INITIATE credentials failed!" + " (" + e.getMessage() + ")"); ge.initCause(e); throw ge; } } final AccessControlContext acc = AccessController.getContext(); try { final int realCaller = (caller == GSSUtil.CALLER_UNKNOWN) ? GSSUtil.CALLER_INITIATE : caller; return AccessController.doPrivileged( new PrivilegedExceptionAction<KerberosTicket>() { public KerberosTicket run() throws Exception { return Krb5Util.getTicket(realCaller, clientPrincipal, tgsPrincipal, acc); } }); } catch (PrivilegedActionException e) { GSSException ge = new GSSException( GSSException.NO_CRED, -1, "Attempt to obtain new INITIATE credentials failed!" + " (" + e.getMessage() + ")"); ge.initCause(e.getException()); throw ge; } }
/** Deletes an entry from the key table. */ void deleteEntry() { PrincipalName pname = null; try { pname = new PrincipalName(principal); if (pname.getRealm() == null) { pname.setRealm(Config.getInstance().getDefaultRealm()); } String answer; BufferedReader cis = new BufferedReader(new InputStreamReader(System.in)); System.out.print( "Are you sure you want to " + " delete service key for " + pname.toString() + " in " + table.tabName() + "?(Y/N) :"); System.out.flush(); answer = cis.readLine(); if (answer.equalsIgnoreCase("Y") || answer.equalsIgnoreCase("Yes")) ; else { // no error, the user did not want to delete the entry System.exit(0); } } catch (KrbException e) { System.err.println("Error occured while deleting the entry. " + "Deletion failed."); e.printStackTrace(); System.exit(-1); } catch (IOException e) { System.err.println("Error occured while deleting the entry. " + " Deletion failed."); e.printStackTrace(); System.exit(-1); } // admin.deleteEntry(pname); table.deleteEntry(pname); try { table.save(); } catch (IOException e) { System.err.println("Error occurs while saving the keytab." + "Deletion fails."); e.printStackTrace(); System.exit(-1); } System.out.println("Done!"); }
/** * Adds a service key to key table. If the specified key table does not exist, the program will * automatically generate a new key table. */ void addEntry() { PrincipalName pname = null; try { pname = new PrincipalName(principal); if (pname.getRealm() == null) { pname.setRealm(Config.getInstance().getDefaultRealm()); } } catch (KrbException e) { System.err.println("Failed to add " + principal + " to keytab."); e.printStackTrace(); System.exit(-1); } if (password == null) { try { BufferedReader cis = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Password for " + pname.toString() + ":"); System.out.flush(); password = new StringBuffer().append(cis.readLine()); } catch (IOException e) { System.err.println("Failed to read the password."); e.printStackTrace(); System.exit(-1); } } try { // admin.addEntry(pname, password); table.addEntry(pname, password); // admin.save(); table.save(); System.out.println("Done!"); System.out.println("Service key for " + principal + " is saved in " + table.tabName()); } catch (KrbCryptoException e) { System.err.println("Failed to add " + principal + " to keytab."); e.printStackTrace(); System.exit(-1); } catch (IOException e) { System.err.println("Failed to save new entry."); e.printStackTrace(); System.exit(-1); } }
void go() throws Exception { OneKDC k = new OneKDC(null); k.writeJAASConf(); Files.delete(Paths.get(OneKDC.KTAB)); // Starts with no keytab c = Context.fromJAAS("client"); s = Context.fromJAAS("com.sun.security.jgss.krb5.accept"); // Test 1: read new key 1 from keytab k.addPrincipal(OneKDC.SERVER, "pass1".toCharArray()); k.writeKtab(OneKDC.KTAB); connect(); // Test 2: service key cached, find 1 in keytab (now contains 1 and 2) k.addPrincipal(OneKDC.SERVER, "pass2".toCharArray()); k.appendKtab(OneKDC.KTAB); connect(); // Test 3: re-login. Now find 2 in keytab c = Context.fromJAAS("client"); connect(); // Test 4: re-login, KDC use 3 this time. c = Context.fromJAAS("client"); // Put 3 and 4 into keytab but keep the real key back to 3. k.addPrincipal(OneKDC.SERVER, "pass3".toCharArray()); k.appendKtab(OneKDC.KTAB); k.addPrincipal(OneKDC.SERVER, "pass4".toCharArray()); k.appendKtab(OneKDC.KTAB); k.addPrincipal(OneKDC.SERVER, "pass3".toCharArray()); connect(); // Test 5: invalid keytab file, should ignore try (FileOutputStream fos = new FileOutputStream(OneKDC.KTAB)) { fos.write("BADBADBAD".getBytes()); } connect(); // Test 6: delete keytab file, identical to revoke all Files.delete(Paths.get(OneKDC.KTAB)); try { connect(); throw new Exception("Should not success"); } catch (GSSException gsse) { System.out.println(gsse); KrbException ke = (KrbException) gsse.getCause(); // KrbApReq.authenticate(*) if (dkey == null)... // This should have been Krb5.KRB_AP_ERR_NOKEY if (ke.returnCode() != Krb5.API_INVALID_ARG) { throw new Exception("Not expected failure code: " + ke.returnCode()); } } // Test 7: 3 revoked, should fail (now contains only 5) k.addPrincipal(OneKDC.SERVER, "pass5".toCharArray()); k.writeKtab(OneKDC.KTAB); // overwrite keytab, which means // old key is revoked try { connect(); throw new Exception("Should not success"); } catch (GSSException gsse) { System.out.println(gsse); // Since 7197159, different kvno is accepted, this return code // will never be thrown out again. // KrbException ke = (KrbException)gsse.getCause(); // if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) { // throw new Exception("Not expected failure code: " + // ke.returnCode()); // } } // Test 8: an empty KDC means revoke all KDC.create("EMPTY.REALM").writeKtab(OneKDC.KTAB); try { connect(); throw new Exception("Should not success"); } catch (GSSException gsse) { System.out.println(gsse); KrbException ke = (KrbException) gsse.getCause(); // KrbApReq.authenticate(*) if (dkey == null)... // This should have been Krb5.KRB_AP_ERR_NOKEY if (ke.returnCode() != Krb5.API_INVALID_ARG) { throw new Exception("Not expected failure code: " + ke.returnCode()); } } }