Explorar el Código

client spnego working

Jonathan Turner hace 9 años
padre
commit
d91ab76148
Se han modificado 6 ficheros con 40 adiciones y 9 borrados
  1. 12 3
      GSSAPI/krb5Token.go
  2. 14 1
      README.md
  3. 1 1
      debug.go
  4. 11 3
      messages/APReq.go
  5. 1 1
      testdata/test_vectors.go
  6. 1 0
      testenv/krbhttp-vagrant/bootstrap.sh

+ 12 - 3
GSSAPI/krb5Token.go

@@ -7,6 +7,7 @@ import (
 	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/asn1tools"
 	"github.com/jcmturner/gokrb5/asn1tools"
 	"github.com/jcmturner/gokrb5/config"
 	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/crypto"
 	"github.com/jcmturner/gokrb5/iana/chksumtype"
 	"github.com/jcmturner/gokrb5/iana/chksumtype"
 	"github.com/jcmturner/gokrb5/messages"
 	"github.com/jcmturner/gokrb5/messages"
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/jcmturner/gokrb5/types"
@@ -35,7 +36,7 @@ func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt types
 	APReq, err := messages.NewAPReq(
 	APReq, err := messages.NewAPReq(
 		tkt,
 		tkt,
 		sessionKey,
 		sessionKey,
-		newAuthenticator(c, cname),
+		newAuthenticator(c, cname, sessionKey.KeyType),
 	)
 	)
 	tb, err = APReq.Marshal()
 	tb, err = APReq.Marshal()
 	if err != nil {
 	if err != nil {
@@ -45,14 +46,22 @@ func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt types
 	return asn1tools.AddASNAppTag(b, 0), nil
 	return asn1tools.AddASNAppTag(b, 0), nil
 }
 }
 
 
-func newAuthenticator(c config.Config, username types.PrincipalName) types.Authenticator {
+func newAuthenticator(c config.Config, username types.PrincipalName, keyType int) types.Authenticator {
 	//RFC 4121 Section 4.1.1
 	//RFC 4121 Section 4.1.1
 	auth := types.NewAuthenticator(c.LibDefaults.Default_realm, username)
 	auth := types.NewAuthenticator(c.LibDefaults.Default_realm, username)
 	auth.Cksum = types.Checksum{
 	auth.Cksum = types.Checksum{
 		CksumType: chksumtype.GSSAPI,
 		CksumType: chksumtype.GSSAPI,
 		Checksum:  newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),
 		Checksum:  newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),
 	}
 	}
-	auth.SeqNumber = int(rand.Int63())
+	auth.SeqNumber = int(rand.Int31())
+	//Generate subkey value
+	etype, _ := crypto.GetEtype(keyType)
+	sk := make([]byte, etype.GetKeyByteSize())
+	rand.Read(sk)
+	auth.SubKey = types.EncryptionKey{
+		KeyType:  keyType,
+		KeyValue: sk,
+	}
 	return auth
 	return auth
 }
 }
 
 

+ 14 - 1
README.md

@@ -1,6 +1,10 @@
 # gokrb5
 # gokrb5
 
 
-This is work in progress and does not yet fully work...
+This is work in progress and may have some issues.
+
+Currently the following is working/tested:
+* Works with a KDC that supports [PA FAST](https://tools.ietf.org/html/rfc6806.html#section-11)
+* Client side authentication to HTTP servers that implement SPNEGO using Kerberos 5
 
 
 [![GoDoc](https://godoc.org/github.com/jcmturner/gokrb5?status.svg)](https://godoc.org/github.com/jcmturner/gokrb5)
 [![GoDoc](https://godoc.org/github.com/jcmturner/gokrb5?status.svg)](https://godoc.org/github.com/jcmturner/gokrb5)
 
 
@@ -51,12 +55,21 @@ err := cl.Login
 ```go
 ```go
 cl.EnableAutoSessionRenewal()
 cl.EnableAutoSessionRenewal()
 ```
 ```
+#### Authenticate to a Service
+##### Native Kerberos
 Request a Serivce ticket for a Service Principal Name (SPN).
 Request a Serivce ticket for a Service Principal Name (SPN).
 This method will use the client's cache either returning a valid cached ticket, renewing a cached ticket with the KDC or requesting a new ticket from the KDC.
 This method will use the client's cache either returning a valid cached ticket, renewing a cached ticket with the KDC or requesting a new ticket from the KDC.
 Therefore the GetServiceTicket method can be continually used for the most efficient interaction with the KDC.
 Therefore the GetServiceTicket method can be continually used for the most efficient interaction with the KDC.
 ```go
 ```go
 tkt, err := cl.GetServiceTicket("HTTP/host.test.gokrb5")
 tkt, err := cl.GetServiceTicket("HTTP/host.test.gokrb5")
 ```
 ```
+##### HTTP SPNEGO
+Create the HTTP request object and then call the client's SetSPNEGOHeader method passing the Service Principal Name (SPN)
+```go
+r, _ := http.NewRequest("GET", "http://host.test.gokrb5/index.html", nil)
+cl.SetSPNEGOHeader(r, "HTTP/host.test.gokrb5")
+HTTPResp, err := http.DefaultClient.Do(r)
+```
 
 
 ## References
 ## References
 ### RFCs
 ### RFCs

+ 1 - 1
debug.go

@@ -72,7 +72,7 @@ func httpRequest() {
 	if err != nil {
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Error on AS_REQ: %v\n", err)
 		fmt.Fprintf(os.Stderr, "Error on AS_REQ: %v\n", err)
 	}
 	}
-	r, _ := http.NewRequest("GET", "http://10.80.88.90/index.html", nil)
+	r, _ := http.NewRequest("GET", "http://host.test.gokrb5/index.html", nil)
 	cl.SetSPNEGOHeader(r, "HTTP/host.test.gokrb5")
 	cl.SetSPNEGOHeader(r, "HTTP/host.test.gokrb5")
 	httpResp, err := http.DefaultClient.Do(r)
 	httpResp, err := http.DefaultClient.Do(r)
 	fmt.Fprintf(os.Stderr, "RESPONSE CODE: %v\n", httpResp.StatusCode)
 	fmt.Fprintf(os.Stderr, "RESPONSE CODE: %v\n", httpResp.StatusCode)

+ 11 - 3
messages/APReq.go

@@ -10,6 +10,7 @@ import (
 	"github.com/jcmturner/gokrb5/iana/asnAppTag"
 	"github.com/jcmturner/gokrb5/iana/asnAppTag"
 	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/iana/msgtype"
 	"github.com/jcmturner/gokrb5/iana/msgtype"
+	"github.com/jcmturner/gokrb5/iana/nametype"
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/jcmturner/gokrb5/types"
 )
 )
 
 
@@ -47,7 +48,7 @@ type APReq struct {
 // Generate a new KRB_AP_REQ struct.
 // Generate a new KRB_AP_REQ struct.
 func NewAPReq(tkt types.Ticket, sessionKey types.EncryptionKey, auth types.Authenticator) (APReq, error) {
 func NewAPReq(tkt types.Ticket, sessionKey types.EncryptionKey, auth types.Authenticator) (APReq, error) {
 	var a APReq
 	var a APReq
-	ed, err := encryptAuthenticator(auth, sessionKey)
+	ed, err := encryptAuthenticator(auth, sessionKey, tkt)
 	if err != nil {
 	if err != nil {
 		return a, fmt.Errorf("Error creating authenticator for AP_REQ: %v", err)
 		return a, fmt.Errorf("Error creating authenticator for AP_REQ: %v", err)
 	}
 	}
@@ -62,13 +63,20 @@ func NewAPReq(tkt types.Ticket, sessionKey types.EncryptionKey, auth types.Authe
 }
 }
 
 
 // Encrypt Authenticator
 // Encrypt Authenticator
-func encryptAuthenticator(a types.Authenticator, sessionKey types.EncryptionKey) (types.EncryptedData, error) {
+func encryptAuthenticator(a types.Authenticator, sessionKey types.EncryptionKey, tkt types.Ticket) (types.EncryptedData, error) {
 	var ed types.EncryptedData
 	var ed types.EncryptedData
 	m, err := a.Marshal()
 	m, err := a.Marshal()
 	if err != nil {
 	if err != nil {
 		return ed, fmt.Errorf("Error marshalling authenticator: %v", err)
 		return ed, fmt.Errorf("Error marshalling authenticator: %v", err)
 	}
 	}
-	return crypto.GetEncryptedData(m, sessionKey, keyusage.TGS_REQ_PA_TGS_REQ_AP_REQ_AUTHENTICATOR, 0)
+	var usage int
+	switch tkt.SName.NameType {
+	case nametype.KRB_NT_PRINCIPAL:
+		usage = keyusage.AP_REQ_AUTHENTICATOR
+	case nametype.KRB_NT_SRV_INST:
+		usage = keyusage.TGS_REQ_PA_TGS_REQ_AP_REQ_AUTHENTICATOR
+	}
+	return crypto.GetEncryptedData(m, sessionKey, uint32(usage), tkt.EncPart.KVNO)
 }
 }
 
 
 // Unmarshal bytes b into the APReq struct.
 // Unmarshal bytes b into the APReq struct.

+ 1 - 1
testdata/test_vectors.go

@@ -98,7 +98,7 @@ var TestVectors = map[string]string{
 }
 }
 
 
 const (
 const (
-	TESTUSER1_KEYTAB = "05020000004b0001000b544553542e474f4b52423500097465737475736572310000000158e14ba20200120020ece15fc2116941977fab023c6fb784933ff1c80d3a71f5d742e169273a3585c5000000020000003b0001000b544553542e474f4b52423500097465737475736572310000000158e14ba202001100106fd4e428fdf2f54f03866c94b6d34d8900000002000000430001000b544553542e474f4b52423500097465737475736572310000000158e14ba202001000189408ef92262634badc25089ef2e0047fcb463425c18f2f20000000020000003b0001000b544553542e474f4b52423500097465737475736572310000000158e14ba202001700109d890eb35d54e48ff29e3386e858e0c0000000020000004b0001000b544553542e474f4b52423500097465737475736572310000000158e14ba202001a0020e4a7346f6e37484ec10ca0bcf14d4e340ab8bcc6b9a42851e1114540325b7e4f000000020000003b0001000b544553542e474f4b52423500097465737475736572310000000158e14ba2020019001076ed573a0bd71371eecd9c5402dace6a00000002000000330001000b544553542e474f4b52423500097465737475736572310000000158e14ba202000800087f68858f6413e54f00000002000000330001000b544553542e474f4b52423500097465737475736572310000000158e14ba202000300080283f2ea20a10efb00000002"
+	TESTUSER1_KEYTAB = "05020000004b0001000b544553542e474f4b52423500097465737475736572310000000158e543060100120020bbdc430aab7e2d4622a0b6951481453b0962e9db8e2f168942ad175cda6d9de900000001"
 	TEST_AS_REQ      = "6a81a63081a3a103020105a20302010aa30e300c300aa10402020095a2020400a48186308183a00703050040000010a1163014a003020101a10d300b1b09746573747573657231a20d1b0b544553542e474f4b524235a320301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a511180f32303137303232303134323530315aa70602040f6755a6a814301202011202011102011002011702011902011a"
 	TEST_AS_REQ      = "6a81a63081a3a103020105a20302010aa30e300c300aa10402020095a2020400a48186308183a00703050040000010a1163014a003020101a10d300b1b09746573747573657231a20d1b0b544553542e474f4b524235a320301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a511180f32303137303232303134323530315aa70602040f6755a6a814301202011202011102011002011702011902011a"
 	TEST_AS_REP      = "6b8202f3308202efa003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010264d3fa49d89b627ed471298846ff92cd8632f657c58fe25322a61fffa32bb7966dc4c44c86a81353def2a11c36c537191406a609147f424a63266c00d02bcc56a27b0969d86ff4352634be9e2a4ac0ad5a36b0b0a3d689f128c0afa97401796e88037a35ad19efaf31d1ed4f3213769c03a58bc90ffac2051db152c0ed0809ad05ffb03aa3afaf731ed85f7a73020cb72355e0de27842dcf7eae3de9f7c14aa237edb25153b217ef3693373bc3cacbebe406910ff9ae9d00b7b08f726cb29a213cb9ad51ba80a8c24fa4b6692a445686889702cfa6ea749bac03e27e982407aca623fbd48586bcf566cfe87e1d9f17a74b1315669c16480f93e9d8782e71a8f11000a682012c30820128a003020112a282011f0482011b99b86153c0393c0e4130628f3e1e0f0a1f034e7e61a111b7fad15884e231c8fd8727e0bc945c9b35be20c57d057c8b09b0de74c53fb38cc15c9a2d483023fc369f5bde4da7324b4732b5a3d9504d92f67026aaa01df4f0138245d2ccb1c5a4014804cf295c7e7e56a867e6cf0c534f667f32da7aa5e700af1461764f1c276a8ff0fbee0e99322fe2059d2321853be09d0956c3afcfd07e3e702646a4678926a77bea20d9aaf3086b6d384821c81900af9013a3519f0e50eab6e1491d72e4ee17c2a44441b2ebc8a796cc3d876e328347dce65f61104e14d4c31532885776c9c8a70186b8b39f928972945c98bd60381ead5448e7ebe93fea308054287ac34b0583b4b9b5e43c5f8518d693ba9eb48a219c27344466b3c693a70462"
 	TEST_AS_REP      = "6b8202f3308202efa003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010264d3fa49d89b627ed471298846ff92cd8632f657c58fe25322a61fffa32bb7966dc4c44c86a81353def2a11c36c537191406a609147f424a63266c00d02bcc56a27b0969d86ff4352634be9e2a4ac0ad5a36b0b0a3d689f128c0afa97401796e88037a35ad19efaf31d1ed4f3213769c03a58bc90ffac2051db152c0ed0809ad05ffb03aa3afaf731ed85f7a73020cb72355e0de27842dcf7eae3de9f7c14aa237edb25153b217ef3693373bc3cacbebe406910ff9ae9d00b7b08f726cb29a213cb9ad51ba80a8c24fa4b6692a445686889702cfa6ea749bac03e27e982407aca623fbd48586bcf566cfe87e1d9f17a74b1315669c16480f93e9d8782e71a8f11000a682012c30820128a003020112a282011f0482011b99b86153c0393c0e4130628f3e1e0f0a1f034e7e61a111b7fad15884e231c8fd8727e0bc945c9b35be20c57d057c8b09b0de74c53fb38cc15c9a2d483023fc369f5bde4da7324b4732b5a3d9504d92f67026aaa01df4f0138245d2ccb1c5a4014804cf295c7e7e56a867e6cf0c534f667f32da7aa5e700af1461764f1c276a8ff0fbee0e99322fe2059d2321853be09d0956c3afcfd07e3e702646a4678926a77bea20d9aaf3086b6d384821c81900af9013a3519f0e50eab6e1491d72e4ee17c2a44441b2ebc8a796cc3d876e328347dce65f61104e14d4c31532885776c9c8a70186b8b39f928972945c98bd60381ead5448e7ebe93fea308054287ac34b0583b4b9b5e43c5f8518d693ba9eb48a219c27344466b3c693a70462"
 	TEST_TGS_REQ     = "6c82038f3082038ba103020105a20302010ca382031a3082031630820245a103020101a282023c048202386e82023430820230a003020105a10302010ea20703050000000000a382015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010264d3fa49d89b627ed471298846ff92cd8632f657c58fe25322a61fffa32bb7966dc4c44c86a81353def2a11c36c537191406a609147f424a63266c00d02bcc56a27b0969d86ff4352634be9e2a4ac0ad5a36b0b0a3d689f128c0afa97401796e88037a35ad19efaf31d1ed4f3213769c03a58bc90ffac2051db152c0ed0809ad05ffb03aa3afaf731ed85f7a73020cb72355e0de27842dcf7eae3de9f7c14aa237edb25153b217ef3693373bc3cacbebe406910ff9ae9d00b7b08f726cb29a213cb9ad51ba80a8c24fa4b6692a445686889702cfa6ea749bac03e27e982407aca623fbd48586bcf566cfe87e1d9f17a74b1315669c16480f93e9d8782e71a8f11000a481bc3081b9a003020112a281b10481ae8ae3cb8ac47d77cfc7b0b6bf0d3c5f8fcc6dd569344256a6a40c004fc2d23ebbe6ee0b9e00eccf37e710b7c01a7d2a63bbed6d75f2b230d24d724ef90edad2c5680e7e2436ab1145ff68481673444ebd61e3aef79b9ee05809551672c6c436eb8ac732a7fe78bd8f380e68a541191e3125554e4bab63dcc19ea931c1477366a6039ff7b7e62521ebfeffd6784b6ef0c97f653ac4d8dfb304f3e2e843faab12d838c23f1105f0a281c39325987cb03081caa10402020088a281c10481bea081bb3081b8a1173015a003020110a10e040ce613d8e9d544f0e56c60d3bba2819c308199a003020112a2819104818ec4fabcb1ec2f24e04ef51f9247239b28275653fa5cbc1dc9e747530c597631050fe86a5f3cba2ff54270aa771dcefa87efc8c8604407f84e603f5c01a2d929e18103561c3ffbc3a0cf63340bdd67a0739d4d81989827fc1d3f7f13e9dd5cc2346ca08e26a2aaf6d0102fbef8f7a6ee0a1caae7880e953ea678da619038786122a0b71853e8d0b95f544f8fbd6945a461305fa00703050040810000a20d1b0b544553542e474f4b524235a3233021a003020101a11a30181b04485454501b10686f73742e746573742e676f6b726235a511180f32303137303232303032323634325aa706020458a9ab2aa8053003020112"
 	TEST_TGS_REQ     = "6c82038f3082038ba103020105a20302010ca382031a3082031630820245a103020101a282023c048202386e82023430820230a003020105a10302010ea20703050000000000a382015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010264d3fa49d89b627ed471298846ff92cd8632f657c58fe25322a61fffa32bb7966dc4c44c86a81353def2a11c36c537191406a609147f424a63266c00d02bcc56a27b0969d86ff4352634be9e2a4ac0ad5a36b0b0a3d689f128c0afa97401796e88037a35ad19efaf31d1ed4f3213769c03a58bc90ffac2051db152c0ed0809ad05ffb03aa3afaf731ed85f7a73020cb72355e0de27842dcf7eae3de9f7c14aa237edb25153b217ef3693373bc3cacbebe406910ff9ae9d00b7b08f726cb29a213cb9ad51ba80a8c24fa4b6692a445686889702cfa6ea749bac03e27e982407aca623fbd48586bcf566cfe87e1d9f17a74b1315669c16480f93e9d8782e71a8f11000a481bc3081b9a003020112a281b10481ae8ae3cb8ac47d77cfc7b0b6bf0d3c5f8fcc6dd569344256a6a40c004fc2d23ebbe6ee0b9e00eccf37e710b7c01a7d2a63bbed6d75f2b230d24d724ef90edad2c5680e7e2436ab1145ff68481673444ebd61e3aef79b9ee05809551672c6c436eb8ac732a7fe78bd8f380e68a541191e3125554e4bab63dcc19ea931c1477366a6039ff7b7e62521ebfeffd6784b6ef0c97f653ac4d8dfb304f3e2e843faab12d838c23f1105f0a281c39325987cb03081caa10402020088a281c10481bea081bb3081b8a1173015a003020110a10e040ce613d8e9d544f0e56c60d3bba2819c308199a003020112a2819104818ec4fabcb1ec2f24e04ef51f9247239b28275653fa5cbc1dc9e747530c597631050fe86a5f3cba2ff54270aa771dcefa87efc8c8604407f84e603f5c01a2d929e18103561c3ffbc3a0cf63340bdd67a0739d4d81989827fc1d3f7f13e9dd5cc2346ca08e26a2aaf6d0102fbef8f7a6ee0a1caae7880e953ea678da619038786122a0b71853e8d0b95f544f8fbd6945a461305fa00703050040810000a20d1b0b544553542e474f4b524235a3233021a003020101a11a30181b04485454501b10686f73742e746573742e676f6b726235a511180f32303137303232303032323634325aa706020458a9ab2aa8053003020112"

+ 1 - 0
testenv/krbhttp-vagrant/bootstrap.sh

@@ -22,6 +22,7 @@ net.ipv6.conf.default.disable_ipv6 = 1
 net.ipv6.conf.lo.disable_ipv6 = 1
 net.ipv6.conf.lo.disable_ipv6 = 1
 EOF
 EOF
 
 
+echo "10.80.88.88 kdc.test.gokrb5" >> /etc/hosts
 echo "10.80.88.89 client.test.gokrb5" >> /etc/hosts
 echo "10.80.88.89 client.test.gokrb5" >> /etc/hosts
 echo "10.80.88.90 host.test.gokrb5" >> /etc/hosts
 echo "10.80.88.90 host.test.gokrb5" >> /etc/hosts