[ 
https://issues.apache.org/jira/browse/HADOOP-14146?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15900989#comment-15900989
 ] 

Kai Zheng commented on HADOOP-14146:
------------------------------------

Hi [~daryn],

Pretty smart and impressive the way you thought of this approach and 
implemented it. It looks overall good to me.

One question, maybe we could avoid maintaining the DER parser codes like 
follows by leveraging the ASN1 and Kerberos library in Apache Kerby? Kerby 
should be good at such stuffs and the current MiniKDC uses it.
{code}
+  /**
+   * Extract the TGS server principal from the given gssapi kerberos or spnego
+   * wrapped token.
+   * @param rawToken bytes of the gss token
+   * @return String of server principal
+   * @throws IllegalArgumentException if token is undecodable
+   */
+  public static String getTokenServerName(byte[] rawToken) {
+    // subsequent comments include only relevant portions of the kerberos
+    // DER encoding that will be extracted.
+    DER token = new DER(rawToken);//.get(0x60);
+    // InitialContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+    //     mech   OID
+    //     mech-token  (NegotiationToken or InnerContextToken)
+    // }
+    DER oid = token.next();
+    if (oid.equals(DER.SPNEGO_MECH_OID)) {
+      // NegotiationToken ::= CHOICE {
+      //     neg-token-init[0] NegTokenInit
+      // }
+      // NegTokenInit ::= SEQUENCE {
+      //     mech-token[2]     InitialContextToken
+      // }
+      token = token.next().get(0xa0, 0x30, 0xa2, 0x04).next();
+      oid = token.next();
+    }
+    if (!oid.equals(DER.KRB5_MECH_OID)) {
+      throw new IllegalArgumentException("Malformed gss token");
+    }
+    // InnerContextToken ::= {
+    //     token-id[1]
+    //     AP-REQ
+    // }
+    if (token.next().getTag() != 1) {
+      throw new IllegalArgumentException("Not an AP-REQ token");
+    }
+    // AP-REQ ::= [APPLICATION 14] SEQUENCE {
+    //     ticket[3]      Ticket
+    // }
+    DER ticket = token.next().get(0x6e, 0x30, 0xa3, 0x61, 0x30);
+    // Ticket ::= [APPLICATION 1] SEQUENCE {
+    //     realm[1]       String
+    //     sname[2]       PrincipalName
+    // }
+    // PrincipalName ::= SEQUENCE {
+    //     name-string[1] SEQUENCE OF String
+    // }
+    String realm = ticket.get(0xa1, 0x1b).getAsString();
+    DER names = ticket.get(0xa2, 0x30, 0xa1, 0x30);
+    StringBuilder sb = new StringBuilder();
+    while (names.hasNext()) {
+      if (sb.length() > 0) {
+        sb.append('/');
+      }
+      sb.append(names.next().getAsString());
+    }
+    return sb.append('@').append(realm).toString();
+  }
{code}

A comparable sample in Kerby's code base is [this 
test|https://github.com/apache/directory-kerby/blob/5b378597485b4d81c337b1996791c1009f759067/kerby-kerb/kerb-core/src/test/java/org/apache/kerby/kerberos/kerb/codec/AsReqCodecTest.java],
 though it parses AS-REQ (but similar to AP-REQ).

{code}
public class AsReqCodecTest {

    @Test
    public void test() throws IOException, ParseException {
        byte[] bytes = CodecTestUtil.readBinaryFile("/asreq.token");
        Asn1.decodeAndDump(bytes);
        ByteBuffer asReqToken = ByteBuffer.wrap(bytes);

        AsReq asReq = new AsReq();
        asReq.decode(asReqToken);
        Asn1.dump(asReq);

        assertThat(asReq.getPvno()).isEqualTo(5);
        assertThat(asReq.getMsgType()).isEqualTo(KrbMessageType.AS_REQ);

        PaData paData = asReq.getPaData();
        PaDataEntry encTimestampEntry = 
paData.findEntry(PaDataType.ENC_TIMESTAMP);
        
assertThat(encTimestampEntry.getPaDataType()).isEqualTo(PaDataType.ENC_TIMESTAMP);
        
assertThat(encTimestampEntry.getPaDataValue()).isEqualTo(Arrays.copyOfRange(bytes,
 33, 96));
        PaDataEntry pacRequestEntry = paData.findEntry(PaDataType.PAC_REQUEST);
        
assertThat(pacRequestEntry.getPaDataType()).isEqualTo(PaDataType.PAC_REQUEST);
        
assertThat(pacRequestEntry.getPaDataValue()).isEqualTo(Arrays.copyOfRange(bytes,
 108, 115));
...
{code}

Please let me know if it doesn't work and I can definitely help.

> KerberosAuthenticationHandler should authenticate with SPN in AP-REQ
> --------------------------------------------------------------------
>
>                 Key: HADOOP-14146
>                 URL: https://issues.apache.org/jira/browse/HADOOP-14146
>             Project: Hadoop Common
>          Issue Type: Bug
>          Components: security
>    Affects Versions: 2.5.0
>            Reporter: Daryn Sharp
>            Assignee: Daryn Sharp
>         Attachments: HADOOP-14146.1.patch, HADOOP-14146.patch
>
>
> Many attempts (HADOOP-10158, HADOOP-11628, HADOOP-13565) have tried to add 
> multiple SPN host and/or realm support to spnego authentication.  The basic 
> problem is the server tries to guess and/or brute force what SPN the client 
> used.  The server should just decode the SPN from the AP-REQ.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

---------------------------------------------------------------------
To unsubscribe, e-mail: common-issues-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-issues-h...@hadoop.apache.org

Reply via email to