You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sm...@apache.org on 2006/11/07 06:06:57 UTC
svn commit: r471985 - in
/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth:
internal/kerberos/v5/ module/
Author: smishura
Date: Mon Nov 6 21:06:56 2006
New Revision: 471985
URL: http://svn.apache.org/viewvc?view=rev&rev=471985
Log:
Improve functionality: complete set of ASN.1 decoders for AS exchange protocol - now Krb5LoginModule can obtain tickets
Modified:
incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KDCReply.java
incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KrbClient.java
incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/Ticket.java
incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/module/Krb5LoginModule.java
Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KDCReply.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KDCReply.java?view=diff&rev=471985&r1=471984&r2=471985
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KDCReply.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KDCReply.java Mon Nov 6 21:06:56 2006
@@ -17,17 +17,25 @@
package org.apache.harmony.auth.internal.kerberos.v5;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.Date;
+
+import javax.crypto.SecretKey;
import org.apache.harmony.security.asn1.ASN1Any;
+import org.apache.harmony.security.asn1.ASN1BitString;
import org.apache.harmony.security.asn1.ASN1Constants;
import org.apache.harmony.security.asn1.ASN1Explicit;
import org.apache.harmony.security.asn1.ASN1Integer;
+import org.apache.harmony.security.asn1.ASN1OctetString;
import org.apache.harmony.security.asn1.ASN1Sequence;
import org.apache.harmony.security.asn1.ASN1SequenceOf;
import org.apache.harmony.security.asn1.ASN1StringType;
import org.apache.harmony.security.asn1.ASN1Type;
import org.apache.harmony.security.asn1.BerInputStream;
+import org.apache.harmony.security.asn1.BitString;
+import org.apache.harmony.security.asn1.DerInputStream;
/**
* @see http://www.ietf.org/rfc/rfc4120.txt
@@ -55,8 +63,28 @@
private final EncryptedData encPart;
- private KDCReply(int msgType, String crealm, PrincipalName cname, Ticket ticket,
- EncryptedData encPart) {
+ //
+ //
+ //
+ private Date authtime;
+
+ private Date starttime;
+
+ private Date endtime;
+
+ private Date renewtill;
+
+ private String srealm;
+
+ private PrincipalName sname;
+
+ // session key
+ private Object[] key;
+
+ private BitString flags;
+
+ private KDCReply(int msgType, String crealm, PrincipalName cname,
+ Ticket ticket, EncryptedData encPart) {
this.msgType = msgType;
this.cname = cname;
this.crealm = crealm;
@@ -64,6 +92,22 @@
this.encPart = encPart;
}
+ public void decrypt(SecretKey key) throws IOException {
+ DerInputStream in = new DerInputStream(new ByteArrayInputStream(encPart
+ .decrypt(key)));
+
+ Object[] values = (Object[]) ENC_AS_REP_PART.decode(in);
+
+ this.key = (Object[]) values[0];
+ flags = (BitString) values[4];
+ authtime = (Date) values[5];
+ starttime = (Date) values[6];
+ endtime = (Date) values[7];
+ renewtill = (Date) values[8];
+ srealm = (String) values[9];
+ sname = (PrincipalName) values[10];
+ }
+
public int getMsgtype() {
return msgType;
}
@@ -84,6 +128,42 @@
return encPart;
}
+ //
+ //
+ //
+
+ public Date getAuthtime() {
+ return authtime;
+ }
+
+ public Date getStarttime() {
+ return starttime;
+ }
+
+ public Date getEndtime() {
+ return endtime;
+ }
+
+ public Date getRenewtill() {
+ return renewtill;
+ }
+
+ public String getSrealm() {
+ return srealm;
+ }
+
+ public PrincipalName getSname() {
+ return sname;
+ }
+
+ public Object[] getKey() {
+ return key;
+ }
+
+ public BitString getFlags() {
+ return flags;
+ }
+
/**
* <pre>
* KDC-REP ::= SEQUENCE {
@@ -119,8 +199,9 @@
Object[] values = (Object[]) in.content;
- return new KDCReply(ASN1Integer.toIntValue(values[1]), (String) values[3],
- (PrincipalName) values[4], (Ticket) values[5], (EncryptedData) values[6]);
+ return new KDCReply(ASN1Integer.toIntValue(values[1]),
+ (String) values[3], (PrincipalName) values[4],
+ (Ticket) values[5], (EncryptedData) values[6]);
}
@Override
@@ -131,4 +212,55 @@
public static final ASN1Explicit AS_REP_ASN1 = new ASN1Explicit(
ASN1Constants.CLASS_APPLICATION, AS_REP, KDC_REP_ASN1);
+
+ private static final ASN1Sequence ENCRYPTION_KEY = new ASN1Sequence(
+ new ASN1Type[] {
+ // TODO should we define Int32 type?
+ new ASN1Explicit(0, ASN1Integer.getInstance()), // keytype
+ new ASN1Explicit(1, ASN1OctetString.getInstance()), // keyvalue
+ });
+
+ private static final ASN1SequenceOf LAST_REQ = new ASN1SequenceOf(
+ new ASN1Sequence(new ASN1Type[] {
+ // TODO should we define Int32 type?
+ new ASN1Explicit(0, ASN1Integer.getInstance()), // lr-type
+ new ASN1Explicit(1, KerberosTime.getASN1()), // lr-value
+ }));
+
+ private static final ASN1Sequence HOST_ADDRESS = new ASN1Sequence(
+ new ASN1Type[] {
+ // TODO should we define Int32 type?
+ new ASN1Explicit(0, ASN1Integer.getInstance()), // addr-type
+ new ASN1Explicit(1, ASN1OctetString.getInstance()), // address
+ });
+
+ private static final ASN1Sequence ENC_KDC_REP_PART = new ASN1Sequence(
+ new ASN1Type[] { new ASN1Explicit(0, ENCRYPTION_KEY), // key
+ new ASN1Explicit(1, LAST_REQ), // last-req
+ // TODO should we define UInt32 type?
+ new ASN1Explicit(2, ASN1Integer.getInstance()), // nonce
+ new ASN1Explicit(3, KerberosTime.getASN1()), // key-expiration
+ // TODO TicketFlags type?
+ new ASN1Explicit(4, ASN1BitString.getInstance()), // flags
+ new ASN1Explicit(5, KerberosTime.getASN1()), // authtime
+ new ASN1Explicit(6, KerberosTime.getASN1()), // starttime
+ new ASN1Explicit(7, KerberosTime.getASN1()), // endtime
+ new ASN1Explicit(8, KerberosTime.getASN1()), // renew-till
+ // TODO should we define Realm type?
+ new ASN1Explicit(9, ASN1StringType.GENERALSTRING), // srealm
+ new ASN1Explicit(10, PrincipalName.ASN1), // sname
+ new ASN1Explicit(11, HOST_ADDRESS), // caddr
+ }) {
+ {
+ setOptional(3); // key-expiration
+ setOptional(6); // starttime
+ setOptional(8); // renew-till
+ setOptional(11); // caddr
+ }
+ };
+
+ //TODO: create const ENC_AS_REP_PART=25
+ private static final ASN1Explicit ENC_AS_REP_PART = new ASN1Explicit(
+ ASN1Constants.CLASS_APPLICATION, 25, ENC_KDC_REP_PART);
+
}
Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KrbClient.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KrbClient.java?view=diff&rev=471985&r1=471984&r2=471985
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KrbClient.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/KrbClient.java Mon Nov 6 21:06:56 2006
@@ -23,6 +23,8 @@
import java.net.DatagramSocket;
import java.net.InetAddress;
+import javax.crypto.SecretKey;
+
import org.apache.harmony.auth.internal.nls.Messages;
import org.apache.harmony.security.asn1.DerInputStream;
@@ -46,10 +48,12 @@
* @param realm - client's realm
* @return - ticket
*/
- public static Ticket doAS(InetAddress address, int port, PrincipalName cname, String realm,
- PrincipalName sname) {
+ public static KDCReply doAS(InetAddress address, int port,
+ PrincipalName cname, String realm, PrincipalName sname,
+ SecretKey key) {
- KDCRequest request = new KDCRequest(KDCRequest.AS_REQ, cname, realm, sname);
+ KDCRequest request = new KDCRequest(KDCRequest.AS_REQ, cname, realm,
+ sname);
try {
DatagramSocket socket = request.send(address, port);
@@ -70,11 +74,16 @@
DerInputStream in = new DerInputStream(out.toByteArray());
if (in.tag == KDCReply.AS_REP_ASN1.constrId) { //TODO AS reply
- throw new RuntimeException();//FIXME
+ KDCReply reply = (KDCReply) KDCReply.AS_REP_ASN1.decode(in);
+
+ reply.decrypt(key);
+
+ return reply;
} else if (in.tag == KerberosErrorMessage.ASN1.constrId) {
KerberosErrorMessage errMsg = KerberosErrorMessage.decode(in);
// auth.52=Error code: {0}
- throw new RuntimeException(Messages.getString("auth.52", errMsg.getErrorCode())); //$NON-NLS-1$
+ throw new RuntimeException(Messages.getString(
+ "auth.52", errMsg.getErrorCode())); //$NON-NLS-1$
} else {
new RuntimeException(); //FIXME
}
Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/Ticket.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/Ticket.java?view=diff&rev=471985&r1=471984&r2=471985
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/Ticket.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/internal/kerberos/v5/Ticket.java Mon Nov 6 21:06:56 2006
@@ -37,6 +37,9 @@
private final String realm;
+ // ASN.1 encoding of this ticket
+ private byte[] encoded;
+
private Ticket(String realm, PrincipalName sname) {
this.sname = sname;
this.realm = realm;
@@ -50,6 +53,10 @@
return sname;
}
+ public byte[] getEncoded() {
+ return encoded;
+ }
+
/**
<pre>Ticket ::= [APPLICATION 1] SEQUENCE {
tkt-vno [0] INTEGER (5),
@@ -72,7 +79,11 @@
Object[] values = (Object[]) in.content;
- return new Ticket((String) values[1], (PrincipalName) values[2]);
+ Ticket ticket = new Ticket((String) values[1],
+ (PrincipalName) values[2]);
+ ticket.encoded = in.getEncoded();
+
+ return ticket;
}
@Override
Modified: incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/module/Krb5LoginModule.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/module/Krb5LoginModule.java?view=diff&rev=471985&r1=471984&r2=471985
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/module/Krb5LoginModule.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/auth/src/main/java/common/org/apache/harmony/auth/module/Krb5LoginModule.java Mon Nov 6 21:06:56 2006
@@ -21,13 +21,18 @@
import java.util.Map;
import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
+import org.apache.harmony.auth.internal.kerberos.v5.KDCReply;
import org.apache.harmony.auth.internal.kerberos.v5.KrbClient;
import org.apache.harmony.auth.internal.kerberos.v5.PrincipalName;
-import org.apache.harmony.auth.internal.kerberos.v5.Ticket;
public class Krb5LoginModule implements LoginModule {
@@ -40,8 +45,12 @@
// client's principal identifier name
private static final String PRINCIPAL = "principal";//$NON-NLS-1$
+ private Subject subject;
+
private Map<String, ?> options;
+ private CallbackHandler callbackHandler;
+
public boolean abort() throws LoginException {
// TODO
return false;
@@ -55,7 +64,9 @@
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
// TODO
+ this.subject = subject;
this.options = options;
+ this.callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
@@ -83,14 +94,69 @@
kdc = kdc.substring(0, pos);
}
- PrincipalName cname = new PrincipalName(PrincipalName.NT_UNKNOWN, new String[] { name });
+ PrincipalName cname = new PrincipalName(PrincipalName.NT_UNKNOWN,
+ new String[] { name });
- PrincipalName krbtgt = new PrincipalName(PrincipalName.NT_SRV_XHST, new String[] {
- "krbtgt", realm }); //$NON-NLS-1$
+ PrincipalName krbtgt = new PrincipalName(PrincipalName.NT_SRV_XHST,
+ new String[] { "krbtgt", realm }); //$NON-NLS-1$
try {
- Ticket ticket = KrbClient.doAS(InetAddress.getByName(kdc), port, cname, realm,
- krbtgt);
+ // get client's password
+ PasswordCallback callback = new PasswordCallback("Password for "
+ + name, false);
+ callbackHandler.handle(new Callback[] { callback });
+
+ KerberosKey key = new KerberosKey(new KerberosPrincipal(name + '@'
+ + realm, KerberosPrincipal.KRB_NT_UNKNOWN), callback
+ .getPassword(), "DES");
+
+ KDCReply reply = KrbClient.doAS(InetAddress.getByName(kdc), port,
+ cname, realm, krbtgt, key);
+
+ // add principal to subject
+ String[] pName = reply.getCname().getName();
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < pName.length - 1; i++) {
+ buf.append(pName[i]);
+ buf.append('/');
+ }
+ buf.append(pName[pName.length - 1]);
+ buf.append('@');
+ buf.append(reply.getCrealm());
+
+ KerberosPrincipal client = new KerberosPrincipal(buf.toString(),
+ reply.getCname().getType());
+ subject.getPrincipals().add(client);
+
+ // add ticket to private credentials
+ byte[] ticket = reply.getTicket().getEncoded();
+
+ String[] sName = reply.getSname().getName();
+ buf = new StringBuilder();
+ for (int i = 0; i < sName.length - 1; i++) {
+ buf.append(sName[i]);
+ buf.append('/');
+ }
+ buf.append(sName[sName.length - 1]);
+ buf.append('@');
+ buf.append(reply.getSrealm());
+
+ KerberosPrincipal server = new KerberosPrincipal(buf.toString(),
+ reply.getSname().getType());
+
+ int keyType = (int) ((byte[]) reply.getKey()[0])[0];
+ byte[] sessionKey = (byte[]) reply.getKey()[1];
+
+ boolean[] flags = reply.getFlags().toBooleanArray();
+
+ KerberosTicket krbTicket = new KerberosTicket(ticket, client,
+ server, sessionKey, keyType, flags, reply.getAuthtime(),
+ reply.getStarttime(), reply.getEndtime(), reply
+ .getRenewtill(),
+ //TODO InetAddress[] clientAddresses
+ null);
+
+ subject.getPrivateCredentials().add(krbTicket);
return true; //FIXME
} catch (Exception e) {