Browse Source

GSSAPI in prep for SPNEGO

Jonathan Turner 9 years ago
parent
commit
934025f597
4 changed files with 182 additions and 4 deletions
  1. 34 0
      GSSAPI/ContextFlags.go
  2. 15 0
      GSSAPI/MechType.go
  3. 125 0
      GSSAPI/NegotiationToken.go
  4. 8 4
      README.md

+ 34 - 0
GSSAPI/ContextFlags.go

@@ -0,0 +1,34 @@
+package GSSAPI
+
+import "github.com/jcmturner/asn1"
+
+/*
+ContextFlags ::= BIT STRING {
+  delegFlag       (0),
+  mutualFlag      (1),
+  replayFlag      (2),
+  sequenceFlag    (3),
+  anonFlag        (4),
+  confFlag        (5),
+  integFlag       (6)
+} (SIZE (32))
+*/
+
+const (
+	delegFlag    = 0
+	mutualFlag   = 1
+	replayFlag   = 2
+	sequenceFlag = 3
+	anonFlag     = 4
+	confFlag     = 5
+	integFlag    = 6
+)
+
+type ContextFlags asn1.BitString
+
+func NewContextFlags() ContextFlags {
+	var c ContextFlags
+	c.BitLength = 32
+	c.Bytes = make([]byte, 4)
+	return c
+}

+ 15 - 0
GSSAPI/MechType.go

@@ -0,0 +1,15 @@
+package GSSAPI
+
+import (
+	"github.com/jcmturner/asn1"
+)
+
+const (
+	SPNEGO_OIDHex                = "2b0601050502"       //1.3.6.1.5.5.2
+	MechType_Krb5_OIDHex         = "2a864886f712010202" //1.2.840.113554.1.2.2
+	MechType_MSLegacyKrb5_OIDHex = "2a864882f712010202" //1.2.840.48018.1.2.2
+)
+
+type MechType asn1.ObjectIdentifier
+
+type MechTypeList []MechType

+ 125 - 0
GSSAPI/NegotiationToken.go

@@ -0,0 +1,125 @@
+package GSSAPI
+
+import (
+	"errors"
+	"fmt"
+	"github.com/jcmturner/asn1"
+)
+
+/*
+https://msdn.microsoft.com/en-us/library/ms995330.aspx
+
+NegotiationToken ::= CHOICE {
+  negTokenInit    [0] NegTokenInit,  This is the Negotiation token sent from the client to the server.
+  negTokenResp    [1] NegTokenResp
+}
+
+NegTokenInit ::= SEQUENCE {
+  mechTypes       [0] MechTypeList,
+  reqFlags        [1] ContextFlags  OPTIONAL,
+  -- inherited from RFC 2478 for backward compatibility,
+  -- RECOMMENDED to be left out
+  mechToken       [2] OCTET STRING  OPTIONAL,
+  mechListMIC     [3] OCTET STRING  OPTIONAL,
+  ...
+}
+
+NegTokenResp ::= SEQUENCE {
+  negState       [0] ENUMERATED {
+    accept-completed    (0),
+    accept-incomplete   (1),
+    reject              (2),
+    request-mic         (3)
+  }                                 OPTIONAL,
+  -- REQUIRED in the first reply from the target
+  supportedMech   [1] MechType      OPTIONAL,
+  -- present only in the first reply from the target
+  responseToken   [2] OCTET STRING  OPTIONAL,
+  mechListMIC     [3] OCTET STRING  OPTIONAL,
+  ...
+}
+*/
+
+// Tag attribute of NegotiationToken will indicate type:
+// 0xa0 (160) - negTokenInit
+// 0xa1 (161) - negTokenResp
+type NegotiationToken asn1.RawValue
+
+type NegTokenInit struct {
+	MechTypes    MechTypeList `asn1:"explicit,tag:0"`
+	ReqFlags     ContextFlags `asn1:"explicit,optional,tag:1"`
+	MechToken    []byte       `asn1:"explicit,optional,tag:2"`
+	MechTokenMIC []byte       `asn1:"explicit,optional,tag:3"`
+}
+
+type NegTokenResp struct {
+	NegState      asn1.Enumerated `asn1:"explicit,optional,tag:0"`
+	SupportedMech MechType        `asn1:"explicit,optional,tag:1"`
+	ResponseToken []byte          `asn1:"explicit,optional,tag:2"`
+	MechListMIC   []byte          `asn1:"explicit,optional,tag:3"`
+}
+
+// Unmarshal and return either a NegTokenInit or a NegTokenResp.
+//
+// The boolean indicates if the reponse is a NegTokenInit.
+// If error is nil and the boolean is false the response is a NegTokenResp.
+func (n *NegotiationToken) Unmarshal(b []byte) (bool, interface{}, error) {
+	_, err := asn1.Unmarshal(b, n)
+	if err != nil {
+		return false, nil, fmt.Errorf("Error unmarshalling NegotiationToken: %v", err)
+	}
+	var negToken interface{}
+	var isInit bool
+	switch n.Tag {
+	case 0:
+		negToken = &NegTokenInit{}
+		isInit = true
+	case 1:
+		negToken = &NegTokenResp{}
+	default:
+		return false, nil, errors.New("Unknown choice type for NegotiationToken")
+	}
+	_, err = asn1.Unmarshal(n.Bytes, negToken)
+	if err != nil {
+		return nil, fmt.Errorf("Error unmarshalling NegotiationToken type %d: %v", n.Tag, err)
+	}
+	return isInit, negToken, nil
+}
+
+// Returns marshalled bytes of a NegotiationToken rather than the NegTokenInit
+func (n *NegTokenInit) Marshal() ([]byte, error) {
+	b, err := asn1.Marshal(*n)
+	if err != nil {
+		return nil, err
+	}
+	nt := NegotiationToken{
+		Tag:        0,
+		Class:      2,
+		IsCompound: true,
+		Bytes:      b,
+	}
+	nb, err := asn1.Marshal(nt)
+	if err != nil {
+		return nil, err
+	}
+	return nb, nil
+}
+
+// Returns marshalled bytes of a NegotiationToken rather than the NegTokenResp
+func (n *NegTokenResp) Marshal() ([]byte, error) {
+	b, err := asn1.Marshal(*n)
+	if err != nil {
+		return nil, err
+	}
+	nt := NegotiationToken{
+		Tag:        1,
+		Class:      2,
+		IsCompound: true,
+		Bytes:      b,
+	}
+	nb, err := asn1.Marshal(nt)
+	if err != nil {
+		return nil, err
+	}
+	return nb, nil
+}

+ 8 - 4
README.md

@@ -66,10 +66,14 @@ tkt, err := cl.GetServiceTicket("HTTP/host.test.gokrb5")
 [text](https://www.ietf.org/rfc/rfc3961.txt) [html](https://tools.ietf.org/html/rfc3961)
 * RFC 3962 Advanced Encryption Standard (AES) Encryption for Kerberos 5
 [text](https://www.ietf.org/rfc/rfc3962.txt) [html](https://tools.ietf.org/html/rfc3962)
-* The Simple and Protected Generic Security Service Application Program Interface (GSS-API) Negotiation Mechanism [text](https://www.ietf.org/rfc/rfc4178.txt) [html](https://tools.ietf.org/html/rfc4178.html)
-* SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows [text](https://www.ietf.org/rfc/rfc4559.txt) [html](https://tools.ietf.org/html/rfc4559.html)
-* RFC 6806 Kerberos Principal Name Canonicalization and Cross-Realm Referrals [text](https://www.ietf.org/rfc/rfc6806.txt) [html](https://tools.ietf.org/html/rfc6806.html)
-* RFC 6113 A Generalized Framework for Kerberos Pre-Authentication [text](https://www.ietf.org/rfc/rfc6113.txt) [html](https://tools.ietf.org/html/rfc6113.html)
+* RFC 4178 The Simple and Protected Generic Security Service Application Program Interface (GSS-API) Negotiation Mechanism
+[text](https://www.ietf.org/rfc/rfc4178.txt) [html](https://tools.ietf.org/html/rfc4178.html)
+* RFC 4559 SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows
+[text](https://www.ietf.org/rfc/rfc4559.txt) [html](https://tools.ietf.org/html/rfc4559.html)
+* RFC 6806 Kerberos Principal Name Canonicalization and Cross-Realm Referrals
+[text](https://www.ietf.org/rfc/rfc6806.txt) [html](https://tools.ietf.org/html/rfc6806.html)
+* RFC 6113 A Generalized Framework for Kerberos Pre-Authentication
+[text](https://www.ietf.org/rfc/rfc6113.txt) [html](https://tools.ietf.org/html/rfc6113.html)
 * [IANA Assigned Kerberos Numbers](http://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml)
 * [Microsoft PAC Validation](https://blogs.msdn.microsoft.com/openspecification/2009/04/24/understanding-microsoft-kerberos-pac-validation/)
 * [Microsoft Kerberos Protocol Extensions](https://msdn.microsoft.com/en-us/library/cc233855.aspx)