This commit is contained in:
parent
741f7d9ffe
commit
b9e73370f9
52
go.mod
52
go.mod
@ -3,27 +3,51 @@ module git.paulbsd.com/paulbsd/qrz
|
|||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/antchfx/htmlquery v1.0.0
|
github.com/alexbrainman/sspi v0.0.0-20200928142253-2a432fede40d // indirect
|
||||||
github.com/antchfx/xpath v1.0.0 // indirect
|
github.com/antchfx/htmlquery v1.2.3
|
||||||
|
github.com/antchfx/xpath v1.1.11 // indirect
|
||||||
|
github.com/apache/thrift v0.12.0 // indirect
|
||||||
|
github.com/gobuffalo/here v0.6.2 // indirect
|
||||||
github.com/gobuffalo/packr/v2 v2.8.1
|
github.com/gobuffalo/packr/v2 v2.8.1
|
||||||
github.com/golang/protobuf v1.3.2 // indirect
|
github.com/golang/protobuf v1.4.3 // indirect
|
||||||
|
github.com/golang/snappy v0.0.2 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.4 // indirect
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
|
||||||
github.com/karrick/godirwalk v1.16.1 // indirect
|
github.com/karrick/godirwalk v1.16.1 // indirect
|
||||||
github.com/labstack/echo/v4 v4.1.16
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/lib/pq v1.6.0
|
github.com/labstack/echo/v4 v4.1.17
|
||||||
github.com/markbates/pkger v0.14.0
|
github.com/lib/pq v1.9.0
|
||||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect
|
github.com/markbates/pkger v0.17.1
|
||||||
|
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||||
|
github.com/nxadm/tail v1.4.5 // indirect
|
||||||
|
github.com/onsi/ginkgo v1.14.2 // indirect
|
||||||
|
github.com/onsi/gomega v1.10.3 // indirect
|
||||||
|
github.com/openzipkin/zipkin-go v0.1.6 // indirect
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/rogpeppe/go-internal v1.6.2 // indirect
|
github.com/rogpeppe/go-internal v1.6.2 // indirect
|
||||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||||
|
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/spf13/cobra v1.1.1 // indirect
|
github.com/spf13/cobra v1.1.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 // indirect
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c // indirect
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
|
||||||
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7 // indirect
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||||
|
golang.org/x/text v0.3.4 // indirect
|
||||||
golang.org/x/tools v0.0.0-20201118215654-4d9c4f8a78b0 // indirect
|
golang.org/x/tools v0.0.0-20201118215654-4d9c4f8a78b0 // indirect
|
||||||
google.golang.org/appengine v1.6.2 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
gopkg.in/ini.v1 v1.51.0
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
xorm.io/xorm v1.0.2
|
gopkg.in/ini.v1 v1.62.0
|
||||||
|
gopkg.in/jcmturner/aescts.v1 v1.0.1 // indirect
|
||||||
|
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 // indirect
|
||||||
|
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
|
||||||
|
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 // indirect
|
||||||
|
gopkg.in/jcmturner/rpc.v1 v1.1.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||||
|
xorm.io/xorm v1.0.5
|
||||||
)
|
)
|
||||||
|
138
go.sum
138
go.sum
@ -17,16 +17,24 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0p
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
||||||
|
github.com/alexbrainman/sspi v0.0.0-20200928142253-2a432fede40d/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
||||||
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/antchfx/htmlquery v1.0.0 h1:O5IXz8fZF3B3MW+B33MZWbTHBlYmcfw0BAxgErHuaMA=
|
github.com/antchfx/htmlquery v1.0.0 h1:O5IXz8fZF3B3MW+B33MZWbTHBlYmcfw0BAxgErHuaMA=
|
||||||
github.com/antchfx/htmlquery v1.0.0/go.mod h1:MS9yksVSQXls00iXkiMqXr0J+umL/AmxXKuP28SUJM8=
|
github.com/antchfx/htmlquery v1.0.0/go.mod h1:MS9yksVSQXls00iXkiMqXr0J+umL/AmxXKuP28SUJM8=
|
||||||
|
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
|
||||||
|
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||||
github.com/antchfx/xpath v1.0.0 h1:Q5gFgh2O40VTSwMOVbFE7nFNRBu3tS21Tn0KAWeEjtk=
|
github.com/antchfx/xpath v1.0.0 h1:Q5gFgh2O40VTSwMOVbFE7nFNRBu3tS21Tn0KAWeEjtk=
|
||||||
github.com/antchfx/xpath v1.0.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
github.com/antchfx/xpath v1.0.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||||
|
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||||
|
github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ=
|
||||||
|
github.com/antchfx/xpath v1.1.11/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
@ -36,6 +44,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
@ -46,19 +55,25 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
@ -66,9 +81,13 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
||||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||||
|
github.com/gobuffalo/here v0.6.2 h1:ZtCqC7F9ou3moLbYfHM1Tj+gwHGgWhjyRjVjsir9BE0=
|
||||||
|
github.com/gobuffalo/here v0.6.2/go.mod h1:D75Sq0p2BVHdgQu3vCRsXbg85rx943V19urJpqAVWjI=
|
||||||
github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gqc=
|
github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gqc=
|
||||||
github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
|
github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
|
||||||
github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
|
github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
|
||||||
@ -79,8 +98,11 @@ github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5
|
|||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
@ -89,12 +111,29 @@ github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg
|
|||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
||||||
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
@ -103,12 +142,15 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
|
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
|
||||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
|
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
@ -150,8 +192,10 @@ github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJA
|
|||||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||||
github.com/jcmturner/gokrb5/v8 v8.2.0 h1:lzPl/30ZLkTveYsYZPKMcgXc8MbnE6RsTd4F9KgiLtk=
|
github.com/jcmturner/gokrb5/v8 v8.2.0 h1:lzPl/30ZLkTveYsYZPKMcgXc8MbnE6RsTd4F9KgiLtk=
|
||||||
github.com/jcmturner/gokrb5/v8 v8.2.0/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM=
|
github.com/jcmturner/gokrb5/v8 v8.2.0/go.mod h1:T1hnNppQsBtxW0tCHMHTkAt8n/sABdzZgZdoFrZaZNM=
|
||||||
|
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
|
||||||
github.com/jcmturner/rpc/v2 v2.0.2 h1:gMB4IwRXYsWw4Bc6o/az2HJgFUA1ffSh90i26ZJ6Xl0=
|
github.com/jcmturner/rpc/v2 v2.0.2 h1:gMB4IwRXYsWw4Bc6o/az2HJgFUA1ffSh90i26ZJ6Xl0=
|
||||||
github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
github.com/jcmturner/rpc/v2 v2.0.2/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
|
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
@ -169,17 +213,27 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
|
|||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo/v4 v4.1.16 h1:8swiwjE5Jkai3RPfZoahp8kjVCRNq+y7Q0hPji2Kz0o=
|
github.com/labstack/echo/v4 v4.1.16 h1:8swiwjE5Jkai3RPfZoahp8kjVCRNq+y7Q0hPji2Kz0o=
|
||||||
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
|
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
|
||||||
|
github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo=
|
||||||
|
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
|
||||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.6.0 h1:I5DPxhYJChW9KYc66se+oKFFQX6VuQrKiprsX6ivRZc=
|
github.com/lib/pq v1.6.0 h1:I5DPxhYJChW9KYc66se+oKFFQX6VuQrKiprsX6ivRZc=
|
||||||
github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
|
github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
|
||||||
|
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||||
|
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
|
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
|
||||||
@ -188,20 +242,28 @@ github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY
|
|||||||
github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
|
github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
|
||||||
github.com/markbates/pkger v0.14.0 h1:z6KCEBkr3zJTkAMz5SJzjA9Izo+Ipb6XXvOIjQEW+PU=
|
github.com/markbates/pkger v0.14.0 h1:z6KCEBkr3zJTkAMz5SJzjA9Izo+Ipb6XXvOIjQEW+PU=
|
||||||
github.com/markbates/pkger v0.14.0/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
github.com/markbates/pkger v0.14.0/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||||
|
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
|
||||||
|
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||||
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
|
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
|
||||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
|
github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
|
||||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||||
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
@ -215,12 +277,23 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.5 h1:obHEce3upls1IBn1gTw/o7bCv7OJb6Ib/o7wNO+4eKw=
|
||||||
|
github.com/nxadm/tail v1.4.5/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
||||||
|
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
||||||
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
@ -236,6 +309,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
|
|||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
@ -263,6 +337,8 @@ github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM
|
|||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||||
|
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
@ -288,6 +364,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
@ -298,6 +376,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
|
|||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
|
||||||
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
|
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||||
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@ -323,8 +403,12 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
|
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
|
||||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
|
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
|
||||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
|
||||||
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -345,6 +429,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
|||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -363,10 +448,18 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
|
|||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
||||||
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -397,21 +490,34 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7 h1:Z991aAXPjz0tLnj74pVXW3eWJ5lHMIBvbRfMq4M2jHA=
|
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7 h1:Z991aAXPjz0tLnj74pVXW3eWJ5lHMIBvbRfMq4M2jHA=
|
||||||
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
|
||||||
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -425,6 +531,7 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
@ -440,6 +547,7 @@ golang.org/x/tools v0.0.0-20201118215654-4d9c4f8a78b0/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
@ -454,6 +562,7 @@ google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
|
google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
|
||||||
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@ -464,21 +573,40 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
|
|||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||||
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
||||||
@ -496,13 +624,23 @@ gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
|||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
|
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
|
||||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/xorm v1.0.2 h1:kZlCh9rqd1AzGwWitcrEEqHE1h1eaZE/ujU5/2tWEtg=
|
xorm.io/xorm v1.0.2 h1:kZlCh9rqd1AzGwWitcrEEqHE1h1eaZE/ujU5/2tWEtg=
|
||||||
xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY=
|
xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY=
|
||||||
|
xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0=
|
||||||
|
xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||||
|
27
vendor/github.com/alexbrainman/sspi/LICENSE
generated
vendored
27
vendor/github.com/alexbrainman/sspi/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1
vendor/github.com/alexbrainman/sspi/README.md
generated
vendored
1
vendor/github.com/alexbrainman/sspi/README.md
generated
vendored
@ -1 +0,0 @@
|
|||||||
This repository holds Go packages for accessing Security Support Provider Interface on Windows.
|
|
57
vendor/github.com/alexbrainman/sspi/buffer.go
generated
vendored
57
vendor/github.com/alexbrainman/sspi/buffer.go
generated
vendored
@ -1,57 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package sspi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *SecBuffer) Set(buftype uint32, data []byte) {
|
|
||||||
b.BufferType = buftype
|
|
||||||
if len(data) > 0 {
|
|
||||||
b.Buffer = &data[0]
|
|
||||||
b.BufferSize = uint32(len(data))
|
|
||||||
} else {
|
|
||||||
b.Buffer = nil
|
|
||||||
b.BufferSize = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SecBuffer) Free() error {
|
|
||||||
if b.Buffer == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return FreeContextBuffer((*byte)(unsafe.Pointer(b.Buffer)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SecBuffer) Bytes() []byte {
|
|
||||||
if b.Buffer == nil || b.BufferSize <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return (*[2 << 20]byte)(unsafe.Pointer(b.Buffer))[:b.BufferSize]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SecBuffer) WriteAll(w io.Writer) (int, error) {
|
|
||||||
if b.BufferSize == 0 || b.Buffer == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
data := b.Bytes()
|
|
||||||
total := 0
|
|
||||||
for {
|
|
||||||
n, err := w.Write(data)
|
|
||||||
total += n
|
|
||||||
if err != nil {
|
|
||||||
return total, err
|
|
||||||
}
|
|
||||||
if n >= len(data) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data = data[n:]
|
|
||||||
}
|
|
||||||
return total, nil
|
|
||||||
}
|
|
7
vendor/github.com/alexbrainman/sspi/mksyscall.go
generated
vendored
7
vendor/github.com/alexbrainman/sspi/mksyscall.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package sspi
|
|
||||||
|
|
||||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -systemdll=false -output=zsyscall_windows.go syscall.go
|
|
462
vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go
generated
vendored
462
vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go
generated
vendored
@ -1,462 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
// Package negotiate provides access to the Microsoft Negotiate SSP Package.
|
|
||||||
//
|
|
||||||
package negotiate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/alexbrainman/sspi"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: maybe (if possible) move all winapi related out of sspi and into sspi/internal/winapi
|
|
||||||
|
|
||||||
// PackageInfo contains Negotiate SSP package description.
|
|
||||||
var PackageInfo *sspi.PackageInfo
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
PackageInfo, err = sspi.QueryPackageInfo(sspi.NEGOSSP_NAME)
|
|
||||||
if err != nil {
|
|
||||||
panic("failed to fetch Negotiate package info: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func acquireCredentials(principalName string, creduse uint32, ai *sspi.SEC_WINNT_AUTH_IDENTITY) (*sspi.Credentials, error) {
|
|
||||||
c, err := sspi.AcquireCredentials(principalName, sspi.NEGOSSP_NAME, creduse, (*byte)(unsafe.Pointer(ai)))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcquireCurrentUserCredentials acquires credentials of currently
|
|
||||||
// logged on user. These will be used by the client to authenticate
|
|
||||||
// itself to the server. It will also be used by the server
|
|
||||||
// to impersonate the user.
|
|
||||||
func AcquireCurrentUserCredentials() (*sspi.Credentials, error) {
|
|
||||||
return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: see if I can share this common ntlm and negotiate code
|
|
||||||
|
|
||||||
// AcquireUserCredentials acquires credentials of user described by
|
|
||||||
// domain, username and password. These will be used by the client to
|
|
||||||
// authenticate itself to the server. It will also be used by the
|
|
||||||
// server to impersonate the user.
|
|
||||||
func AcquireUserCredentials(domain, username, password string) (*sspi.Credentials, error) {
|
|
||||||
if len(username) == 0 {
|
|
||||||
return nil, errors.New("username parameter cannot be empty")
|
|
||||||
}
|
|
||||||
d, err := syscall.UTF16FromString(domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
u, err := syscall.UTF16FromString(username)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
p, err := syscall.UTF16FromString(password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ai := sspi.SEC_WINNT_AUTH_IDENTITY{
|
|
||||||
User: &u[0],
|
|
||||||
UserLength: uint32(len(u) - 1), // do not count terminating 0
|
|
||||||
Domain: &d[0],
|
|
||||||
DomainLength: uint32(len(d) - 1), // do not count terminating 0
|
|
||||||
Password: &p[0],
|
|
||||||
PasswordLength: uint32(len(p) - 1), // do not count terminating 0
|
|
||||||
Flags: sspi.SEC_WINNT_AUTH_IDENTITY_UNICODE,
|
|
||||||
}
|
|
||||||
return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, &ai)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcquireServerCredentials acquires server credentials that will
|
|
||||||
// be used to authenticate clients.
|
|
||||||
// The principalName parameter is passed to the underlying call to
|
|
||||||
// the winapi AcquireCredentialsHandle function (and specifies the
|
|
||||||
// name of the principal whose credentials the underlying handle
|
|
||||||
// will reference).
|
|
||||||
// As a special case, using an empty string for the principal name
|
|
||||||
// will require the credential of the user under whose security context
|
|
||||||
// the current process is running.
|
|
||||||
func AcquireServerCredentials(principalName string) (*sspi.Credentials, error) {
|
|
||||||
return acquireCredentials(principalName, sspi.SECPKG_CRED_INBOUND, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateContext(c *sspi.Context, dst, src []byte, targetName *uint16) (authCompleted bool, n int, err error) {
|
|
||||||
var inBuf, outBuf [1]sspi.SecBuffer
|
|
||||||
inBuf[0].Set(sspi.SECBUFFER_TOKEN, src)
|
|
||||||
inBufs := &sspi.SecBufferDesc{
|
|
||||||
Version: sspi.SECBUFFER_VERSION,
|
|
||||||
BuffersCount: 1,
|
|
||||||
Buffers: &inBuf[0],
|
|
||||||
}
|
|
||||||
outBuf[0].Set(sspi.SECBUFFER_TOKEN, dst)
|
|
||||||
outBufs := &sspi.SecBufferDesc{
|
|
||||||
Version: sspi.SECBUFFER_VERSION,
|
|
||||||
BuffersCount: 1,
|
|
||||||
Buffers: &outBuf[0],
|
|
||||||
}
|
|
||||||
ret := c.Update(targetName, outBufs, inBufs)
|
|
||||||
switch ret {
|
|
||||||
case sspi.SEC_E_OK:
|
|
||||||
// session established -> return success
|
|
||||||
return true, int(outBuf[0].BufferSize), nil
|
|
||||||
case sspi.SEC_I_COMPLETE_NEEDED, sspi.SEC_I_COMPLETE_AND_CONTINUE:
|
|
||||||
ret = sspi.CompleteAuthToken(c.Handle, outBufs)
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return false, 0, ret
|
|
||||||
}
|
|
||||||
case sspi.SEC_I_CONTINUE_NEEDED:
|
|
||||||
default:
|
|
||||||
return false, 0, ret
|
|
||||||
}
|
|
||||||
return false, int(outBuf[0].BufferSize), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSignature(c *sspi.Context, msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
_, maxSignature, _, _, err := c.Sizes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if maxSignature == 0 {
|
|
||||||
return nil, errors.New("integrity services are not requested or unavailable")
|
|
||||||
}
|
|
||||||
|
|
||||||
var b [2]sspi.SecBuffer
|
|
||||||
b[0].Set(sspi.SECBUFFER_DATA, msg)
|
|
||||||
b[1].Set(sspi.SECBUFFER_TOKEN, make([]byte, maxSignature))
|
|
||||||
|
|
||||||
ret := sspi.MakeSignature(c.Handle, qop, sspi.NewSecBufferDesc(b[:]), seqno)
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return nil, ret
|
|
||||||
}
|
|
||||||
|
|
||||||
return b[1].Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptMessage(c *sspi.Context, msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
_ /*maxToken*/, maxSignature, cBlockSize, cSecurityTrailer, err := c.Sizes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if maxSignature == 0 {
|
|
||||||
return nil, errors.New("integrity services are not requested or unavailable")
|
|
||||||
}
|
|
||||||
|
|
||||||
var b [3]sspi.SecBuffer
|
|
||||||
b[0].Set(sspi.SECBUFFER_TOKEN, make([]byte, cSecurityTrailer))
|
|
||||||
b[1].Set(sspi.SECBUFFER_DATA, msg)
|
|
||||||
b[2].Set(sspi.SECBUFFER_PADDING, make([]byte, cBlockSize))
|
|
||||||
|
|
||||||
ret := sspi.EncryptMessage(c.Handle, qop, sspi.NewSecBufferDesc(b[:]), seqno)
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return nil, ret
|
|
||||||
}
|
|
||||||
|
|
||||||
r0, r1, r2 := b[0].Bytes(), b[1].Bytes(), b[2].Bytes()
|
|
||||||
res := make([]byte, 0, len(r0)+len(r1)+len(r2))
|
|
||||||
res = append(res, r0...)
|
|
||||||
res = append(res, r1...)
|
|
||||||
res = append(res, r2...)
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptMessage(c *sspi.Context, msg []byte, seqno uint32) (uint32, []byte, error) {
|
|
||||||
var b [2]sspi.SecBuffer
|
|
||||||
b[0].Set(sspi.SECBUFFER_STREAM, msg)
|
|
||||||
b[1].Set(sspi.SECBUFFER_DATA, []byte{})
|
|
||||||
|
|
||||||
var qop uint32
|
|
||||||
ret := sspi.DecryptMessage(c.Handle, sspi.NewSecBufferDesc(b[:]), seqno, &qop)
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return qop, nil, ret
|
|
||||||
}
|
|
||||||
|
|
||||||
return qop, b[1].Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifySignature(c *sspi.Context, msg, token []byte, seqno uint32) (uint32, error) {
|
|
||||||
var b [2]sspi.SecBuffer
|
|
||||||
b[0].Set(sspi.SECBUFFER_DATA, msg)
|
|
||||||
b[1].Set(sspi.SECBUFFER_TOKEN, token)
|
|
||||||
|
|
||||||
var qop uint32
|
|
||||||
|
|
||||||
ret := sspi.VerifySignature(c.Handle, sspi.NewSecBufferDesc(b[:]), seqno, &qop)
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return 0, ret
|
|
||||||
}
|
|
||||||
|
|
||||||
return qop, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientContext is used by the client to manage all steps of Negotiate negotiation.
|
|
||||||
type ClientContext struct {
|
|
||||||
sctxt *sspi.Context
|
|
||||||
targetName *uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientContext creates a new client context. It uses client
|
|
||||||
// credentials cred generated by AcquireCurrentUserCredentials or
|
|
||||||
// AcquireUserCredentials and SPN to start a client Negotiate
|
|
||||||
// negotiation sequence. targetName is the service principal name
|
|
||||||
// (SPN) or the security context of the destination server.
|
|
||||||
// NewClientContext returns a new token to be sent to the server.
|
|
||||||
func NewClientContext(cred *sspi.Credentials, targetName string) (cc *ClientContext, outputToken []byte, err error) {
|
|
||||||
return NewClientContextWithFlags(cred, targetName, sspi.ISC_REQ_CONNECTION)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientContextWithFlags creates a new client context. It uses client
|
|
||||||
// credentials cred generated by AcquireCurrentUserCredentials or
|
|
||||||
// AcquireUserCredentials and SPN to start a client Negotiate
|
|
||||||
// negotiation sequence. targetName is the service principal name
|
|
||||||
// (SPN) or the security context of the destination server.
|
|
||||||
// The flags parameter is used to indicate requests for the context
|
|
||||||
// (for example sspi.ISC_REQ_CONFIDENTIALITY|sspi.ISC_REQ_REPLAY_DETECT)
|
|
||||||
// NewClientContextWithFlags returns a new token to be sent to the server.
|
|
||||||
func NewClientContextWithFlags(cred *sspi.Credentials, targetName string, flags uint32) (cc *ClientContext, outputToken []byte, err error) {
|
|
||||||
var tname *uint16
|
|
||||||
if len(targetName) > 0 {
|
|
||||||
p, err2 := syscall.UTF16FromString(targetName)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, nil, err2
|
|
||||||
}
|
|
||||||
if len(p) > 0 {
|
|
||||||
tname = &p[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
otoken := make([]byte, PackageInfo.MaxToken)
|
|
||||||
c := sspi.NewClientContext(cred, flags)
|
|
||||||
|
|
||||||
authCompleted, n, err2 := updateContext(c, otoken, nil, tname)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, nil, err2
|
|
||||||
}
|
|
||||||
if authCompleted {
|
|
||||||
c.Release()
|
|
||||||
return nil, nil, errors.New("negotiate authentication should not be completed yet")
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
c.Release()
|
|
||||||
return nil, nil, errors.New("negotiate token should not be empty")
|
|
||||||
}
|
|
||||||
otoken = otoken[:n]
|
|
||||||
return &ClientContext{sctxt: c, targetName: tname}, otoken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release free up resources associated with client context c.
|
|
||||||
func (c *ClientContext) Release() error {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.sctxt.Release()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expiry returns c expiry time.
|
|
||||||
func (c *ClientContext) Expiry() time.Time {
|
|
||||||
return c.sctxt.Expiry()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update advances client part of Negotiate negotiation c. It uses
|
|
||||||
// token received from the server and returns true if client part
|
|
||||||
// of authentication is complete. It also returns new token to be
|
|
||||||
// sent to the server.
|
|
||||||
func (c *ClientContext) Update(token []byte) (authCompleted bool, outputToken []byte, err error) {
|
|
||||||
otoken := make([]byte, PackageInfo.MaxToken)
|
|
||||||
authDone, n, err2 := updateContext(c.sctxt, otoken, token, c.targetName)
|
|
||||||
if err2 != nil {
|
|
||||||
return false, nil, err2
|
|
||||||
}
|
|
||||||
if n == 0 && !authDone {
|
|
||||||
return false, nil, errors.New("negotiate token should not be empty")
|
|
||||||
}
|
|
||||||
otoken = otoken[:n]
|
|
||||||
return authDone, otoken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sizes queries the client context for the sizes used in per-message
|
|
||||||
// functions. It returns the maximum token size used in authentication
|
|
||||||
// exchanges, the maximum signature size, the preferred integral size of
|
|
||||||
// messages, the size of any security trailer, and any error.
|
|
||||||
func (c *ClientContext) Sizes() (uint32, uint32, uint32, uint32, error) {
|
|
||||||
return c.sctxt.Sizes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeSignature uses the established client context to create a signature
|
|
||||||
// for the given message using the provided quality of protection flags and
|
|
||||||
// sequence number. It returns the signature token in addition to any error.
|
|
||||||
func (c *ClientContext) MakeSignature(msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
return makeSignature(c.sctxt, msg, qop, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignature uses the established client context and signature token
|
|
||||||
// to check that the provided message hasn't been tampered or received out
|
|
||||||
// of sequence. It returns any quality of protection flags and any error
|
|
||||||
// that occurred.
|
|
||||||
func (c *ClientContext) VerifySignature(msg, token []byte, seqno uint32) (uint32, error) {
|
|
||||||
return verifySignature(c.sctxt, msg, token, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage uses the established client context to encrypt a message
|
|
||||||
// using the provided quality of protection flags and sequence number.
|
|
||||||
// It returns the signature token in addition to any error.
|
|
||||||
// IMPORTANT: the input msg parameter is updated in place by the low-level windows api
|
|
||||||
// so must be copied if the initial content should not be modified.
|
|
||||||
func (c *ClientContext) EncryptMessage(msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
return encryptMessage(c.sctxt, msg, qop, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage uses the established client context to decrypt a message
|
|
||||||
// using the provided sequence number.
|
|
||||||
// It returns the quality of protection flag and the decrypted message in addition to any error.
|
|
||||||
func (c *ClientContext) DecryptMessage(msg []byte, seqno uint32) (uint32, []byte, error) {
|
|
||||||
return decryptMessage(c.sctxt, msg, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyFlags determines if all flags used to construct the client context
|
|
||||||
// were honored (see NewClientContextWithFlags). It should be called after c.Update.
|
|
||||||
func (c *ClientContext) VerifyFlags() error {
|
|
||||||
return c.sctxt.VerifyFlags()
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySelectiveFlags determines if the given flags were honored (see NewClientContextWithFlags).
|
|
||||||
// It should be called after c.Update.
|
|
||||||
func (c *ClientContext) VerifySelectiveFlags(flags uint32) error {
|
|
||||||
return c.sctxt.VerifySelectiveFlags(flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerContext is used by the server to manage all steps of Negotiate
|
|
||||||
// negotiation. Once authentication is completed the context can be
|
|
||||||
// used to impersonate client.
|
|
||||||
type ServerContext struct {
|
|
||||||
sctxt *sspi.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewServerContext creates new server context. It uses server
|
|
||||||
// credentials created by AcquireServerCredentials and token from
|
|
||||||
// the client to start server Negotiate negotiation sequence.
|
|
||||||
// It also returns new token to be sent to the client.
|
|
||||||
func NewServerContext(cred *sspi.Credentials, token []byte) (sc *ServerContext, authDone bool, outputToken []byte, err error) {
|
|
||||||
otoken := make([]byte, PackageInfo.MaxToken)
|
|
||||||
c := sspi.NewServerContext(cred, sspi.ASC_REQ_CONNECTION)
|
|
||||||
authDone, n, err2 := updateContext(c, otoken, token, nil)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, false, nil, err2
|
|
||||||
}
|
|
||||||
otoken = otoken[:n]
|
|
||||||
return &ServerContext{sctxt: c}, authDone, otoken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release free up resources associated with server context c.
|
|
||||||
func (c *ServerContext) Release() error {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.sctxt.Release()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expiry returns c expiry time.
|
|
||||||
func (c *ServerContext) Expiry() time.Time {
|
|
||||||
return c.sctxt.Expiry()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update advances server part of Negotiate negotiation c. It uses
|
|
||||||
// token received from the client and returns true if server part
|
|
||||||
// of authentication is complete. It also returns new token to be
|
|
||||||
// sent to the client.
|
|
||||||
func (c *ServerContext) Update(token []byte) (authCompleted bool, outputToken []byte, err error) {
|
|
||||||
otoken := make([]byte, PackageInfo.MaxToken)
|
|
||||||
authDone, n, err2 := updateContext(c.sctxt, otoken, token, nil)
|
|
||||||
if err2 != nil {
|
|
||||||
return false, nil, err2
|
|
||||||
}
|
|
||||||
if n == 0 && !authDone {
|
|
||||||
return false, nil, errors.New("negotiate token should not be empty")
|
|
||||||
}
|
|
||||||
otoken = otoken[:n]
|
|
||||||
return authDone, otoken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const _SECPKG_ATTR_NATIVE_NAMES = 13
|
|
||||||
|
|
||||||
type _SecPkgContext_NativeNames struct {
|
|
||||||
ClientName *uint16
|
|
||||||
ServerName *uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsername returns the username corresponding to the authenticated client
|
|
||||||
func (c *ServerContext) GetUsername() (string, error) {
|
|
||||||
var ns _SecPkgContext_NativeNames
|
|
||||||
ret := sspi.QueryContextAttributes(c.sctxt.Handle, _SECPKG_ATTR_NATIVE_NAMES, (*byte)(unsafe.Pointer(&ns)))
|
|
||||||
if ret != sspi.SEC_E_OK {
|
|
||||||
return "", ret
|
|
||||||
}
|
|
||||||
sspi.FreeContextBuffer((*byte)(unsafe.Pointer(ns.ServerName)))
|
|
||||||
defer sspi.FreeContextBuffer((*byte)(unsafe.Pointer(ns.ClientName)))
|
|
||||||
return syscall.UTF16ToString((*[2 << 20]uint16)(unsafe.Pointer(ns.ClientName))[:]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImpersonateUser changes current OS thread user. New user is
|
|
||||||
// the user as specified by client credentials.
|
|
||||||
func (c *ServerContext) ImpersonateUser() error {
|
|
||||||
return c.sctxt.ImpersonateUser()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevertToSelf stops impersonation. It changes current OS thread
|
|
||||||
// user to what it was before ImpersonateUser was executed.
|
|
||||||
func (c *ServerContext) RevertToSelf() error {
|
|
||||||
return c.sctxt.RevertToSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sizes queries the server context for the sizes used in per-message
|
|
||||||
// functions. It returns the maximum token size used in authentication
|
|
||||||
// exchanges, the maximum signature size, the preferred integral size of
|
|
||||||
// messages, the size of any security trailer, and any error.
|
|
||||||
func (c *ServerContext) Sizes() (uint32, uint32, uint32, uint32, error) {
|
|
||||||
return c.sctxt.Sizes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeSignature uses the established server context to create a signature
|
|
||||||
// for the given message using the provided quality of protection flags and
|
|
||||||
// sequence number. It returns the signature token in addition to any error.
|
|
||||||
func (c *ServerContext) MakeSignature(msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
return makeSignature(c.sctxt, msg, qop, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignature uses the established server context and signature token
|
|
||||||
// to check that the provided message hasn't been tampered or received out
|
|
||||||
// of sequence. It returns any quality of protection flags and any error
|
|
||||||
// that occurred.
|
|
||||||
func (c *ServerContext) VerifySignature(msg, token []byte, seqno uint32) (uint32, error) {
|
|
||||||
return verifySignature(c.sctxt, msg, token, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage uses the established server context to encrypt a message
|
|
||||||
// using the provided quality of protection flags and sequence number.
|
|
||||||
// It returns the signature token in addition to any error.
|
|
||||||
// IMPORTANT: the input msg parameter is updated in place by the low-level windows api
|
|
||||||
// so must be copied if the initial content should not be modified.
|
|
||||||
func (c *ServerContext) EncryptMessage(msg []byte, qop, seqno uint32) ([]byte, error) {
|
|
||||||
return encryptMessage(c.sctxt, msg, qop, seqno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage uses the established server context to decrypt a message
|
|
||||||
// using the provided sequence number.
|
|
||||||
// It returns the quality of protection flag and the decrypted message in addition to any error.
|
|
||||||
func (c *ServerContext) DecryptMessage(msg []byte, seqno uint32) (uint32, []byte, error) {
|
|
||||||
return decryptMessage(c.sctxt, msg, seqno)
|
|
||||||
}
|
|
226
vendor/github.com/alexbrainman/sspi/sspi.go
generated
vendored
226
vendor/github.com/alexbrainman/sspi/sspi.go
generated
vendored
@ -1,226 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package sspi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: add documentation
|
|
||||||
|
|
||||||
type PackageInfo struct {
|
|
||||||
Capabilities uint32
|
|
||||||
Version uint16
|
|
||||||
RPCID uint16
|
|
||||||
MaxToken uint32
|
|
||||||
Name string
|
|
||||||
Comment string
|
|
||||||
}
|
|
||||||
|
|
||||||
func QueryPackageInfo(pkgname string) (*PackageInfo, error) {
|
|
||||||
name, err := syscall.UTF16PtrFromString(pkgname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var pi *SecPkgInfo
|
|
||||||
ret := QuerySecurityPackageInfo(name, &pi)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return nil, ret
|
|
||||||
}
|
|
||||||
defer FreeContextBuffer((*byte)(unsafe.Pointer(pi)))
|
|
||||||
|
|
||||||
return &PackageInfo{
|
|
||||||
Capabilities: pi.Capabilities,
|
|
||||||
Version: pi.Version,
|
|
||||||
RPCID: pi.RPCID,
|
|
||||||
MaxToken: pi.MaxToken,
|
|
||||||
Name: syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Name))[:]),
|
|
||||||
Comment: syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Comment))[:]),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Credentials struct {
|
|
||||||
Handle CredHandle
|
|
||||||
expiry syscall.Filetime
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcquireCredentials calls the windows AcquireCredentialsHandle function and
|
|
||||||
// returns Credentials containing a security handle that can be used for
|
|
||||||
// InitializeSecurityContext or AcceptSecurityContext operations.
|
|
||||||
// As a special case, passing an empty string as the principal parameter will
|
|
||||||
// pass a null string to the underlying function.
|
|
||||||
func AcquireCredentials(principal string, pkgname string, creduse uint32, authdata *byte) (*Credentials, error) {
|
|
||||||
var principalName *uint16
|
|
||||||
if principal != "" {
|
|
||||||
var err error
|
|
||||||
principalName, err = syscall.UTF16PtrFromString(principal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name, err := syscall.UTF16PtrFromString(pkgname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var c Credentials
|
|
||||||
ret := AcquireCredentialsHandle(principalName, name, creduse, nil, authdata, 0, 0, &c.Handle, &c.expiry)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return nil, ret
|
|
||||||
}
|
|
||||||
return &c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Credentials) Release() error {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ret := FreeCredentialsHandle(&c.Handle)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Credentials) Expiry() time.Time {
|
|
||||||
return time.Unix(0, c.expiry.Nanoseconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add functions to display and manage RequestedFlags and EstablishedFlags fields.
|
|
||||||
// TODO: maybe get rid of RequestedFlags and EstablishedFlags fields, and replace them with input parameter for New...Context and return value of Update (instead of current bool parameter).
|
|
||||||
|
|
||||||
type updateFunc func(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno
|
|
||||||
|
|
||||||
type Context struct {
|
|
||||||
Cred *Credentials
|
|
||||||
Handle *CtxtHandle
|
|
||||||
handle CtxtHandle
|
|
||||||
updFn updateFunc
|
|
||||||
expiry syscall.Filetime
|
|
||||||
RequestedFlags uint32
|
|
||||||
EstablishedFlags uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClientContext(cred *Credentials, flags uint32) *Context {
|
|
||||||
return &Context{
|
|
||||||
Cred: cred,
|
|
||||||
updFn: initialize,
|
|
||||||
RequestedFlags: flags,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServerContext(cred *Credentials, flags uint32) *Context {
|
|
||||||
return &Context{
|
|
||||||
Cred: cred,
|
|
||||||
updFn: accept,
|
|
||||||
RequestedFlags: flags,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func initialize(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
|
|
||||||
return InitializeSecurityContext(&c.Cred.Handle, h, targname, c.RequestedFlags,
|
|
||||||
0, SECURITY_NATIVE_DREP, in, 0, newh, out, &c.EstablishedFlags, &c.expiry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func accept(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno {
|
|
||||||
return AcceptSecurityContext(&c.Cred.Handle, h, in, c.RequestedFlags,
|
|
||||||
SECURITY_NATIVE_DREP, newh, out, &c.EstablishedFlags, &c.expiry)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) Update(targname *uint16, out, in *SecBufferDesc) syscall.Errno {
|
|
||||||
h := c.Handle
|
|
||||||
if c.Handle == nil {
|
|
||||||
c.Handle = &c.handle
|
|
||||||
}
|
|
||||||
return c.updFn(c, targname, h, c.Handle, out, in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) Release() error {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ret := DeleteSecurityContext(c.Handle)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) Expiry() time.Time {
|
|
||||||
return time.Unix(0, c.expiry.Nanoseconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add comment to function doco that this "impersonation" is applied to current OS thread.
|
|
||||||
func (c *Context) ImpersonateUser() error {
|
|
||||||
ret := ImpersonateSecurityContext(c.Handle)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) RevertToSelf() error {
|
|
||||||
ret := RevertSecurityContext(c.Handle)
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sizes queries the context for the sizes used in per-message functions.
|
|
||||||
// It returns the maximum token size used in authentication exchanges, the
|
|
||||||
// maximum signature size, the preferred integral size of messages, the
|
|
||||||
// size of any security trailer, and any error.
|
|
||||||
func (c *Context) Sizes() (uint32, uint32, uint32, uint32, error) {
|
|
||||||
var s _SecPkgContext_Sizes
|
|
||||||
ret := QueryContextAttributes(c.Handle, _SECPKG_ATTR_SIZES, (*byte)(unsafe.Pointer(&s)))
|
|
||||||
if ret != SEC_E_OK {
|
|
||||||
return 0, 0, 0, 0, ret
|
|
||||||
}
|
|
||||||
return s.MaxToken, s.MaxSignature, s.BlockSize, s.SecurityTrailer, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyFlags determines if all flags used to construct the context
|
|
||||||
// were honored (see NewClientContext). It should be called after c.Update.
|
|
||||||
func (c *Context) VerifyFlags() error {
|
|
||||||
return c.VerifySelectiveFlags(c.RequestedFlags)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySelectiveFlags determines if the given flags were honored (see NewClientContext).
|
|
||||||
// It should be called after c.Update.
|
|
||||||
func (c *Context) VerifySelectiveFlags(flags uint32) error {
|
|
||||||
if valid, missing, extra := verifySelectiveFlags(flags, c.RequestedFlags); !valid {
|
|
||||||
return fmt.Errorf("sspi: invalid flags check: desired=%b requested=%b missing=%b extra=%b", flags, c.RequestedFlags, missing, extra)
|
|
||||||
}
|
|
||||||
if valid, missing, extra := verifySelectiveFlags(flags, c.EstablishedFlags); !valid {
|
|
||||||
return fmt.Errorf("sspi: invalid flags: desired=%b established=%b missing=%b extra=%b", flags, c.EstablishedFlags, missing, extra)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifySelectiveFlags determines if all bits requested in flags are set in establishedFlags.
|
|
||||||
// missing represents the bits set in flags that are not set in establishedFlags.
|
|
||||||
// extra represents the bits set in establishedFlags that are not set in flags.
|
|
||||||
// valid is true and missing is zero when establishedFlags has all of the requested flags.
|
|
||||||
func verifySelectiveFlags(flags, establishedFlags uint32) (valid bool, missing, extra uint32) {
|
|
||||||
missing = flags&establishedFlags ^ flags
|
|
||||||
extra = flags | establishedFlags ^ flags
|
|
||||||
valid = missing == 0
|
|
||||||
return valid, missing, extra
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSecBufferDesc returns an initialized SecBufferDesc describing the
|
|
||||||
// provided SecBuffer.
|
|
||||||
func NewSecBufferDesc(b []SecBuffer) *SecBufferDesc {
|
|
||||||
return &SecBufferDesc{
|
|
||||||
Version: SECBUFFER_VERSION,
|
|
||||||
BuffersCount: uint32(len(b)),
|
|
||||||
Buffers: &b[0],
|
|
||||||
}
|
|
||||||
}
|
|
174
vendor/github.com/alexbrainman/sspi/syscall.go
generated
vendored
174
vendor/github.com/alexbrainman/sspi/syscall.go
generated
vendored
@ -1,174 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package sspi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SEC_E_OK = syscall.Errno(0)
|
|
||||||
|
|
||||||
SEC_I_COMPLETE_AND_CONTINUE = syscall.Errno(590612)
|
|
||||||
SEC_I_COMPLETE_NEEDED = syscall.Errno(590611)
|
|
||||||
SEC_I_CONTINUE_NEEDED = syscall.Errno(590610)
|
|
||||||
|
|
||||||
SEC_E_LOGON_DENIED = syscall.Errno(0x8009030c)
|
|
||||||
SEC_E_CONTEXT_EXPIRED = syscall.Errno(0x80090317) // not sure if the value is valid
|
|
||||||
SEC_E_INCOMPLETE_MESSAGE = syscall.Errno(0x80090318)
|
|
||||||
|
|
||||||
NTLMSP_NAME = "NTLM"
|
|
||||||
MICROSOFT_KERBEROS_NAME = "Kerberos"
|
|
||||||
NEGOSSP_NAME = "Negotiate"
|
|
||||||
UNISP_NAME = "Microsoft Unified Security Protocol Provider"
|
|
||||||
|
|
||||||
_SECPKG_ATTR_SIZES = 0
|
|
||||||
_SECPKG_ATTR_NAMES = 1
|
|
||||||
_SECPKG_ATTR_LIFESPAN = 2
|
|
||||||
_SECPKG_ATTR_DCE_INFO = 3
|
|
||||||
_SECPKG_ATTR_STREAM_SIZES = 4
|
|
||||||
_SECPKG_ATTR_KEY_INFO = 5
|
|
||||||
_SECPKG_ATTR_AUTHORITY = 6
|
|
||||||
_SECPKG_ATTR_PROTO_INFO = 7
|
|
||||||
_SECPKG_ATTR_PASSWORD_EXPIRY = 8
|
|
||||||
_SECPKG_ATTR_SESSION_KEY = 9
|
|
||||||
_SECPKG_ATTR_PACKAGE_INFO = 10
|
|
||||||
_SECPKG_ATTR_USER_FLAGS = 11
|
|
||||||
_SECPKG_ATTR_NEGOTIATION_INFO = 12
|
|
||||||
_SECPKG_ATTR_NATIVE_NAMES = 13
|
|
||||||
_SECPKG_ATTR_FLAGS = 14
|
|
||||||
)
|
|
||||||
|
|
||||||
type SecPkgInfo struct {
|
|
||||||
Capabilities uint32
|
|
||||||
Version uint16
|
|
||||||
RPCID uint16
|
|
||||||
MaxToken uint32
|
|
||||||
Name *uint16
|
|
||||||
Comment *uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
type _SecPkgContext_Sizes struct {
|
|
||||||
MaxToken uint32
|
|
||||||
MaxSignature uint32
|
|
||||||
BlockSize uint32
|
|
||||||
SecurityTrailer uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys QuerySecurityPackageInfo(pkgname *uint16, pkginfo **SecPkgInfo) (ret syscall.Errno) = secur32.QuerySecurityPackageInfoW
|
|
||||||
//sys FreeContextBuffer(buf *byte) (ret syscall.Errno) = secur32.FreeContextBuffer
|
|
||||||
|
|
||||||
const (
|
|
||||||
SECPKG_CRED_INBOUND = 1
|
|
||||||
SECPKG_CRED_OUTBOUND = 2
|
|
||||||
SECPKG_CRED_BOTH = (SECPKG_CRED_OUTBOUND | SECPKG_CRED_INBOUND)
|
|
||||||
|
|
||||||
SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2
|
|
||||||
)
|
|
||||||
|
|
||||||
type SEC_WINNT_AUTH_IDENTITY struct {
|
|
||||||
User *uint16
|
|
||||||
UserLength uint32
|
|
||||||
Domain *uint16
|
|
||||||
DomainLength uint32
|
|
||||||
Password *uint16
|
|
||||||
PasswordLength uint32
|
|
||||||
Flags uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type LUID struct {
|
|
||||||
LowPart uint32
|
|
||||||
HighPart int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type CredHandle struct {
|
|
||||||
Lower uintptr
|
|
||||||
Upper uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys AcquireCredentialsHandle(principal *uint16, pkgname *uint16, creduse uint32, logonid *LUID, authdata *byte, getkeyfn uintptr, getkeyarg uintptr, handle *CredHandle, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.AcquireCredentialsHandleW
|
|
||||||
//sys FreeCredentialsHandle(handle *CredHandle) (ret syscall.Errno) = secur32.FreeCredentialsHandle
|
|
||||||
|
|
||||||
const (
|
|
||||||
SECURITY_NATIVE_DREP = 16
|
|
||||||
|
|
||||||
SECBUFFER_DATA = 1
|
|
||||||
SECBUFFER_TOKEN = 2
|
|
||||||
SECBUFFER_PKG_PARAMS = 3
|
|
||||||
SECBUFFER_MISSING = 4
|
|
||||||
SECBUFFER_EXTRA = 5
|
|
||||||
SECBUFFER_STREAM_TRAILER = 6
|
|
||||||
SECBUFFER_STREAM_HEADER = 7
|
|
||||||
SECBUFFER_PADDING = 9
|
|
||||||
SECBUFFER_STREAM = 10
|
|
||||||
SECBUFFER_READONLY = 0x80000000
|
|
||||||
SECBUFFER_ATTRMASK = 0xf0000000
|
|
||||||
SECBUFFER_VERSION = 0
|
|
||||||
SECBUFFER_EMPTY = 0
|
|
||||||
|
|
||||||
ISC_REQ_DELEGATE = 1
|
|
||||||
ISC_REQ_MUTUAL_AUTH = 2
|
|
||||||
ISC_REQ_REPLAY_DETECT = 4
|
|
||||||
ISC_REQ_SEQUENCE_DETECT = 8
|
|
||||||
ISC_REQ_CONFIDENTIALITY = 16
|
|
||||||
ISC_REQ_USE_SESSION_KEY = 32
|
|
||||||
ISC_REQ_PROMPT_FOR_CREDS = 64
|
|
||||||
ISC_REQ_USE_SUPPLIED_CREDS = 128
|
|
||||||
ISC_REQ_ALLOCATE_MEMORY = 256
|
|
||||||
ISC_REQ_USE_DCE_STYLE = 512
|
|
||||||
ISC_REQ_DATAGRAM = 1024
|
|
||||||
ISC_REQ_CONNECTION = 2048
|
|
||||||
ISC_REQ_EXTENDED_ERROR = 16384
|
|
||||||
ISC_REQ_STREAM = 32768
|
|
||||||
ISC_REQ_INTEGRITY = 65536
|
|
||||||
ISC_REQ_MANUAL_CRED_VALIDATION = 524288
|
|
||||||
ISC_REQ_HTTP = 268435456
|
|
||||||
|
|
||||||
ASC_REQ_DELEGATE = 1
|
|
||||||
ASC_REQ_MUTUAL_AUTH = 2
|
|
||||||
ASC_REQ_REPLAY_DETECT = 4
|
|
||||||
ASC_REQ_SEQUENCE_DETECT = 8
|
|
||||||
ASC_REQ_CONFIDENTIALITY = 16
|
|
||||||
ASC_REQ_USE_SESSION_KEY = 32
|
|
||||||
ASC_REQ_ALLOCATE_MEMORY = 256
|
|
||||||
ASC_REQ_USE_DCE_STYLE = 512
|
|
||||||
ASC_REQ_DATAGRAM = 1024
|
|
||||||
ASC_REQ_CONNECTION = 2048
|
|
||||||
ASC_REQ_EXTENDED_ERROR = 32768
|
|
||||||
ASC_REQ_STREAM = 65536
|
|
||||||
ASC_REQ_INTEGRITY = 131072
|
|
||||||
)
|
|
||||||
|
|
||||||
type CtxtHandle struct {
|
|
||||||
Lower uintptr
|
|
||||||
Upper uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type SecBuffer struct {
|
|
||||||
BufferSize uint32
|
|
||||||
BufferType uint32
|
|
||||||
Buffer *byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type SecBufferDesc struct {
|
|
||||||
Version uint32
|
|
||||||
BuffersCount uint32
|
|
||||||
Buffers *SecBuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys InitializeSecurityContext(credential *CredHandle, context *CtxtHandle, targname *uint16, contextreq uint32, reserved1 uint32, targdatarep uint32, input *SecBufferDesc, reserved2 uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.InitializeSecurityContextW
|
|
||||||
//sys AcceptSecurityContext(credential *CredHandle, context *CtxtHandle, input *SecBufferDesc, contextreq uint32, targdatarep uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.AcceptSecurityContext
|
|
||||||
//sys CompleteAuthToken(context *CtxtHandle, token *SecBufferDesc) (ret syscall.Errno) = secur32.CompleteAuthToken
|
|
||||||
//sys DeleteSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.DeleteSecurityContext
|
|
||||||
//sys ImpersonateSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.ImpersonateSecurityContext
|
|
||||||
//sys RevertSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.RevertSecurityContext
|
|
||||||
//sys QueryContextAttributes(context *CtxtHandle, attribute uint32, buf *byte) (ret syscall.Errno) = secur32.QueryContextAttributesW
|
|
||||||
//sys EncryptMessage(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) = secur32.EncryptMessage
|
|
||||||
//sys DecryptMessage(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) = secur32.DecryptMessage
|
|
||||||
//sys ApplyControlToken(context *CtxtHandle, input *SecBufferDesc) (ret syscall.Errno) = secur32.ApplyControlToken
|
|
||||||
//sys MakeSignature(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) = secur32.MakeSignature
|
|
||||||
//sys VerifySignature(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) = secur32.VerifySignature
|
|
152
vendor/github.com/alexbrainman/sspi/zsyscall_windows.go
generated
vendored
152
vendor/github.com/alexbrainman/sspi/zsyscall_windows.go
generated
vendored
@ -1,152 +0,0 @@
|
|||||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
|
||||||
|
|
||||||
package sspi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ unsafe.Pointer
|
|
||||||
|
|
||||||
// Do the interface allocations only once for common
|
|
||||||
// Errno values.
|
|
||||||
const (
|
|
||||||
errnoERROR_IO_PENDING = 997
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
|
||||||
)
|
|
||||||
|
|
||||||
// errnoErr returns common boxed Errno values, to prevent
|
|
||||||
// allocations at runtime.
|
|
||||||
func errnoErr(e syscall.Errno) error {
|
|
||||||
switch e {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case errnoERROR_IO_PENDING:
|
|
||||||
return errERROR_IO_PENDING
|
|
||||||
}
|
|
||||||
// TODO: add more here, after collecting data on the common
|
|
||||||
// error values see on Windows. (perhaps when running
|
|
||||||
// all.bat?)
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
modsecur32 = syscall.NewLazyDLL("secur32.dll")
|
|
||||||
|
|
||||||
procQuerySecurityPackageInfoW = modsecur32.NewProc("QuerySecurityPackageInfoW")
|
|
||||||
procFreeContextBuffer = modsecur32.NewProc("FreeContextBuffer")
|
|
||||||
procAcquireCredentialsHandleW = modsecur32.NewProc("AcquireCredentialsHandleW")
|
|
||||||
procFreeCredentialsHandle = modsecur32.NewProc("FreeCredentialsHandle")
|
|
||||||
procInitializeSecurityContextW = modsecur32.NewProc("InitializeSecurityContextW")
|
|
||||||
procAcceptSecurityContext = modsecur32.NewProc("AcceptSecurityContext")
|
|
||||||
procCompleteAuthToken = modsecur32.NewProc("CompleteAuthToken")
|
|
||||||
procDeleteSecurityContext = modsecur32.NewProc("DeleteSecurityContext")
|
|
||||||
procImpersonateSecurityContext = modsecur32.NewProc("ImpersonateSecurityContext")
|
|
||||||
procRevertSecurityContext = modsecur32.NewProc("RevertSecurityContext")
|
|
||||||
procQueryContextAttributesW = modsecur32.NewProc("QueryContextAttributesW")
|
|
||||||
procEncryptMessage = modsecur32.NewProc("EncryptMessage")
|
|
||||||
procDecryptMessage = modsecur32.NewProc("DecryptMessage")
|
|
||||||
procApplyControlToken = modsecur32.NewProc("ApplyControlToken")
|
|
||||||
procMakeSignature = modsecur32.NewProc("MakeSignature")
|
|
||||||
procVerifySignature = modsecur32.NewProc("VerifySignature")
|
|
||||||
)
|
|
||||||
|
|
||||||
func QuerySecurityPackageInfo(pkgname *uint16, pkginfo **SecPkgInfo) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procQuerySecurityPackageInfoW.Addr(), 2, uintptr(unsafe.Pointer(pkgname)), uintptr(unsafe.Pointer(pkginfo)), 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func FreeContextBuffer(buf *byte) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procFreeContextBuffer.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func AcquireCredentialsHandle(principal *uint16, pkgname *uint16, creduse uint32, logonid *LUID, authdata *byte, getkeyfn uintptr, getkeyarg uintptr, handle *CredHandle, expiry *syscall.Filetime) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall9(procAcquireCredentialsHandleW.Addr(), 9, uintptr(unsafe.Pointer(principal)), uintptr(unsafe.Pointer(pkgname)), uintptr(creduse), uintptr(unsafe.Pointer(logonid)), uintptr(unsafe.Pointer(authdata)), uintptr(getkeyfn), uintptr(getkeyarg), uintptr(unsafe.Pointer(handle)), uintptr(unsafe.Pointer(expiry)))
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func FreeCredentialsHandle(handle *CredHandle) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procFreeCredentialsHandle.Addr(), 1, uintptr(unsafe.Pointer(handle)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitializeSecurityContext(credential *CredHandle, context *CtxtHandle, targname *uint16, contextreq uint32, reserved1 uint32, targdatarep uint32, input *SecBufferDesc, reserved2 uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall12(procInitializeSecurityContextW.Addr(), 12, uintptr(unsafe.Pointer(credential)), uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(targname)), uintptr(contextreq), uintptr(reserved1), uintptr(targdatarep), uintptr(unsafe.Pointer(input)), uintptr(reserved2), uintptr(unsafe.Pointer(newcontext)), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(contextattr)), uintptr(unsafe.Pointer(expiry)))
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func AcceptSecurityContext(credential *CredHandle, context *CtxtHandle, input *SecBufferDesc, contextreq uint32, targdatarep uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall9(procAcceptSecurityContext.Addr(), 9, uintptr(unsafe.Pointer(credential)), uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(input)), uintptr(contextreq), uintptr(targdatarep), uintptr(unsafe.Pointer(newcontext)), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(contextattr)), uintptr(unsafe.Pointer(expiry)))
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func CompleteAuthToken(context *CtxtHandle, token *SecBufferDesc) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procCompleteAuthToken.Addr(), 2, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(token)), 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteSecurityContext(context *CtxtHandle) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procDeleteSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ImpersonateSecurityContext(context *CtxtHandle) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procImpersonateSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RevertSecurityContext(context *CtxtHandle) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procRevertSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func QueryContextAttributes(context *CtxtHandle, attribute uint32, buf *byte) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procQueryContextAttributesW.Addr(), 3, uintptr(unsafe.Pointer(context)), uintptr(attribute), uintptr(unsafe.Pointer(buf)))
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func EncryptMessage(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall6(procEncryptMessage.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(qop), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecryptMessage(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall6(procDecryptMessage.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), uintptr(unsafe.Pointer(qop)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ApplyControlToken(context *CtxtHandle, input *SecBufferDesc) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall(procApplyControlToken.Addr(), 2, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(input)), 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeSignature(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall6(procMakeSignature.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(qop), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func VerifySignature(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) {
|
|
||||||
r0, _, _ := syscall.Syscall6(procVerifySignature.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), uintptr(unsafe.Pointer(qop)), 0, 0)
|
|
||||||
ret = syscall.Errno(r0)
|
|
||||||
return
|
|
||||||
}
|
|
7
vendor/github.com/antchfx/htmlquery/.travis.yml
generated
vendored
7
vendor/github.com/antchfx/htmlquery/.travis.yml
generated
vendored
@ -1,15 +1,16 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.6
|
- 1.9.x
|
||||||
- 1.7
|
- 1.12.x
|
||||||
- 1.8
|
- 1.13.x
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get golang.org/x/net/html/charset
|
- go get golang.org/x/net/html/charset
|
||||||
- go get golang.org/x/net/html
|
- go get golang.org/x/net/html
|
||||||
- go get github.com/antchfx/xpath
|
- go get github.com/antchfx/xpath
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
|
- go get github.com/golang/groupcache
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
- $HOME/gopath/bin/goveralls -service=travis-ci
|
102
vendor/github.com/antchfx/htmlquery/README.md
generated
vendored
102
vendor/github.com/antchfx/htmlquery/README.md
generated
vendored
@ -8,31 +8,42 @@ htmlquery
|
|||||||
Overview
|
Overview
|
||||||
====
|
====
|
||||||
|
|
||||||
htmlquery is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression.
|
`htmlquery` is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression.
|
||||||
|
|
||||||
Changelogs
|
`htmlquery` built-in the query object caching feature based on [LRU](https://godoc.org/github.com/golang/groupcache/lru), this feature will caching the recently used XPATH query string. Enable query caching can avoid re-compile XPath expression each query.
|
||||||
===
|
|
||||||
|
|
||||||
2019-02-04
|
|
||||||
- [#7](https://github.com/antchfx/htmlquery/issues/7) Removed deprecated `FindEach()` and `FindEachWithBreak()` methods.
|
|
||||||
|
|
||||||
2018-12-28
|
|
||||||
- Avoid adding duplicate elements to list for `Find()` method. [#6](https://github.com/antchfx/htmlquery/issues/6)
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
====
|
====
|
||||||
|
|
||||||
> $ go get github.com/antchfx/htmlquery
|
```
|
||||||
|
go get github.com/antchfx/htmlquery
|
||||||
|
```
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
====
|
====
|
||||||
|
|
||||||
|
#### Query, returns matched elements or error.
|
||||||
|
|
||||||
|
```go
|
||||||
|
nodes, err := htmlquery.QueryAll(doc, "//a")
|
||||||
|
if err != nil {
|
||||||
|
panic(`not a valid XPath expression.`)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Load HTML document from URL.
|
#### Load HTML document from URL.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
doc, err := htmlquery.LoadURL("http://example.com/")
|
doc, err := htmlquery.LoadURL("http://example.com/")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Load HTML from document.
|
||||||
|
|
||||||
|
```go
|
||||||
|
filePath := "/home/user/sample.html"
|
||||||
|
doc, err := htmlquery.LoadDoc(filePath)
|
||||||
|
```
|
||||||
|
|
||||||
#### Load HTML document from string.
|
#### Load HTML document from string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -52,10 +63,13 @@ list := htmlquery.Find(doc, "//a")
|
|||||||
list := range htmlquery.Find(doc, "//a[@href]")
|
list := range htmlquery.Find(doc, "//a[@href]")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Find all A elements and only get `href` attribute self.
|
#### Find all A elements with `href` attribute and only return `href` value.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
list := range htmlquery.Find(doc, "//a/@href")
|
list := range htmlquery.Find(doc, "//a/@href")
|
||||||
|
for n := range list{
|
||||||
|
fmt.Println(htmlquery.InnerText(n)) // output @href value without A element.
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Find the third A element.
|
### Find the third A element.
|
||||||
@ -72,7 +86,55 @@ v := expr.Evaluate(htmlquery.CreateXPathNavigator(doc)).(float64)
|
|||||||
fmt.Printf("total count is %f", v)
|
fmt.Printf("total count is %f", v)
|
||||||
```
|
```
|
||||||
|
|
||||||
Quick Tutorial
|
|
||||||
|
FAQ
|
||||||
|
====
|
||||||
|
|
||||||
|
#### `Find()` vs `QueryAll()`, which is better?
|
||||||
|
|
||||||
|
`Find` and `QueryAll` both do the same things, searches all of matched html nodes.
|
||||||
|
The `Find` will panics if you give an error XPath query, but `QueryAll` will return an error for you.
|
||||||
|
|
||||||
|
#### Can I save my query expression object for the next query?
|
||||||
|
|
||||||
|
Yes, you can. We offer the `QuerySelector` and `QuerySelectorAll` methods, It will accept your query expression object.
|
||||||
|
|
||||||
|
Cache a query expression object(or reused) will avoid re-compile XPath query expression, improve your query performance.
|
||||||
|
|
||||||
|
#### XPath query object cache performance
|
||||||
|
|
||||||
|
```
|
||||||
|
goos: windows
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/antchfx/htmlquery
|
||||||
|
BenchmarkSelectorCache-4 20000000 55.2 ns/op
|
||||||
|
BenchmarkDisableSelectorCache-4 500000 3162 ns/op
|
||||||
|
```
|
||||||
|
|
||||||
|
#### How to disable caching?
|
||||||
|
|
||||||
|
```
|
||||||
|
htmlquery.DisableSelectorCache = true
|
||||||
|
```
|
||||||
|
|
||||||
|
Changelogs
|
||||||
|
===
|
||||||
|
|
||||||
|
2019-11-19
|
||||||
|
- Add built-in query object cache feature, avoid re-compilation for the same query string. [#16](https://github.com/antchfx/htmlquery/issues/16)
|
||||||
|
- Added LoadDoc [18](https://github.com/antchfx/htmlquery/pull/18)
|
||||||
|
|
||||||
|
2019-10-05
|
||||||
|
- Add new methods that compatible with invalid XPath expression error: `QueryAll` and `Query`.
|
||||||
|
- Add `QuerySelector` and `QuerySelectorAll` methods, supported reused your query object.
|
||||||
|
|
||||||
|
2019-02-04
|
||||||
|
- [#7](https://github.com/antchfx/htmlquery/issues/7) Removed deprecated `FindEach()` and `FindEachWithBreak()` methods.
|
||||||
|
|
||||||
|
2018-12-28
|
||||||
|
- Avoid adding duplicate elements to list for `Find()` method. [#6](https://github.com/antchfx/htmlquery/issues/6)
|
||||||
|
|
||||||
|
Tutorial
|
||||||
===
|
===
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -82,7 +144,11 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// Find all news item.
|
// Find all news item.
|
||||||
for i, n := range htmlquery.Find(doc, "//ol/li") {
|
list, err := htmlquery.QueryAll(doc, "//ol/li")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for i, n := range list {
|
||||||
a := htmlquery.FindOne(n, "//a")
|
a := htmlquery.FindOne(n, "//a")
|
||||||
fmt.Printf("%d %s(%s)\n", i, htmlquery.InnerText(a), htmlquery.SelectAttr(a, "href"))
|
fmt.Printf("%d %s(%s)\n", i, htmlquery.InnerText(a), htmlquery.SelectAttr(a, "href"))
|
||||||
}
|
}
|
||||||
@ -91,11 +157,11 @@ func main() {
|
|||||||
|
|
||||||
List of supported XPath query packages
|
List of supported XPath query packages
|
||||||
===
|
===
|
||||||
|Name |Description |
|
| Name | Description |
|
||||||
|--------------------------|----------------|
|
| ------------------------------------------------- | ----------------------------------------- |
|
||||||
|[htmlquery](https://github.com/antchfx/htmlquery) | XPath query package for the HTML document|
|
| [htmlquery](https://github.com/antchfx/htmlquery) | XPath query package for the HTML document |
|
||||||
|[xmlquery](https://github.com/antchfx/xmlquery) | XPath query package for the XML document|
|
| [xmlquery](https://github.com/antchfx/xmlquery) | XPath query package for the XML document |
|
||||||
|[jsonquery](https://github.com/antchfx/jsonquery) | XPath query package for the JSON document|
|
| [jsonquery](https://github.com/antchfx/jsonquery) | XPath query package for the JSON document |
|
||||||
|
|
||||||
Questions
|
Questions
|
||||||
===
|
===
|
||||||
|
42
vendor/github.com/antchfx/htmlquery/cache.go
generated
vendored
Normal file
42
vendor/github.com/antchfx/htmlquery/cache.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package htmlquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/antchfx/xpath"
|
||||||
|
"github.com/golang/groupcache/lru"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DisableSelectorCache will disable caching for the query selector if value is true.
|
||||||
|
var DisableSelectorCache = false
|
||||||
|
|
||||||
|
// SelectorCacheMaxEntries allows how many selector object can be caching. Default is 50.
|
||||||
|
// Will disable caching if SelectorCacheMaxEntries <= 0.
|
||||||
|
var SelectorCacheMaxEntries = 50
|
||||||
|
|
||||||
|
var (
|
||||||
|
cacheOnce sync.Once
|
||||||
|
cache *lru.Cache
|
||||||
|
cacheMutex sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func getQuery(expr string) (*xpath.Expr, error) {
|
||||||
|
if DisableSelectorCache || SelectorCacheMaxEntries <= 0 {
|
||||||
|
return xpath.Compile(expr)
|
||||||
|
}
|
||||||
|
cacheOnce.Do(func() {
|
||||||
|
cache = lru.New(SelectorCacheMaxEntries)
|
||||||
|
})
|
||||||
|
cacheMutex.Lock()
|
||||||
|
defer cacheMutex.Unlock()
|
||||||
|
if v, ok := cache.Get(expr); ok {
|
||||||
|
return v.(*xpath.Expr), nil
|
||||||
|
}
|
||||||
|
v, err := xpath.Compile(expr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cache.Add(expr, v)
|
||||||
|
return v, nil
|
||||||
|
|
||||||
|
}
|
9
vendor/github.com/antchfx/htmlquery/go.mod
generated
vendored
Normal file
9
vendor/github.com/antchfx/htmlquery/go.mod
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module github.com/antchfx/htmlquery
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/antchfx/xpath v1.1.6
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
|
||||||
|
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
|
||||||
|
)
|
11
vendor/github.com/antchfx/htmlquery/go.sum
generated
vendored
Normal file
11
vendor/github.com/antchfx/htmlquery/go.sum
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0=
|
||||||
|
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
|
||||||
|
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
83
vendor/github.com/antchfx/htmlquery/query.go
generated
vendored
83
vendor/github.com/antchfx/htmlquery/query.go
generated
vendored
@ -4,10 +4,12 @@ Package htmlquery provides extract data from HTML documents using XPath expressi
|
|||||||
package htmlquery
|
package htmlquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/antchfx/xpath"
|
"github.com/antchfx/xpath"
|
||||||
"golang.org/x/net/html"
|
"golang.org/x/net/html"
|
||||||
@ -21,14 +23,63 @@ func CreateXPathNavigator(top *html.Node) *NodeNavigator {
|
|||||||
return &NodeNavigator{curr: top, root: top, attr: -1}
|
return &NodeNavigator{curr: top, root: top, attr: -1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find searches the html.Node that matches by the specified XPath expr.
|
// Find is like QueryAll but Will panics if the expression `expr` cannot be parsed.
|
||||||
|
//
|
||||||
|
// See `QueryAll()` function.
|
||||||
func Find(top *html.Node, expr string) []*html.Node {
|
func Find(top *html.Node, expr string) []*html.Node {
|
||||||
exp, err := xpath.Compile(expr)
|
nodes, err := QueryAll(top, expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne is like Query but will panics if the expression `expr` cannot be parsed.
|
||||||
|
// See `Query()` function.
|
||||||
|
func FindOne(top *html.Node, expr string) *html.Node {
|
||||||
|
node, err := Query(top, expr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryAll searches the html.Node that matches by the specified XPath expr.
|
||||||
|
// Return an error if the expression `expr` cannot be parsed.
|
||||||
|
func QueryAll(top *html.Node, expr string) ([]*html.Node, error) {
|
||||||
|
exp, err := getQuery(expr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nodes := QuerySelectorAll(top, exp)
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query searches the html.Node that matches by the specified XPath expr,
|
||||||
|
// and return the first element of matched html.Node.
|
||||||
|
//
|
||||||
|
// Return an error if the expression `expr` cannot be parsed.
|
||||||
|
func Query(top *html.Node, expr string) (*html.Node, error) {
|
||||||
|
exp, err := getQuery(expr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return QuerySelector(top, exp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuerySelector returns the first matched html.Node by the specified XPath selector.
|
||||||
|
func QuerySelector(top *html.Node, selector *xpath.Expr) *html.Node {
|
||||||
|
t := selector.Select(CreateXPathNavigator(top))
|
||||||
|
if t.MoveNext() {
|
||||||
|
return getCurrentNode(t.Current().(*NodeNavigator))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuerySelectorAll searches all of the html.Node that matches the specified XPath selectors.
|
||||||
|
func QuerySelectorAll(top *html.Node, selector *xpath.Expr) []*html.Node {
|
||||||
var elems []*html.Node
|
var elems []*html.Node
|
||||||
t := exp.Select(CreateXPathNavigator(top))
|
t := selector.Select(CreateXPathNavigator(top))
|
||||||
for t.MoveNext() {
|
for t.MoveNext() {
|
||||||
nav := t.Current().(*NodeNavigator)
|
nav := t.Current().(*NodeNavigator)
|
||||||
n := getCurrentNode(nav)
|
n := getCurrentNode(nav)
|
||||||
@ -42,21 +93,6 @@ func Find(top *html.Node, expr string) []*html.Node {
|
|||||||
return elems
|
return elems
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindOne searches the html.Node that matches by the specified XPath expr,
|
|
||||||
// and returns first element of matched html.Node.
|
|
||||||
func FindOne(top *html.Node, expr string) *html.Node {
|
|
||||||
var elem *html.Node
|
|
||||||
exp, err := xpath.Compile(expr)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
t := exp.Select(CreateXPathNavigator(top))
|
|
||||||
if t.MoveNext() {
|
|
||||||
elem = getCurrentNode(t.Current().(*NodeNavigator))
|
|
||||||
}
|
|
||||||
return elem
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadURL loads the HTML document from the specified URL.
|
// LoadURL loads the HTML document from the specified URL.
|
||||||
func LoadURL(url string) (*html.Node, error) {
|
func LoadURL(url string) (*html.Node, error) {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
@ -72,6 +108,17 @@ func LoadURL(url string) (*html.Node, error) {
|
|||||||
return html.Parse(r)
|
return html.Parse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadDoc loads the HTML document from the specified file path.
|
||||||
|
func LoadDoc(path string) (*html.Node, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return html.Parse(bufio.NewReader(f))
|
||||||
|
}
|
||||||
|
|
||||||
func getCurrentNode(n *NodeNavigator) *html.Node {
|
func getCurrentNode(n *NodeNavigator) *html.Node {
|
||||||
if n.NodeType() == xpath.AttributeNode {
|
if n.NodeType() == xpath.AttributeNode {
|
||||||
childNode := &html.Node{
|
childNode := &html.Node{
|
||||||
|
6
vendor/github.com/antchfx/xpath/README.md
generated
vendored
6
vendor/github.com/antchfx/xpath/README.md
generated
vendored
@ -138,12 +138,15 @@ Supported Features
|
|||||||
`lang()`| ✗ |
|
`lang()`| ✗ |
|
||||||
`last()`| ✓ |
|
`last()`| ✓ |
|
||||||
`local-name()`| ✓ |
|
`local-name()`| ✓ |
|
||||||
|
`matches()`| ✓ |
|
||||||
`name()`| ✓ |
|
`name()`| ✓ |
|
||||||
`namespace-uri()`| ✓ |
|
`namespace-uri()`| ✓ |
|
||||||
`normalize-space()`| ✓ |
|
`normalize-space()`| ✓ |
|
||||||
`not()`| ✓ |
|
`not()`| ✓ |
|
||||||
`number()`| ✓ |
|
`number()`| ✓ |
|
||||||
`position()`| ✓ |
|
`position()`| ✓ |
|
||||||
|
`replace()`| ✓ |
|
||||||
|
`reverse()`| ✓ |
|
||||||
`round()`| ✓ |
|
`round()`| ✓ |
|
||||||
`starts-with()`| ✓ |
|
`starts-with()`| ✓ |
|
||||||
`string()`| ✓ |
|
`string()`| ✓ |
|
||||||
@ -160,6 +163,9 @@ Supported Features
|
|||||||
Changelogs
|
Changelogs
|
||||||
===
|
===
|
||||||
|
|
||||||
|
2019-03-19
|
||||||
|
- optimize XPath `|` operation performance. [#33](https://github.com/antchfx/xpath/issues/33). Tips: suggest split into multiple subquery if you have a lot of `|` operations.
|
||||||
|
|
||||||
2019-01-29
|
2019-01-29
|
||||||
- improvement `normalize-space` function. [#32](https://github.com/antchfx/xpath/issues/32)
|
- improvement `normalize-space` function. [#32](https://github.com/antchfx/xpath/issues/32)
|
||||||
|
|
||||||
|
78
vendor/github.com/antchfx/xpath/build.go
generated
vendored
78
vendor/github.com/antchfx/xpath/build.go
generated
vendored
@ -77,7 +77,18 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
|||||||
} else {
|
} else {
|
||||||
qyGrandInput = &contextQuery{}
|
qyGrandInput = &contextQuery{}
|
||||||
}
|
}
|
||||||
qyOutput = &descendantQuery{Input: qyGrandInput, Predicate: predicate, Self: true}
|
// fix #20: https://github.com/antchfx/htmlquery/issues/20
|
||||||
|
filter := func(n NodeNavigator) bool {
|
||||||
|
v := predicate(n)
|
||||||
|
switch root.Prop {
|
||||||
|
case "text":
|
||||||
|
v = v && n.NodeType() == TextNode
|
||||||
|
case "comment":
|
||||||
|
v = v && n.NodeType() == CommentNode
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
qyOutput = &descendantQuery{Input: qyGrandInput, Predicate: filter, Self: true}
|
||||||
return qyOutput, nil
|
return qyOutput, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,8 +193,23 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: containsFunc(arg1, arg2)}
|
qyOutput = &functionQuery{Input: b.firstInput, Func: containsFunc(arg1, arg2)}
|
||||||
|
case "matches":
|
||||||
|
//matches(string , pattern)
|
||||||
|
if len(root.Args) != 2 {
|
||||||
|
return nil, errors.New("xpath: matches function must have two parameters")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
arg1, arg2 query
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
qyOutput = &functionQuery{Input: b.firstInput, Func: matchesFunc(arg1, arg2)}
|
||||||
case "substring":
|
case "substring":
|
||||||
//substring( string , start [, length] )
|
//substring( string , start [, length] )
|
||||||
if len(root.Args) < 2 {
|
if len(root.Args) < 2 {
|
||||||
@ -243,6 +269,25 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: argQuery, Func: normalizespaceFunc}
|
qyOutput = &functionQuery{Input: argQuery, Func: normalizespaceFunc}
|
||||||
|
case "replace":
|
||||||
|
//replace( string , string, string )
|
||||||
|
if len(root.Args) != 3 {
|
||||||
|
return nil, errors.New("xpath: replace function must have three parameters")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
arg1, arg2, arg3 query
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if arg3, err = b.processNode(root.Args[2]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
qyOutput = &functionQuery{Input: b.firstInput, Func: replaceFunc(arg1, arg2, arg3)}
|
||||||
case "translate":
|
case "translate":
|
||||||
//translate( string , string, string )
|
//translate( string , string, string )
|
||||||
if len(root.Args) != 3 {
|
if len(root.Args) != 3 {
|
||||||
@ -272,27 +317,27 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: argQuery, Func: notFunc}
|
qyOutput = &functionQuery{Input: argQuery, Func: notFunc}
|
||||||
case "name", "local-name", "namespace-uri":
|
case "name", "local-name", "namespace-uri":
|
||||||
inp := b.firstInput
|
|
||||||
if len(root.Args) > 1 {
|
if len(root.Args) > 1 {
|
||||||
return nil, fmt.Errorf("xpath: %s function must have at most one parameter", root.FuncName)
|
return nil, fmt.Errorf("xpath: %s function must have at most one parameter", root.FuncName)
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
arg query
|
||||||
|
err error
|
||||||
|
)
|
||||||
if len(root.Args) == 1 {
|
if len(root.Args) == 1 {
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
arg, err = b.processNode(root.Args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
inp = argQuery
|
|
||||||
}
|
}
|
||||||
f := &functionQuery{Input: inp}
|
|
||||||
switch root.FuncName {
|
switch root.FuncName {
|
||||||
case "name":
|
case "name":
|
||||||
f.Func = nameFunc
|
qyOutput = &functionQuery{Input: b.firstInput, Func: nameFunc(arg)}
|
||||||
case "local-name":
|
case "local-name":
|
||||||
f.Func = localNameFunc
|
qyOutput = &functionQuery{Input: b.firstInput, Func: localNameFunc(arg)}
|
||||||
case "namespace-uri":
|
case "namespace-uri":
|
||||||
f.Func = namespaceFunc
|
qyOutput = &functionQuery{Input: b.firstInput, Func: namespaceFunc(arg)}
|
||||||
}
|
}
|
||||||
qyOutput = f
|
|
||||||
case "true", "false":
|
case "true", "false":
|
||||||
val := root.FuncName == "true"
|
val := root.FuncName == "true"
|
||||||
qyOutput = &functionQuery{
|
qyOutput = &functionQuery{
|
||||||
@ -379,6 +424,15 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
args = append(args, q)
|
args = append(args, q)
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: concatFunc(args...)}
|
qyOutput = &functionQuery{Input: b.firstInput, Func: concatFunc(args...)}
|
||||||
|
case "reverse":
|
||||||
|
if len(root.Args) == 0 {
|
||||||
|
return nil, fmt.Errorf("xpath: reverse(node-sets) function must with have parameters node-sets")
|
||||||
|
}
|
||||||
|
argQuery, err := b.processNode(root.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
qyOutput = &transformFunctionQuery{Input: argQuery, Func: reverseFunc}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("not yet support this function %s()", root.FuncName)
|
return nil, fmt.Errorf("not yet support this function %s()", root.FuncName)
|
||||||
}
|
}
|
||||||
@ -396,13 +450,15 @@ func (b *builder) processOperatorNode(root *operatorNode) (query, error) {
|
|||||||
}
|
}
|
||||||
var qyOutput query
|
var qyOutput query
|
||||||
switch root.Op {
|
switch root.Op {
|
||||||
case "+", "-", "div", "mod": // Numeric operator
|
case "+", "-", "*", "div", "mod": // Numeric operator
|
||||||
var exprFunc func(interface{}, interface{}) interface{}
|
var exprFunc func(interface{}, interface{}) interface{}
|
||||||
switch root.Op {
|
switch root.Op {
|
||||||
case "+":
|
case "+":
|
||||||
exprFunc = plusFunc
|
exprFunc = plusFunc
|
||||||
case "-":
|
case "-":
|
||||||
exprFunc = minusFunc
|
exprFunc = minusFunc
|
||||||
|
case "*":
|
||||||
|
exprFunc = mulFunc
|
||||||
case "div":
|
case "div":
|
||||||
exprFunc = divFunc
|
exprFunc = divFunc
|
||||||
case "mod":
|
case "mod":
|
||||||
|
80
vendor/github.com/antchfx/xpath/cache.go
generated
vendored
Normal file
80
vendor/github.com/antchfx/xpath/cache.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package xpath
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type loadFunc func(key interface{}) (interface{}, error)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultCap = 65536
|
||||||
|
)
|
||||||
|
|
||||||
|
// The reason we're building a simple capacity-resetting loading cache (when capacity reached) instead of using
|
||||||
|
// something like github.com/hashicorp/golang-lru is primarily due to (not wanting to create) external dependency.
|
||||||
|
// Currently this library has 0 external dep (other than go sdk), and supports go 1.6, 1.9, and 1.10 (and later).
|
||||||
|
// Creating external lib dependencies (plus their transitive dependencies) would make things hard if not impossible.
|
||||||
|
// We expect under most circumstances, the defaultCap is big enough for any long running services that use this
|
||||||
|
// library if their xpath regexp cardinality is low. However, in extreme cases when the capacity is reached, we
|
||||||
|
// simply reset the cache, taking a small subsequent perf hit (next to nothing considering amortization) in trade
|
||||||
|
// of more complex and less performant LRU type of construct.
|
||||||
|
type loadingCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
cap int
|
||||||
|
load loadFunc
|
||||||
|
m map[interface{}]interface{}
|
||||||
|
reset int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLoadingCache creates a new instance of a loading cache with capacity. Capacity must be >= 0, or
|
||||||
|
// it will panic. Capacity == 0 means the cache growth is unbounded.
|
||||||
|
func NewLoadingCache(load loadFunc, capacity int) *loadingCache {
|
||||||
|
if capacity < 0 {
|
||||||
|
panic("capacity must be >= 0")
|
||||||
|
}
|
||||||
|
return &loadingCache{cap: capacity, load: load, m: make(map[interface{}]interface{})}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *loadingCache) get(key interface{}) (interface{}, error) {
|
||||||
|
c.RLock()
|
||||||
|
v, found := c.m[key]
|
||||||
|
c.RUnlock()
|
||||||
|
if found {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
v, err := c.load(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Lock()
|
||||||
|
if c.cap > 0 && len(c.m) >= c.cap {
|
||||||
|
c.m = map[interface{}]interface{}{key: v}
|
||||||
|
c.reset++
|
||||||
|
} else {
|
||||||
|
c.m[key] = v
|
||||||
|
}
|
||||||
|
c.Unlock()
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// RegexpCache is a loading cache for string -> *regexp.Regexp mapping. It is exported so that in rare cases
|
||||||
|
// client can customize load func and/or capacity.
|
||||||
|
RegexpCache = defaultRegexpCache()
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultRegexpCache() *loadingCache {
|
||||||
|
return NewLoadingCache(
|
||||||
|
func(key interface{}) (interface{}, error) {
|
||||||
|
return regexp.Compile(key.(string))
|
||||||
|
}, defaultCap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRegexp(pattern string) (*regexp.Regexp, error) {
|
||||||
|
exp, err := RegexpCache.get(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return exp.(*regexp.Regexp), nil
|
||||||
|
}
|
252
vendor/github.com/antchfx/xpath/func.go
generated
vendored
252
vendor/github.com/antchfx/xpath/func.go
generated
vendored
@ -4,11 +4,26 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defined an interface of stringBuilder that compatible with
|
||||||
|
// strings.Builder(go 1.10) and bytes.Buffer(< go 1.10)
|
||||||
|
type stringBuilder interface {
|
||||||
|
WriteRune(r rune) (n int, err error)
|
||||||
|
WriteString(s string) (int, error)
|
||||||
|
Reset()
|
||||||
|
Grow(n int)
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
|
var builderPool = sync.Pool{New: func() interface{} {
|
||||||
|
return newStringBuilder()
|
||||||
|
}}
|
||||||
|
|
||||||
// The XPath function list.
|
// The XPath function list.
|
||||||
|
|
||||||
func predicate(q query) func(NodeNavigator) bool {
|
func predicate(q query) func(NodeNavigator) bool {
|
||||||
@ -25,7 +40,7 @@ func predicate(q query) func(NodeNavigator) bool {
|
|||||||
func positionFunc(q query, t iterator) interface{} {
|
func positionFunc(q query, t iterator) interface{} {
|
||||||
var (
|
var (
|
||||||
count = 1
|
count = 1
|
||||||
node = t.Current()
|
node = t.Current().Copy()
|
||||||
)
|
)
|
||||||
test := predicate(q)
|
test := predicate(q)
|
||||||
for node.MoveToPrevious() {
|
for node.MoveToPrevious() {
|
||||||
@ -40,7 +55,7 @@ func positionFunc(q query, t iterator) interface{} {
|
|||||||
func lastFunc(q query, t iterator) interface{} {
|
func lastFunc(q query, t iterator) interface{} {
|
||||||
var (
|
var (
|
||||||
count = 0
|
count = 0
|
||||||
node = t.Current()
|
node = t.Current().Copy()
|
||||||
)
|
)
|
||||||
node.MoveToFirst()
|
node.MoveToFirst()
|
||||||
test := predicate(q)
|
test := predicate(q)
|
||||||
@ -58,6 +73,7 @@ func lastFunc(q query, t iterator) interface{} {
|
|||||||
// countFunc is a XPath Node Set functions count(node-set).
|
// countFunc is a XPath Node Set functions count(node-set).
|
||||||
func countFunc(q query, t iterator) interface{} {
|
func countFunc(q query, t iterator) interface{} {
|
||||||
var count = 0
|
var count = 0
|
||||||
|
q = functionArgs(q)
|
||||||
test := predicate(q)
|
test := predicate(q)
|
||||||
switch typ := q.Evaluate(t).(type) {
|
switch typ := q.Evaluate(t).(type) {
|
||||||
case query:
|
case query:
|
||||||
@ -73,7 +89,7 @@ func countFunc(q query, t iterator) interface{} {
|
|||||||
// sumFunc is a XPath Node Set functions sum(node-set).
|
// sumFunc is a XPath Node Set functions sum(node-set).
|
||||||
func sumFunc(q query, t iterator) interface{} {
|
func sumFunc(q query, t iterator) interface{} {
|
||||||
var sum float64
|
var sum float64
|
||||||
switch typ := q.Evaluate(t).(type) {
|
switch typ := functionArgs(q).Evaluate(t).(type) {
|
||||||
case query:
|
case query:
|
||||||
for node := typ.Select(t); node != nil; node = typ.Select(t) {
|
for node := typ.Select(t); node != nil; node = typ.Select(t) {
|
||||||
if v, err := strconv.ParseFloat(node.Value(), 64); err == nil {
|
if v, err := strconv.ParseFloat(node.Value(), 64); err == nil {
|
||||||
@ -116,52 +132,82 @@ func asNumber(t iterator, o interface{}) float64 {
|
|||||||
|
|
||||||
// ceilingFunc is a XPath Node Set functions ceiling(node-set).
|
// ceilingFunc is a XPath Node Set functions ceiling(node-set).
|
||||||
func ceilingFunc(q query, t iterator) interface{} {
|
func ceilingFunc(q query, t iterator) interface{} {
|
||||||
val := asNumber(t, q.Evaluate(t))
|
val := asNumber(t, functionArgs(q).Evaluate(t))
|
||||||
return math.Ceil(val)
|
return math.Ceil(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// floorFunc is a XPath Node Set functions floor(node-set).
|
// floorFunc is a XPath Node Set functions floor(node-set).
|
||||||
func floorFunc(q query, t iterator) interface{} {
|
func floorFunc(q query, t iterator) interface{} {
|
||||||
val := asNumber(t, q.Evaluate(t))
|
val := asNumber(t, functionArgs(q).Evaluate(t))
|
||||||
return math.Floor(val)
|
return math.Floor(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// roundFunc is a XPath Node Set functions round(node-set).
|
// roundFunc is a XPath Node Set functions round(node-set).
|
||||||
func roundFunc(q query, t iterator) interface{} {
|
func roundFunc(q query, t iterator) interface{} {
|
||||||
val := asNumber(t, q.Evaluate(t))
|
val := asNumber(t, functionArgs(q).Evaluate(t))
|
||||||
//return math.Round(val)
|
//return math.Round(val)
|
||||||
return round(val)
|
return round(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nameFunc is a XPath functions name([node-set]).
|
// nameFunc is a XPath functions name([node-set]).
|
||||||
func nameFunc(q query, t iterator) interface{} {
|
func nameFunc(arg query) func(query, iterator) interface{} {
|
||||||
v := q.Select(t)
|
return func(q query, t iterator) interface{} {
|
||||||
if v == nil {
|
var v NodeNavigator
|
||||||
return ""
|
if arg == nil {
|
||||||
|
v = t.Current()
|
||||||
|
} else {
|
||||||
|
v = arg.Clone().Select(t)
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ns := v.Prefix()
|
||||||
|
if ns == "" {
|
||||||
|
return v.LocalName()
|
||||||
|
}
|
||||||
|
return ns + ":" + v.LocalName()
|
||||||
}
|
}
|
||||||
ns := v.Prefix()
|
|
||||||
if ns == "" {
|
|
||||||
return v.LocalName()
|
|
||||||
}
|
|
||||||
return ns + ":" + v.LocalName()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// localNameFunc is a XPath functions local-name([node-set]).
|
// localNameFunc is a XPath functions local-name([node-set]).
|
||||||
func localNameFunc(q query, t iterator) interface{} {
|
func localNameFunc(arg query) func(query, iterator) interface{} {
|
||||||
v := q.Select(t)
|
return func(q query, t iterator) interface{} {
|
||||||
if v == nil {
|
var v NodeNavigator
|
||||||
return ""
|
if arg == nil {
|
||||||
|
v = t.Current()
|
||||||
|
} else {
|
||||||
|
v = arg.Clone().Select(t)
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v.LocalName()
|
||||||
}
|
}
|
||||||
return v.LocalName()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// namespaceFunc is a XPath functions namespace-uri([node-set]).
|
// namespaceFunc is a XPath functions namespace-uri([node-set]).
|
||||||
func namespaceFunc(q query, t iterator) interface{} {
|
func namespaceFunc(arg query) func(query, iterator) interface{} {
|
||||||
v := q.Select(t)
|
return func(q query, t iterator) interface{} {
|
||||||
if v == nil {
|
var v NodeNavigator
|
||||||
return ""
|
if arg == nil {
|
||||||
|
v = t.Current()
|
||||||
|
} else {
|
||||||
|
// Get the first node in the node-set if specified.
|
||||||
|
v = arg.Clone().Select(t)
|
||||||
|
if v == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fix about namespace-uri() bug: https://github.com/antchfx/xmlquery/issues/22
|
||||||
|
// TODO: In the next version, add NamespaceURL() to the NodeNavigator interface.
|
||||||
|
type namespaceURL interface {
|
||||||
|
NamespaceURL() string
|
||||||
|
}
|
||||||
|
if f, ok := v.(namespaceURL); ok {
|
||||||
|
return f.NamespaceURL()
|
||||||
|
}
|
||||||
|
return v.Prefix()
|
||||||
}
|
}
|
||||||
return v.Prefix()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func asBool(t iterator, v interface{}) bool {
|
func asBool(t iterator, v interface{}) bool {
|
||||||
@ -171,7 +217,7 @@ func asBool(t iterator, v interface{}) bool {
|
|||||||
case *NodeIterator:
|
case *NodeIterator:
|
||||||
return v.MoveNext()
|
return v.MoveNext()
|
||||||
case bool:
|
case bool:
|
||||||
return bool(v)
|
return v
|
||||||
case float64:
|
case float64:
|
||||||
return v != 0
|
return v != 0
|
||||||
case string:
|
case string:
|
||||||
@ -209,19 +255,19 @@ func asString(t iterator, v interface{}) string {
|
|||||||
|
|
||||||
// booleanFunc is a XPath functions boolean([node-set]).
|
// booleanFunc is a XPath functions boolean([node-set]).
|
||||||
func booleanFunc(q query, t iterator) interface{} {
|
func booleanFunc(q query, t iterator) interface{} {
|
||||||
v := q.Evaluate(t)
|
v := functionArgs(q).Evaluate(t)
|
||||||
return asBool(t, v)
|
return asBool(t, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// numberFunc is a XPath functions number([node-set]).
|
// numberFunc is a XPath functions number([node-set]).
|
||||||
func numberFunc(q query, t iterator) interface{} {
|
func numberFunc(q query, t iterator) interface{} {
|
||||||
v := q.Evaluate(t)
|
v := functionArgs(q).Evaluate(t)
|
||||||
return asNumber(t, v)
|
return asNumber(t, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stringFunc is a XPath functions string([node-set]).
|
// stringFunc is a XPath functions string([node-set]).
|
||||||
func stringFunc(q query, t iterator) interface{} {
|
func stringFunc(q query, t iterator) interface{} {
|
||||||
v := q.Evaluate(t)
|
v := functionArgs(q).Evaluate(t)
|
||||||
return asString(t, v)
|
return asString(t, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +278,7 @@ func startwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
m, n string
|
m, n string
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
switch typ := arg1.Evaluate(t).(type) {
|
switch typ := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
m = typ
|
m = typ
|
||||||
case query:
|
case query:
|
||||||
@ -244,7 +290,7 @@ func startwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
default:
|
default:
|
||||||
panic(errors.New("starts-with() function argument type must be string"))
|
panic(errors.New("starts-with() function argument type must be string"))
|
||||||
}
|
}
|
||||||
n, ok = arg2.Evaluate(t).(string)
|
n, ok = functionArgs(arg2).Evaluate(t).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New("starts-with() function argument type must be string"))
|
panic(errors.New("starts-with() function argument type must be string"))
|
||||||
}
|
}
|
||||||
@ -259,7 +305,7 @@ func endwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
m, n string
|
m, n string
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
switch typ := arg1.Evaluate(t).(type) {
|
switch typ := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
m = typ
|
m = typ
|
||||||
case query:
|
case query:
|
||||||
@ -271,7 +317,7 @@ func endwithFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
default:
|
default:
|
||||||
panic(errors.New("ends-with() function argument type must be string"))
|
panic(errors.New("ends-with() function argument type must be string"))
|
||||||
}
|
}
|
||||||
n, ok = arg2.Evaluate(t).(string)
|
n, ok = functionArgs(arg2).Evaluate(t).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New("ends-with() function argument type must be string"))
|
panic(errors.New("ends-with() function argument type must be string"))
|
||||||
}
|
}
|
||||||
@ -286,8 +332,7 @@ func containsFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
m, n string
|
m, n string
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
|
switch typ := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
switch typ := arg1.Evaluate(t).(type) {
|
|
||||||
case string:
|
case string:
|
||||||
m = typ
|
m = typ
|
||||||
case query:
|
case query:
|
||||||
@ -300,7 +345,7 @@ func containsFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
panic(errors.New("contains() function argument type must be string"))
|
panic(errors.New("contains() function argument type must be string"))
|
||||||
}
|
}
|
||||||
|
|
||||||
n, ok = arg2.Evaluate(t).(string)
|
n, ok = functionArgs(arg2).Evaluate(t).(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(errors.New("contains() function argument type must be string"))
|
panic(errors.New("contains() function argument type must be string"))
|
||||||
}
|
}
|
||||||
@ -309,15 +354,39 @@ func containsFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
// matchesFunc is an XPath function that tests a given string against a regexp pattern.
|
||||||
regnewline = regexp.MustCompile(`[\r\n\t]`)
|
// Note: does not support https://www.w3.org/TR/xpath-functions-31/#func-matches 3rd optional `flags` argument; if
|
||||||
regseqspace = regexp.MustCompile(`\s{2,}`)
|
// needed, directly put flags in the regexp pattern, such as `(?i)^pattern$` for `i` flag.
|
||||||
)
|
func matchesFunc(arg1, arg2 query) func(query, iterator) interface{} {
|
||||||
|
return func(q query, t iterator) interface{} {
|
||||||
|
var s string
|
||||||
|
switch typ := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
|
case string:
|
||||||
|
s = typ
|
||||||
|
case query:
|
||||||
|
node := typ.Select(t)
|
||||||
|
if node == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
s = node.Value()
|
||||||
|
}
|
||||||
|
var pattern string
|
||||||
|
var ok bool
|
||||||
|
if pattern, ok = functionArgs(arg2).Evaluate(t).(string); !ok {
|
||||||
|
panic(errors.New("matches() function second argument type must be string"))
|
||||||
|
}
|
||||||
|
re, err := getRegexp(pattern)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("matches() function second argument is not a valid regexp pattern, err: %s", err.Error()))
|
||||||
|
}
|
||||||
|
return re.MatchString(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// normalizespaceFunc is XPath functions normalize-space(string?)
|
// normalizespaceFunc is XPath functions normalize-space(string?)
|
||||||
func normalizespaceFunc(q query, t iterator) interface{} {
|
func normalizespaceFunc(q query, t iterator) interface{} {
|
||||||
var m string
|
var m string
|
||||||
switch typ := q.Evaluate(t).(type) {
|
switch typ := functionArgs(q).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
m = typ
|
m = typ
|
||||||
case query:
|
case query:
|
||||||
@ -327,17 +396,33 @@ func normalizespaceFunc(q query, t iterator) interface{} {
|
|||||||
}
|
}
|
||||||
m = node.Value()
|
m = node.Value()
|
||||||
}
|
}
|
||||||
m = strings.TrimSpace(m)
|
var b = builderPool.Get().(stringBuilder)
|
||||||
m = regnewline.ReplaceAllString(m, " ")
|
b.Grow(len(m))
|
||||||
m = regseqspace.ReplaceAllString(m, " ")
|
|
||||||
return m
|
runeStr := []rune(strings.TrimSpace(m))
|
||||||
|
l := len(runeStr)
|
||||||
|
for i := range runeStr {
|
||||||
|
r := runeStr[i]
|
||||||
|
isSpace := unicode.IsSpace(r)
|
||||||
|
if !(isSpace && (i+1 < l && unicode.IsSpace(runeStr[i+1]))) {
|
||||||
|
if isSpace {
|
||||||
|
r = ' '
|
||||||
|
}
|
||||||
|
b.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result := b.String()
|
||||||
|
b.Reset()
|
||||||
|
builderPool.Put(b)
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// substringFunc is XPath functions substring function returns a part of a given string.
|
// substringFunc is XPath functions substring function returns a part of a given string.
|
||||||
func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
||||||
return func(q query, t iterator) interface{} {
|
return func(q query, t iterator) interface{} {
|
||||||
var m string
|
var m string
|
||||||
switch typ := arg1.Evaluate(t).(type) {
|
switch typ := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
m = typ
|
m = typ
|
||||||
case query:
|
case query:
|
||||||
@ -351,14 +436,14 @@ func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
|||||||
var start, length float64
|
var start, length float64
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if start, ok = arg2.Evaluate(t).(float64); !ok {
|
if start, ok = functionArgs(arg2).Evaluate(t).(float64); !ok {
|
||||||
panic(errors.New("substring() function first argument type must be int"))
|
panic(errors.New("substring() function first argument type must be int"))
|
||||||
} else if start < 1 {
|
} else if start < 1 {
|
||||||
panic(errors.New("substring() function first argument type must be >= 1"))
|
panic(errors.New("substring() function first argument type must be >= 1"))
|
||||||
}
|
}
|
||||||
start--
|
start--
|
||||||
if arg3 != nil {
|
if arg3 != nil {
|
||||||
if length, ok = arg3.Evaluate(t).(float64); !ok {
|
if length, ok = functionArgs(arg3).Evaluate(t).(float64); !ok {
|
||||||
panic(errors.New("substring() function second argument type must be int"))
|
panic(errors.New("substring() function second argument type must be int"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,7 +461,7 @@ func substringFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
|||||||
func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interface{} {
|
func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interface{} {
|
||||||
return func(q query, t iterator) interface{} {
|
return func(q query, t iterator) interface{} {
|
||||||
var str string
|
var str string
|
||||||
switch v := arg1.Evaluate(t).(type) {
|
switch v := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
str = v
|
str = v
|
||||||
case query:
|
case query:
|
||||||
@ -387,7 +472,7 @@ func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interf
|
|||||||
str = node.Value()
|
str = node.Value()
|
||||||
}
|
}
|
||||||
var word string
|
var word string
|
||||||
switch v := arg2.Evaluate(t).(type) {
|
switch v := functionArgs(arg2).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
word = v
|
word = v
|
||||||
case query:
|
case query:
|
||||||
@ -416,7 +501,7 @@ func substringIndFunc(arg1, arg2 query, after bool) func(query, iterator) interf
|
|||||||
// equal to the number of characters in a given string.
|
// equal to the number of characters in a given string.
|
||||||
func stringLengthFunc(arg1 query) func(query, iterator) interface{} {
|
func stringLengthFunc(arg1 query) func(query, iterator) interface{} {
|
||||||
return func(q query, t iterator) interface{} {
|
return func(q query, t iterator) interface{} {
|
||||||
switch v := arg1.Evaluate(t).(type) {
|
switch v := functionArgs(arg1).Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
return float64(len(v))
|
return float64(len(v))
|
||||||
case query:
|
case query:
|
||||||
@ -433,11 +518,11 @@ func stringLengthFunc(arg1 query) func(query, iterator) interface{} {
|
|||||||
// translateFunc is XPath functions translate() function returns a replaced string.
|
// translateFunc is XPath functions translate() function returns a replaced string.
|
||||||
func translateFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
func translateFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
||||||
return func(q query, t iterator) interface{} {
|
return func(q query, t iterator) interface{} {
|
||||||
str := asString(t, arg1.Evaluate(t))
|
str := asString(t, functionArgs(arg1).Evaluate(t))
|
||||||
src := asString(t, arg2.Evaluate(t))
|
src := asString(t, functionArgs(arg2).Evaluate(t))
|
||||||
dst := asString(t, arg3.Evaluate(t))
|
dst := asString(t, functionArgs(arg3).Evaluate(t))
|
||||||
|
|
||||||
var replace []string
|
replace := make([]string, 0, len(src))
|
||||||
for i, s := range src {
|
for i, s := range src {
|
||||||
d := ""
|
d := ""
|
||||||
if i < len(dst) {
|
if i < len(dst) {
|
||||||
@ -449,9 +534,20 @@ func translateFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replaceFunc is XPath functions replace() function returns a replaced string.
|
||||||
|
func replaceFunc(arg1, arg2, arg3 query) func(query, iterator) interface{} {
|
||||||
|
return func(q query, t iterator) interface{} {
|
||||||
|
str := asString(t, functionArgs(arg1).Evaluate(t))
|
||||||
|
src := asString(t, functionArgs(arg2).Evaluate(t))
|
||||||
|
dst := asString(t, functionArgs(arg3).Evaluate(t))
|
||||||
|
|
||||||
|
return strings.Replace(str, src, dst, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// notFunc is XPATH functions not(expression) function operation.
|
// notFunc is XPATH functions not(expression) function operation.
|
||||||
func notFunc(q query, t iterator) interface{} {
|
func notFunc(q query, t iterator) interface{} {
|
||||||
switch v := q.Evaluate(t).(type) {
|
switch v := functionArgs(q).Evaluate(t).(type) {
|
||||||
case bool:
|
case bool:
|
||||||
return !v
|
return !v
|
||||||
case query:
|
case query:
|
||||||
@ -467,18 +563,52 @@ func notFunc(q query, t iterator) interface{} {
|
|||||||
// concat( string1 , string2 [, stringn]* )
|
// concat( string1 , string2 [, stringn]* )
|
||||||
func concatFunc(args ...query) func(query, iterator) interface{} {
|
func concatFunc(args ...query) func(query, iterator) interface{} {
|
||||||
return func(q query, t iterator) interface{} {
|
return func(q query, t iterator) interface{} {
|
||||||
var a []string
|
b := builderPool.Get().(stringBuilder)
|
||||||
for _, v := range args {
|
for _, v := range args {
|
||||||
|
v = functionArgs(v)
|
||||||
|
|
||||||
switch v := v.Evaluate(t).(type) {
|
switch v := v.Evaluate(t).(type) {
|
||||||
case string:
|
case string:
|
||||||
a = append(a, v)
|
b.WriteString(v)
|
||||||
case query:
|
case query:
|
||||||
node := v.Select(t)
|
node := v.Select(t)
|
||||||
if node != nil {
|
if node != nil {
|
||||||
a = append(a, node.Value())
|
b.WriteString(node.Value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(a, "")
|
result := b.String()
|
||||||
|
b.Reset()
|
||||||
|
builderPool.Put(b)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/antchfx/xpath/issues/43
|
||||||
|
func functionArgs(q query) query {
|
||||||
|
if _, ok := q.(*functionQuery); ok {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
return q.Clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverseFunc(q query, t iterator) func() NodeNavigator {
|
||||||
|
var list []NodeNavigator
|
||||||
|
for {
|
||||||
|
node := q.Select(t)
|
||||||
|
if node == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
list = append(list, node.Copy())
|
||||||
|
}
|
||||||
|
i := len(list)
|
||||||
|
return func() NodeNavigator {
|
||||||
|
if i <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
i--
|
||||||
|
node := list[i]
|
||||||
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/antchfx/xpath/func_go110.go
generated
vendored
9
vendor/github.com/antchfx/xpath/func_go110.go
generated
vendored
@ -2,8 +2,15 @@
|
|||||||
|
|
||||||
package xpath
|
package xpath
|
||||||
|
|
||||||
import "math"
|
import (
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func round(f float64) int {
|
func round(f float64) int {
|
||||||
return int(math.Round(f))
|
return int(math.Round(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newStringBuilder() stringBuilder{
|
||||||
|
return &strings.Builder{}
|
||||||
|
}
|
||||||
|
9
vendor/github.com/antchfx/xpath/func_pre_go110.go
generated
vendored
9
vendor/github.com/antchfx/xpath/func_pre_go110.go
generated
vendored
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
package xpath
|
package xpath
|
||||||
|
|
||||||
import "math"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
// math.Round() is supported by Go 1.10+,
|
// math.Round() is supported by Go 1.10+,
|
||||||
// This method just compatible for version <1.10.
|
// This method just compatible for version <1.10.
|
||||||
@ -13,3 +16,7 @@ func round(f float64) int {
|
|||||||
}
|
}
|
||||||
return int(f + math.Copysign(0.5, f))
|
return int(f + math.Copysign(0.5, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newStringBuilder() stringBuilder {
|
||||||
|
return &bytes.Buffer{}
|
||||||
|
}
|
||||||
|
3
vendor/github.com/antchfx/xpath/go.mod
generated
vendored
Normal file
3
vendor/github.com/antchfx/xpath/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/antchfx/xpath
|
||||||
|
|
||||||
|
go 1.14
|
12
vendor/github.com/antchfx/xpath/operator.go
generated
vendored
12
vendor/github.com/antchfx/xpath/operator.go
generated
vendored
@ -163,7 +163,17 @@ func cmpNodeSetString(t iterator, op string, m, n interface{}) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cmpNodeSetNodeSet(t iterator, op string, m, n interface{}) bool {
|
func cmpNodeSetNodeSet(t iterator, op string, m, n interface{}) bool {
|
||||||
return false
|
a := m.(query)
|
||||||
|
b := n.(query)
|
||||||
|
x := a.Select(t)
|
||||||
|
if x == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
y := b.Select(t)
|
||||||
|
if y == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return cmpStringStringF(op, x.Value(), y.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmpStringNumeric(t iterator, op string, m, n interface{}) bool {
|
func cmpStringNumeric(t iterator, op string, m, n interface{}) bool {
|
||||||
|
143
vendor/github.com/antchfx/xpath/query.go
generated
vendored
143
vendor/github.com/antchfx/xpath/query.go
generated
vendored
@ -22,6 +22,17 @@ type query interface {
|
|||||||
Clone() query
|
Clone() query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nopQuery is an empty query that always return nil for any query.
|
||||||
|
type nopQuery struct {
|
||||||
|
query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nopQuery) Select(iterator) NodeNavigator { return nil }
|
||||||
|
|
||||||
|
func (nopQuery) Evaluate(iterator) interface{} { return nil }
|
||||||
|
|
||||||
|
func (nopQuery) Clone() query { return nopQuery{} }
|
||||||
|
|
||||||
// contextQuery is returns current node on the iterator object query.
|
// contextQuery is returns current node on the iterator object query.
|
||||||
type contextQuery struct {
|
type contextQuery struct {
|
||||||
count int
|
count int
|
||||||
@ -65,6 +76,7 @@ func (a *ancestorQuery) Select(t iterator) NodeNavigator {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
first := true
|
first := true
|
||||||
|
node = node.Copy()
|
||||||
a.iterator = func() NodeNavigator {
|
a.iterator = func() NodeNavigator {
|
||||||
if first && a.Self {
|
if first && a.Self {
|
||||||
first = false
|
first = false
|
||||||
@ -216,6 +228,7 @@ func (c *childQuery) position() int {
|
|||||||
type descendantQuery struct {
|
type descendantQuery struct {
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
posit int
|
posit int
|
||||||
|
level int
|
||||||
|
|
||||||
Self bool
|
Self bool
|
||||||
Input query
|
Input query
|
||||||
@ -231,32 +244,38 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
node = node.Copy()
|
node = node.Copy()
|
||||||
level := 0
|
d.level = 0
|
||||||
|
positmap := make(map[int]int)
|
||||||
first := true
|
first := true
|
||||||
d.iterator = func() NodeNavigator {
|
d.iterator = func() NodeNavigator {
|
||||||
if first && d.Self {
|
if first && d.Self {
|
||||||
first = false
|
first = false
|
||||||
if d.Predicate(node) {
|
if d.Predicate(node) {
|
||||||
|
d.posit = 1
|
||||||
|
positmap[d.level] = 1
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if node.MoveToChild() {
|
if node.MoveToChild() {
|
||||||
level++
|
d.level = d.level + 1
|
||||||
|
positmap[d.level] = 0
|
||||||
} else {
|
} else {
|
||||||
for {
|
for {
|
||||||
if level == 0 {
|
if d.level == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if node.MoveToNext() {
|
if node.MoveToNext() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
node.MoveToParent()
|
node.MoveToParent()
|
||||||
level--
|
d.level = d.level - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if d.Predicate(node) {
|
if d.Predicate(node) {
|
||||||
|
positmap[d.level]++
|
||||||
|
d.posit = positmap[d.level]
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +283,6 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if node := d.iterator(); node != nil {
|
if node := d.iterator(); node != nil {
|
||||||
d.posit++
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
d.iterator = nil
|
d.iterator = nil
|
||||||
@ -286,12 +304,17 @@ func (d *descendantQuery) position() int {
|
|||||||
return d.posit
|
return d.posit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *descendantQuery) depth() int {
|
||||||
|
return d.level
|
||||||
|
}
|
||||||
|
|
||||||
func (d *descendantQuery) Clone() query {
|
func (d *descendantQuery) Clone() query {
|
||||||
return &descendantQuery{Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate}
|
return &descendantQuery{Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
// followingQuery is an XPath following node query.(following::*|following-sibling::*)
|
// followingQuery is an XPath following node query.(following::*|following-sibling::*)
|
||||||
type followingQuery struct {
|
type followingQuery struct {
|
||||||
|
posit int
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
|
|
||||||
Input query
|
Input query
|
||||||
@ -302,6 +325,7 @@ type followingQuery struct {
|
|||||||
func (f *followingQuery) Select(t iterator) NodeNavigator {
|
func (f *followingQuery) Select(t iterator) NodeNavigator {
|
||||||
for {
|
for {
|
||||||
if f.iterator == nil {
|
if f.iterator == nil {
|
||||||
|
f.posit = 0
|
||||||
node := f.Input.Select(t)
|
node := f.Input.Select(t)
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -314,12 +338,13 @@ func (f *followingQuery) Select(t iterator) NodeNavigator {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if f.Predicate(node) {
|
if f.Predicate(node) {
|
||||||
|
f.posit++
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var q query // descendant query
|
var q *descendantQuery // descendant query
|
||||||
f.iterator = func() NodeNavigator {
|
f.iterator = func() NodeNavigator {
|
||||||
for {
|
for {
|
||||||
if q == nil {
|
if q == nil {
|
||||||
@ -336,6 +361,7 @@ func (f *followingQuery) Select(t iterator) NodeNavigator {
|
|||||||
t.Current().MoveTo(node)
|
t.Current().MoveTo(node)
|
||||||
}
|
}
|
||||||
if node := q.Select(t); node != nil {
|
if node := q.Select(t); node != nil {
|
||||||
|
f.posit = q.posit
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
q = nil
|
q = nil
|
||||||
@ -364,9 +390,14 @@ func (f *followingQuery) Clone() query {
|
|||||||
return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate}
|
return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *followingQuery) position() int {
|
||||||
|
return f.posit
|
||||||
|
}
|
||||||
|
|
||||||
// precedingQuery is an XPath preceding node query.(preceding::*)
|
// precedingQuery is an XPath preceding node query.(preceding::*)
|
||||||
type precedingQuery struct {
|
type precedingQuery struct {
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
|
posit int
|
||||||
Input query
|
Input query
|
||||||
Sibling bool // The matching sibling node of current node.
|
Sibling bool // The matching sibling node of current node.
|
||||||
Predicate func(NodeNavigator) bool
|
Predicate func(NodeNavigator) bool
|
||||||
@ -375,6 +406,7 @@ type precedingQuery struct {
|
|||||||
func (p *precedingQuery) Select(t iterator) NodeNavigator {
|
func (p *precedingQuery) Select(t iterator) NodeNavigator {
|
||||||
for {
|
for {
|
||||||
if p.iterator == nil {
|
if p.iterator == nil {
|
||||||
|
p.posit = 0
|
||||||
node := p.Input.Select(t)
|
node := p.Input.Select(t)
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -387,6 +419,7 @@ func (p *precedingQuery) Select(t iterator) NodeNavigator {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if p.Predicate(node) {
|
if p.Predicate(node) {
|
||||||
|
p.posit++
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -400,6 +433,7 @@ func (p *precedingQuery) Select(t iterator) NodeNavigator {
|
|||||||
if !node.MoveToParent() {
|
if !node.MoveToParent() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
p.posit = 0
|
||||||
}
|
}
|
||||||
q = &descendantQuery{
|
q = &descendantQuery{
|
||||||
Self: true,
|
Self: true,
|
||||||
@ -409,6 +443,7 @@ func (p *precedingQuery) Select(t iterator) NodeNavigator {
|
|||||||
t.Current().MoveTo(node)
|
t.Current().MoveTo(node)
|
||||||
}
|
}
|
||||||
if node := q.Select(t); node != nil {
|
if node := q.Select(t); node != nil {
|
||||||
|
p.posit++
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
q = nil
|
q = nil
|
||||||
@ -436,6 +471,10 @@ func (p *precedingQuery) Clone() query {
|
|||||||
return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate}
|
return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *precedingQuery) position() int {
|
||||||
|
return p.posit
|
||||||
|
}
|
||||||
|
|
||||||
// parentQuery is an XPath parent node query.(parent::*)
|
// parentQuery is an XPath parent node query.(parent::*)
|
||||||
type parentQuery struct {
|
type parentQuery struct {
|
||||||
Input query
|
Input query
|
||||||
@ -504,6 +543,8 @@ func (s *selfQuery) Clone() query {
|
|||||||
type filterQuery struct {
|
type filterQuery struct {
|
||||||
Input query
|
Input query
|
||||||
Predicate query
|
Predicate query
|
||||||
|
posit int
|
||||||
|
positmap map[int]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterQuery) do(t iterator) bool {
|
func (f *filterQuery) do(t iterator) bool {
|
||||||
@ -514,8 +555,8 @@ func (f *filterQuery) do(t iterator) bool {
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
return len(val.String()) > 0
|
return len(val.String()) > 0
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
pt := float64(getNodePosition(f.Input))
|
pt := getNodePosition(f.Input)
|
||||||
return int(val.Float()) == int(pt)
|
return int(val.Float()) == pt
|
||||||
default:
|
default:
|
||||||
if q, ok := f.Predicate.(query); ok {
|
if q, ok := f.Predicate.(query); ok {
|
||||||
return q.Select(t) != nil
|
return q.Select(t) != nil
|
||||||
@ -524,17 +565,29 @@ func (f *filterQuery) do(t iterator) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *filterQuery) position() int {
|
||||||
|
return f.posit
|
||||||
|
}
|
||||||
|
|
||||||
func (f *filterQuery) Select(t iterator) NodeNavigator {
|
func (f *filterQuery) Select(t iterator) NodeNavigator {
|
||||||
|
if f.positmap == nil {
|
||||||
|
f.positmap = make(map[int]int)
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
|
|
||||||
node := f.Input.Select(t)
|
node := f.Input.Select(t)
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
node = node.Copy()
|
node = node.Copy()
|
||||||
//fmt.Println(node.LocalName())
|
|
||||||
|
|
||||||
t.Current().MoveTo(node)
|
t.Current().MoveTo(node)
|
||||||
if f.do(t) {
|
if f.do(t) {
|
||||||
|
// fix https://github.com/antchfx/htmlquery/issues/26
|
||||||
|
// Calculate and keep the each of matching node's position in the same depth.
|
||||||
|
level := getNodeDepth(f.Input)
|
||||||
|
f.positmap[level]++
|
||||||
|
f.posit = f.positmap[level]
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,8 +602,9 @@ func (f *filterQuery) Clone() query {
|
|||||||
return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()}
|
return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// functionQuery is an XPath function that call a function to returns
|
// functionQuery is an XPath function that returns a computed value for
|
||||||
// value of current NodeNavigator node.
|
// the Evaluate call of the current NodeNavigator node. Select call isn't
|
||||||
|
// applicable for functionQuery.
|
||||||
type functionQuery struct {
|
type functionQuery struct {
|
||||||
Input query // Node Set
|
Input query // Node Set
|
||||||
Func func(query, iterator) interface{} // The xpath function.
|
Func func(query, iterator) interface{} // The xpath function.
|
||||||
@ -570,6 +624,34 @@ func (f *functionQuery) Clone() query {
|
|||||||
return &functionQuery{Input: f.Input.Clone(), Func: f.Func}
|
return &functionQuery{Input: f.Input.Clone(), Func: f.Func}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transformFunctionQuery diffs from functionQuery where the latter computes a scalar
|
||||||
|
// value (number,string,boolean) for the current NodeNavigator node while the former
|
||||||
|
// (transformFunctionQuery) performs a mapping or transform of the current NodeNavigator
|
||||||
|
// and returns a new NodeNavigator. It is used for non-scalar XPath functions such as
|
||||||
|
// reverse(), remove(), subsequence(), unordered(), etc.
|
||||||
|
type transformFunctionQuery struct {
|
||||||
|
Input query
|
||||||
|
Func func(query, iterator) func() NodeNavigator
|
||||||
|
iterator func() NodeNavigator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *transformFunctionQuery) Select(t iterator) NodeNavigator {
|
||||||
|
if f.iterator == nil {
|
||||||
|
f.iterator = f.Func(f.Input, t)
|
||||||
|
}
|
||||||
|
return f.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *transformFunctionQuery) Evaluate(t iterator) interface{} {
|
||||||
|
f.Input.Evaluate(t)
|
||||||
|
f.iterator = nil
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *transformFunctionQuery) Clone() query {
|
||||||
|
return &transformFunctionQuery{Input: f.Input.Clone(), Func: f.Func}
|
||||||
|
}
|
||||||
|
|
||||||
// constantQuery is an XPath constant operand.
|
// constantQuery is an XPath constant operand.
|
||||||
type constantQuery struct {
|
type constantQuery struct {
|
||||||
Val interface{}
|
Val interface{}
|
||||||
@ -731,7 +813,8 @@ type unionQuery struct {
|
|||||||
|
|
||||||
func (u *unionQuery) Select(t iterator) NodeNavigator {
|
func (u *unionQuery) Select(t iterator) NodeNavigator {
|
||||||
if u.iterator == nil {
|
if u.iterator == nil {
|
||||||
var m = make(map[uint64]NodeNavigator)
|
var list []NodeNavigator
|
||||||
|
var m = make(map[uint64]bool)
|
||||||
root := t.Current().Copy()
|
root := t.Current().Copy()
|
||||||
for {
|
for {
|
||||||
node := u.Left.Select(t)
|
node := u.Left.Select(t)
|
||||||
@ -740,7 +823,8 @@ func (u *unionQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
code := getHashCode(node.Copy())
|
code := getHashCode(node.Copy())
|
||||||
if _, ok := m[code]; !ok {
|
if _, ok := m[code]; !ok {
|
||||||
m[code] = node.Copy()
|
m[code] = true
|
||||||
|
list = append(list, node.Copy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Current().MoveTo(root)
|
t.Current().MoveTo(root)
|
||||||
@ -751,16 +835,11 @@ func (u *unionQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
code := getHashCode(node.Copy())
|
code := getHashCode(node.Copy())
|
||||||
if _, ok := m[code]; !ok {
|
if _, ok := m[code]; !ok {
|
||||||
m[code] = node.Copy()
|
m[code] = true
|
||||||
|
list = append(list, node.Copy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list := make([]NodeNavigator, len(m))
|
|
||||||
var i int
|
var i int
|
||||||
for _, v := range m {
|
|
||||||
list[i] = v
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i = 0
|
|
||||||
u.iterator = func() NodeNavigator {
|
u.iterator = func() NodeNavigator {
|
||||||
if i >= len(list) {
|
if i >= len(list) {
|
||||||
return nil
|
return nil
|
||||||
@ -789,8 +868,18 @@ func getHashCode(n NodeNavigator) uint64 {
|
|||||||
switch n.NodeType() {
|
switch n.NodeType() {
|
||||||
case AttributeNode, TextNode, CommentNode:
|
case AttributeNode, TextNode, CommentNode:
|
||||||
sb.WriteString(fmt.Sprintf("%s=%s", n.LocalName(), n.Value()))
|
sb.WriteString(fmt.Sprintf("%s=%s", n.LocalName(), n.Value()))
|
||||||
if n.MoveToParent() {
|
// https://github.com/antchfx/htmlquery/issues/25
|
||||||
sb.WriteString(n.LocalName())
|
d := 1
|
||||||
|
for n.MoveToPrevious() {
|
||||||
|
d++
|
||||||
|
}
|
||||||
|
sb.WriteString(fmt.Sprintf("-%d", d))
|
||||||
|
for n.MoveToParent() {
|
||||||
|
d = 1
|
||||||
|
for n.MoveToPrevious() {
|
||||||
|
d++
|
||||||
|
}
|
||||||
|
sb.WriteString(fmt.Sprintf("-%d", d))
|
||||||
}
|
}
|
||||||
case ElementNode:
|
case ElementNode:
|
||||||
sb.WriteString(n.Prefix() + n.LocalName())
|
sb.WriteString(n.Prefix() + n.LocalName())
|
||||||
@ -822,3 +911,13 @@ func getNodePosition(q query) int {
|
|||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNodeDepth(q query) int {
|
||||||
|
type Depth interface {
|
||||||
|
depth() int
|
||||||
|
}
|
||||||
|
if count, ok := q.(Depth); ok {
|
||||||
|
return count.depth()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
6
vendor/github.com/antchfx/xpath/xpath.go
generated
vendored
6
vendor/github.com/antchfx/xpath/xpath.go
generated
vendored
@ -2,6 +2,7 @@ package xpath
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeType represents a type of XPath node.
|
// NodeType represents a type of XPath node.
|
||||||
@ -144,6 +145,9 @@ func Compile(expr string) (*Expr, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if qy == nil {
|
||||||
|
return nil, fmt.Errorf(fmt.Sprintf("undeclared variable in XPath expression: %s", expr))
|
||||||
|
}
|
||||||
return &Expr{s: expr, q: qy}, nil
|
return &Expr{s: expr, q: qy}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +155,7 @@ func Compile(expr string) (*Expr, error) {
|
|||||||
func MustCompile(expr string) *Expr {
|
func MustCompile(expr string) *Expr {
|
||||||
exp, err := Compile(expr)
|
exp, err := Compile(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return &Expr{s: expr, q: nopQuery{}}
|
||||||
}
|
}
|
||||||
return exp
|
return exp
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/gobuffalo/here/dir.go
generated
vendored
9
vendor/github.com/gobuffalo/here/dir.go
generated
vendored
@ -2,6 +2,7 @@ package here
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
@ -48,7 +49,7 @@ func (h Here) Dir(p string) (Info, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return i, err
|
return i, fmt.Errorf("here.Dir: %s: %w", p, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return h.cache(i.ImportPath, func(p string) (Info, error) {
|
return h.cache(i.ImportPath, func(p string) (Info, error) {
|
||||||
@ -72,12 +73,12 @@ func fromNonGoDir(dir string) (Info, error) {
|
|||||||
if nonGoDirRx.MatchString(err.Error()) {
|
if nonGoDirRx.MatchString(err.Error()) {
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
return i, err
|
return i, fmt.Errorf("here.nonGoDir: %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &i.Module); err != nil {
|
if err := json.Unmarshal(b, &i.Module); err != nil {
|
||||||
return i, err
|
return i, fmt.Errorf("here.nonGoDir: %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return i, err
|
return i, nil
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/gobuffalo/here/go.mod
generated
vendored
8
vendor/github.com/gobuffalo/here/go.mod
generated
vendored
@ -4,8 +4,8 @@ go 1.13
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.2.0 // indirect
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.5.1
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.7 // indirect
|
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||||
)
|
)
|
||||||
|
19
vendor/github.com/gobuffalo/here/go.sum
generated
vendored
19
vendor/github.com/gobuffalo/here/go.sum
generated
vendored
@ -1,19 +1,22 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
4
vendor/github.com/gobuffalo/here/here.go
generated
vendored
4
vendor/github.com/gobuffalo/here/here.go
generated
vendored
@ -35,7 +35,7 @@ func run(n string, args ...string) ([]byte, error) {
|
|||||||
c.Stderr = ebb
|
c.Stderr = ebb
|
||||||
err := c.Run()
|
err := c.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %s", err, ebb)
|
return nil, fmt.Errorf("%v %w: %s", c.Args, err, ebb)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bb.Bytes(), nil
|
return bb.Bytes(), nil
|
||||||
@ -48,7 +48,7 @@ func (h Here) cache(p string, fn func(string) (Info, error)) (Info, error) {
|
|||||||
}
|
}
|
||||||
i, err := fn(p)
|
i, err := fn(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return i, err
|
return i, fmt.Errorf("here.cache: %s: %w", p, err)
|
||||||
}
|
}
|
||||||
h.infos.Store(p, i)
|
h.infos.Store(p, i)
|
||||||
return i, nil
|
return i, nil
|
||||||
|
1
vendor/github.com/gobuffalo/here/parse.go
generated
vendored
1
vendor/github.com/gobuffalo/here/parse.go
generated
vendored
@ -57,6 +57,7 @@ func (i Info) build(p, pkg, name string) (Path, error) {
|
|||||||
pt.Name = "/" + pt.Name
|
pt.Name = "/" + pt.Name
|
||||||
}
|
}
|
||||||
pt.Name = strings.TrimPrefix(pt.Name, i.Dir)
|
pt.Name = strings.TrimPrefix(pt.Name, i.Dir)
|
||||||
|
|
||||||
return pt, nil
|
return pt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/gobuffalo/here/pkg.go
generated
vendored
2
vendor/github.com/gobuffalo/here/pkg.go
generated
vendored
@ -32,7 +32,7 @@ func (h Here) Package(p string) (Info, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return i, err
|
return i, fmt.Errorf("here.Package: %s: %w", p, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.cache(i.Dir, func(p string) (Info, error) {
|
h.cache(i.Dir, func(p string) (Info, error) {
|
||||||
|
191
vendor/github.com/golang/groupcache/LICENSE
generated
vendored
Normal file
191
vendor/github.com/golang/groupcache/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, and
|
||||||
|
distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||||
|
owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity.
|
||||||
|
For the purposes of this definition, "control" means (i) the power, direct or
|
||||||
|
indirect, to cause the direction or management of such entity, whether by
|
||||||
|
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||||
|
permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, including
|
||||||
|
but not limited to software source code, documentation source, and configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical transformation or
|
||||||
|
translation of a Source form, including but not limited to compiled object code,
|
||||||
|
generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||||
|
available under the License, as indicated by a copyright notice that is included
|
||||||
|
in or attached to the work (an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||||
|
is based on (or derived from) the Work and for which the editorial revisions,
|
||||||
|
annotations, elaborations, or other modifications represent, as a whole, an
|
||||||
|
original work of authorship. For the purposes of this License, Derivative Works
|
||||||
|
shall not include works that remain separable from, or merely link (or bind by
|
||||||
|
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including the original version
|
||||||
|
of the Work and any modifications or additions to that Work or Derivative Works
|
||||||
|
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||||
|
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||||
|
on behalf of the copyright owner. For the purposes of this definition,
|
||||||
|
"submitted" means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems, and
|
||||||
|
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||||
|
the purpose of discussing and improving the Work, but excluding communication
|
||||||
|
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||||
|
owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||||
|
of whom a Contribution has been received by Licensor and subsequently
|
||||||
|
incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||||
|
Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable (except as stated in this section) patent license to make, have
|
||||||
|
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||||
|
such license applies only to those patent claims licensable by such Contributor
|
||||||
|
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||||
|
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||||
|
submitted. If You institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||||
|
Contribution incorporated within the Work constitutes direct or contributory
|
||||||
|
patent infringement, then any patent licenses granted to You under this License
|
||||||
|
for that Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution.
|
||||||
|
|
||||||
|
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||||
|
in any medium, with or without modifications, and in Source or Object form,
|
||||||
|
provided that You meet the following conditions:
|
||||||
|
|
||||||
|
You must give any other recipients of the Work or Derivative Works a copy of
|
||||||
|
this License; and
|
||||||
|
You must cause any modified files to carry prominent notices stating that You
|
||||||
|
changed the files; and
|
||||||
|
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||||
|
all copyright, patent, trademark, and attribution notices from the Source form
|
||||||
|
of the Work, excluding those notices that do not pertain to any part of the
|
||||||
|
Derivative Works; and
|
||||||
|
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||||
|
Derivative Works that You distribute must include a readable copy of the
|
||||||
|
attribution notices contained within such NOTICE file, excluding those notices
|
||||||
|
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||||
|
following places: within a NOTICE text file distributed as part of the
|
||||||
|
Derivative Works; within the Source form or documentation, if provided along
|
||||||
|
with the Derivative Works; or, within a display generated by the Derivative
|
||||||
|
Works, if and wherever such third-party notices normally appear. The contents of
|
||||||
|
the NOTICE file are for informational purposes only and do not modify the
|
||||||
|
License. You may add Your own attribution notices within Derivative Works that
|
||||||
|
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||||
|
provided that such additional attribution notices cannot be construed as
|
||||||
|
modifying the License.
|
||||||
|
You may add Your own copyright statement to Your modifications and may provide
|
||||||
|
additional or different license terms and conditions for use, reproduction, or
|
||||||
|
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||||
|
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||||
|
with the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions.
|
||||||
|
|
||||||
|
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||||
|
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||||
|
conditions of this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||||
|
any separate license agreement you may have executed with Licensor regarding
|
||||||
|
such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks.
|
||||||
|
|
||||||
|
This License does not grant permission to use the trade names, trademarks,
|
||||||
|
service marks, or product names of the Licensor, except as required for
|
||||||
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||||
|
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||||
|
including, without limitation, any warranties or conditions of TITLE,
|
||||||
|
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||||
|
solely responsible for determining the appropriateness of using or
|
||||||
|
redistributing the Work and assume any risks associated with Your exercise of
|
||||||
|
permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability.
|
||||||
|
|
||||||
|
In no event and under no legal theory, whether in tort (including negligence),
|
||||||
|
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||||
|
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special, incidental,
|
||||||
|
or consequential damages of any character arising as a result of this License or
|
||||||
|
out of the use or inability to use the Work (including but not limited to
|
||||||
|
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||||
|
any and all other commercial damages or losses), even if such Contributor has
|
||||||
|
been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability.
|
||||||
|
|
||||||
|
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||||
|
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||||
|
other liability obligations and/or rights consistent with this License. However,
|
||||||
|
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||||
|
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||||
|
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason of your
|
||||||
|
accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following boilerplate
|
||||||
|
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||||
|
identifying information. (Don't include the brackets!) The text should be
|
||||||
|
enclosed in the appropriate comment syntax for the file format. We also
|
||||||
|
recommend that a file or class name and description of purpose be included on
|
||||||
|
the same "printed page" as the copyright notice for easier identification within
|
||||||
|
third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
133
vendor/github.com/golang/groupcache/lru/lru.go
generated
vendored
Normal file
133
vendor/github.com/golang/groupcache/lru/lru.go
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package lru implements an LRU cache.
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import "container/list"
|
||||||
|
|
||||||
|
// Cache is an LRU cache. It is not safe for concurrent access.
|
||||||
|
type Cache struct {
|
||||||
|
// MaxEntries is the maximum number of cache entries before
|
||||||
|
// an item is evicted. Zero means no limit.
|
||||||
|
MaxEntries int
|
||||||
|
|
||||||
|
// OnEvicted optionally specifies a callback function to be
|
||||||
|
// executed when an entry is purged from the cache.
|
||||||
|
OnEvicted func(key Key, value interface{})
|
||||||
|
|
||||||
|
ll *list.List
|
||||||
|
cache map[interface{}]*list.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators
|
||||||
|
type Key interface{}
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
key Key
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Cache.
|
||||||
|
// If maxEntries is zero, the cache has no limit and it's assumed
|
||||||
|
// that eviction is done by the caller.
|
||||||
|
func New(maxEntries int) *Cache {
|
||||||
|
return &Cache{
|
||||||
|
MaxEntries: maxEntries,
|
||||||
|
ll: list.New(),
|
||||||
|
cache: make(map[interface{}]*list.Element),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a value to the cache.
|
||||||
|
func (c *Cache) Add(key Key, value interface{}) {
|
||||||
|
if c.cache == nil {
|
||||||
|
c.cache = make(map[interface{}]*list.Element)
|
||||||
|
c.ll = list.New()
|
||||||
|
}
|
||||||
|
if ee, ok := c.cache[key]; ok {
|
||||||
|
c.ll.MoveToFront(ee)
|
||||||
|
ee.Value.(*entry).value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ele := c.ll.PushFront(&entry{key, value})
|
||||||
|
c.cache[key] = ele
|
||||||
|
if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
|
||||||
|
c.RemoveOldest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get looks up a key's value from the cache.
|
||||||
|
func (c *Cache) Get(key Key) (value interface{}, ok bool) {
|
||||||
|
if c.cache == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ele, hit := c.cache[key]; hit {
|
||||||
|
c.ll.MoveToFront(ele)
|
||||||
|
return ele.Value.(*entry).value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the provided key from the cache.
|
||||||
|
func (c *Cache) Remove(key Key) {
|
||||||
|
if c.cache == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ele, hit := c.cache[key]; hit {
|
||||||
|
c.removeElement(ele)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
|
func (c *Cache) RemoveOldest() {
|
||||||
|
if c.cache == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ele := c.ll.Back()
|
||||||
|
if ele != nil {
|
||||||
|
c.removeElement(ele)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) removeElement(e *list.Element) {
|
||||||
|
c.ll.Remove(e)
|
||||||
|
kv := e.Value.(*entry)
|
||||||
|
delete(c.cache, kv.key)
|
||||||
|
if c.OnEvicted != nil {
|
||||||
|
c.OnEvicted(kv.key, kv.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of items in the cache.
|
||||||
|
func (c *Cache) Len() int {
|
||||||
|
if c.cache == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return c.ll.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear purges all stored items from the cache.
|
||||||
|
func (c *Cache) Clear() {
|
||||||
|
if c.OnEvicted != nil {
|
||||||
|
for _, e := range c.cache {
|
||||||
|
kv := e.Value.(*entry)
|
||||||
|
c.OnEvicted(kv.key, kv.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.ll = nil
|
||||||
|
c.cache = nil
|
||||||
|
}
|
2
vendor/github.com/golang/snappy/AUTHORS
generated
vendored
2
vendor/github.com/golang/snappy/AUTHORS
generated
vendored
@ -8,8 +8,10 @@
|
|||||||
|
|
||||||
# Please keep the list sorted.
|
# Please keep the list sorted.
|
||||||
|
|
||||||
|
Amazon.com, Inc
|
||||||
Damian Gryski <dgryski@gmail.com>
|
Damian Gryski <dgryski@gmail.com>
|
||||||
Google Inc.
|
Google Inc.
|
||||||
Jan Mercl <0xjnml@gmail.com>
|
Jan Mercl <0xjnml@gmail.com>
|
||||||
|
Klaus Post <klauspost@gmail.com>
|
||||||
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
Rodolfo Carvalho <rhcarvalho@gmail.com>
|
||||||
Sebastien Binet <seb.binet@gmail.com>
|
Sebastien Binet <seb.binet@gmail.com>
|
||||||
|
2
vendor/github.com/golang/snappy/CONTRIBUTORS
generated
vendored
2
vendor/github.com/golang/snappy/CONTRIBUTORS
generated
vendored
@ -28,7 +28,9 @@
|
|||||||
|
|
||||||
Damian Gryski <dgryski@gmail.com>
|
Damian Gryski <dgryski@gmail.com>
|
||||||
Jan Mercl <0xjnml@gmail.com>
|
Jan Mercl <0xjnml@gmail.com>
|
||||||
|
Jonathan Swinney <jswinney@amazon.com>
|
||||||
Kai Backman <kaib@golang.org>
|
Kai Backman <kaib@golang.org>
|
||||||
|
Klaus Post <klauspost@gmail.com>
|
||||||
Marc-Antoine Ruel <maruel@chromium.org>
|
Marc-Antoine Ruel <maruel@chromium.org>
|
||||||
Nigel Tao <nigeltao@golang.org>
|
Nigel Tao <nigeltao@golang.org>
|
||||||
Rob Pike <r@golang.org>
|
Rob Pike <r@golang.org>
|
||||||
|
4
vendor/github.com/golang/snappy/decode.go
generated
vendored
4
vendor/github.com/golang/snappy/decode.go
generated
vendored
@ -52,6 +52,8 @@ const (
|
|||||||
// Otherwise, a newly allocated slice will be returned.
|
// Otherwise, a newly allocated slice will be returned.
|
||||||
//
|
//
|
||||||
// The dst and src must not overlap. It is valid to pass a nil dst.
|
// The dst and src must not overlap. It is valid to pass a nil dst.
|
||||||
|
//
|
||||||
|
// Decode handles the Snappy block format, not the Snappy stream format.
|
||||||
func Decode(dst, src []byte) ([]byte, error) {
|
func Decode(dst, src []byte) ([]byte, error) {
|
||||||
dLen, s, err := decodedLen(src)
|
dLen, s, err := decodedLen(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -83,6 +85,8 @@ func NewReader(r io.Reader) *Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reader is an io.Reader that can read Snappy-compressed bytes.
|
// Reader is an io.Reader that can read Snappy-compressed bytes.
|
||||||
|
//
|
||||||
|
// Reader handles the Snappy stream format, not the Snappy block format.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
r io.Reader
|
r io.Reader
|
||||||
err error
|
err error
|
||||||
|
503
vendor/github.com/golang/snappy/decode_arm64.s
generated
vendored
Normal file
503
vendor/github.com/golang/snappy/decode_arm64.s
generated
vendored
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !appengine
|
||||||
|
// +build gc
|
||||||
|
// +build !noasm
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// The asm code generally follows the pure Go code in decode_other.go, except
|
||||||
|
// where marked with a "!!!".
|
||||||
|
|
||||||
|
// func decode(dst, src []byte) int
|
||||||
|
//
|
||||||
|
// All local variables fit into registers. The non-zero stack size is only to
|
||||||
|
// spill registers and push args when issuing a CALL. The register allocation:
|
||||||
|
// - R2 scratch
|
||||||
|
// - R3 scratch
|
||||||
|
// - R4 length or x
|
||||||
|
// - R5 offset
|
||||||
|
// - R6 &src[s]
|
||||||
|
// - R7 &dst[d]
|
||||||
|
// + R8 dst_base
|
||||||
|
// + R9 dst_len
|
||||||
|
// + R10 dst_base + dst_len
|
||||||
|
// + R11 src_base
|
||||||
|
// + R12 src_len
|
||||||
|
// + R13 src_base + src_len
|
||||||
|
// - R14 used by doCopy
|
||||||
|
// - R15 used by doCopy
|
||||||
|
//
|
||||||
|
// The registers R8-R13 (marked with a "+") are set at the start of the
|
||||||
|
// function, and after a CALL returns, and are not otherwise modified.
|
||||||
|
//
|
||||||
|
// The d variable is implicitly R7 - R8, and len(dst)-d is R10 - R7.
|
||||||
|
// The s variable is implicitly R6 - R11, and len(src)-s is R13 - R6.
|
||||||
|
TEXT ·decode(SB), NOSPLIT, $56-56
|
||||||
|
// Initialize R6, R7 and R8-R13.
|
||||||
|
MOVD dst_base+0(FP), R8
|
||||||
|
MOVD dst_len+8(FP), R9
|
||||||
|
MOVD R8, R7
|
||||||
|
MOVD R8, R10
|
||||||
|
ADD R9, R10, R10
|
||||||
|
MOVD src_base+24(FP), R11
|
||||||
|
MOVD src_len+32(FP), R12
|
||||||
|
MOVD R11, R6
|
||||||
|
MOVD R11, R13
|
||||||
|
ADD R12, R13, R13
|
||||||
|
|
||||||
|
loop:
|
||||||
|
// for s < len(src)
|
||||||
|
CMP R13, R6
|
||||||
|
BEQ end
|
||||||
|
|
||||||
|
// R4 = uint32(src[s])
|
||||||
|
//
|
||||||
|
// switch src[s] & 0x03
|
||||||
|
MOVBU (R6), R4
|
||||||
|
MOVW R4, R3
|
||||||
|
ANDW $3, R3
|
||||||
|
MOVW $1, R1
|
||||||
|
CMPW R1, R3
|
||||||
|
BGE tagCopy
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// The code below handles literal tags.
|
||||||
|
|
||||||
|
// case tagLiteral:
|
||||||
|
// x := uint32(src[s] >> 2)
|
||||||
|
// switch
|
||||||
|
MOVW $60, R1
|
||||||
|
ADD R4>>2, ZR, R4
|
||||||
|
CMPW R4, R1
|
||||||
|
BLS tagLit60Plus
|
||||||
|
|
||||||
|
// case x < 60:
|
||||||
|
// s++
|
||||||
|
ADD $1, R6, R6
|
||||||
|
|
||||||
|
doLit:
|
||||||
|
// This is the end of the inner "switch", when we have a literal tag.
|
||||||
|
//
|
||||||
|
// We assume that R4 == x and x fits in a uint32, where x is the variable
|
||||||
|
// used in the pure Go decode_other.go code.
|
||||||
|
|
||||||
|
// length = int(x) + 1
|
||||||
|
//
|
||||||
|
// Unlike the pure Go code, we don't need to check if length <= 0 because
|
||||||
|
// R4 can hold 64 bits, so the increment cannot overflow.
|
||||||
|
ADD $1, R4, R4
|
||||||
|
|
||||||
|
// Prepare to check if copying length bytes will run past the end of dst or
|
||||||
|
// src.
|
||||||
|
//
|
||||||
|
// R2 = len(dst) - d
|
||||||
|
// R3 = len(src) - s
|
||||||
|
MOVD R10, R2
|
||||||
|
SUB R7, R2, R2
|
||||||
|
MOVD R13, R3
|
||||||
|
SUB R6, R3, R3
|
||||||
|
|
||||||
|
// !!! Try a faster technique for short (16 or fewer bytes) copies.
|
||||||
|
//
|
||||||
|
// if length > 16 || len(dst)-d < 16 || len(src)-s < 16 {
|
||||||
|
// goto callMemmove // Fall back on calling runtime·memmove.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The C++ snappy code calls this TryFastAppend. It also checks len(src)-s
|
||||||
|
// against 21 instead of 16, because it cannot assume that all of its input
|
||||||
|
// is contiguous in memory and so it needs to leave enough source bytes to
|
||||||
|
// read the next tag without refilling buffers, but Go's Decode assumes
|
||||||
|
// contiguousness (the src argument is a []byte).
|
||||||
|
MOVD $16, R1
|
||||||
|
CMP R1, R4
|
||||||
|
BGT callMemmove
|
||||||
|
CMP R1, R2
|
||||||
|
BLT callMemmove
|
||||||
|
CMP R1, R3
|
||||||
|
BLT callMemmove
|
||||||
|
|
||||||
|
// !!! Implement the copy from src to dst as a 16-byte load and store.
|
||||||
|
// (Decode's documentation says that dst and src must not overlap.)
|
||||||
|
//
|
||||||
|
// This always copies 16 bytes, instead of only length bytes, but that's
|
||||||
|
// OK. If the input is a valid Snappy encoding then subsequent iterations
|
||||||
|
// will fix up the overrun. Otherwise, Decode returns a nil []byte (and a
|
||||||
|
// non-nil error), so the overrun will be ignored.
|
||||||
|
//
|
||||||
|
// Note that on arm64, it is legal and cheap to issue unaligned 8-byte or
|
||||||
|
// 16-byte loads and stores. This technique probably wouldn't be as
|
||||||
|
// effective on architectures that are fussier about alignment.
|
||||||
|
|
||||||
|
VLD1 0(R6), [V0.B16]
|
||||||
|
VST1 [V0.B16], 0(R7)
|
||||||
|
|
||||||
|
// d += length
|
||||||
|
// s += length
|
||||||
|
ADD R4, R7, R7
|
||||||
|
ADD R4, R6, R6
|
||||||
|
B loop
|
||||||
|
|
||||||
|
callMemmove:
|
||||||
|
// if length > len(dst)-d || length > len(src)-s { etc }
|
||||||
|
CMP R2, R4
|
||||||
|
BGT errCorrupt
|
||||||
|
CMP R3, R4
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// copy(dst[d:], src[s:s+length])
|
||||||
|
//
|
||||||
|
// This means calling runtime·memmove(&dst[d], &src[s], length), so we push
|
||||||
|
// R7, R6 and R4 as arguments. Coincidentally, we also need to spill those
|
||||||
|
// three registers to the stack, to save local variables across the CALL.
|
||||||
|
MOVD R7, 8(RSP)
|
||||||
|
MOVD R6, 16(RSP)
|
||||||
|
MOVD R4, 24(RSP)
|
||||||
|
MOVD R7, 32(RSP)
|
||||||
|
MOVD R6, 40(RSP)
|
||||||
|
MOVD R4, 48(RSP)
|
||||||
|
CALL runtime·memmove(SB)
|
||||||
|
|
||||||
|
// Restore local variables: unspill registers from the stack and
|
||||||
|
// re-calculate R8-R13.
|
||||||
|
MOVD 32(RSP), R7
|
||||||
|
MOVD 40(RSP), R6
|
||||||
|
MOVD 48(RSP), R4
|
||||||
|
MOVD dst_base+0(FP), R8
|
||||||
|
MOVD dst_len+8(FP), R9
|
||||||
|
MOVD R8, R10
|
||||||
|
ADD R9, R10, R10
|
||||||
|
MOVD src_base+24(FP), R11
|
||||||
|
MOVD src_len+32(FP), R12
|
||||||
|
MOVD R11, R13
|
||||||
|
ADD R12, R13, R13
|
||||||
|
|
||||||
|
// d += length
|
||||||
|
// s += length
|
||||||
|
ADD R4, R7, R7
|
||||||
|
ADD R4, R6, R6
|
||||||
|
B loop
|
||||||
|
|
||||||
|
tagLit60Plus:
|
||||||
|
// !!! This fragment does the
|
||||||
|
//
|
||||||
|
// s += x - 58; if uint(s) > uint(len(src)) { etc }
|
||||||
|
//
|
||||||
|
// checks. In the asm version, we code it once instead of once per switch case.
|
||||||
|
ADD R4, R6, R6
|
||||||
|
SUB $58, R6, R6
|
||||||
|
MOVD R6, R3
|
||||||
|
SUB R11, R3, R3
|
||||||
|
CMP R12, R3
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// case x == 60:
|
||||||
|
MOVW $61, R1
|
||||||
|
CMPW R1, R4
|
||||||
|
BEQ tagLit61
|
||||||
|
BGT tagLit62Plus
|
||||||
|
|
||||||
|
// x = uint32(src[s-1])
|
||||||
|
MOVBU -1(R6), R4
|
||||||
|
B doLit
|
||||||
|
|
||||||
|
tagLit61:
|
||||||
|
// case x == 61:
|
||||||
|
// x = uint32(src[s-2]) | uint32(src[s-1])<<8
|
||||||
|
MOVHU -2(R6), R4
|
||||||
|
B doLit
|
||||||
|
|
||||||
|
tagLit62Plus:
|
||||||
|
MOVW $62, R1
|
||||||
|
CMPW R1, R4
|
||||||
|
BHI tagLit63
|
||||||
|
|
||||||
|
// case x == 62:
|
||||||
|
// x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16
|
||||||
|
MOVHU -3(R6), R4
|
||||||
|
MOVBU -1(R6), R3
|
||||||
|
ORR R3<<16, R4
|
||||||
|
B doLit
|
||||||
|
|
||||||
|
tagLit63:
|
||||||
|
// case x == 63:
|
||||||
|
// x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
|
||||||
|
MOVWU -4(R6), R4
|
||||||
|
B doLit
|
||||||
|
|
||||||
|
// The code above handles literal tags.
|
||||||
|
// ----------------------------------------
|
||||||
|
// The code below handles copy tags.
|
||||||
|
|
||||||
|
tagCopy4:
|
||||||
|
// case tagCopy4:
|
||||||
|
// s += 5
|
||||||
|
ADD $5, R6, R6
|
||||||
|
|
||||||
|
// if uint(s) > uint(len(src)) { etc }
|
||||||
|
MOVD R6, R3
|
||||||
|
SUB R11, R3, R3
|
||||||
|
CMP R12, R3
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// length = 1 + int(src[s-5])>>2
|
||||||
|
MOVD $1, R1
|
||||||
|
ADD R4>>2, R1, R4
|
||||||
|
|
||||||
|
// offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24)
|
||||||
|
MOVWU -4(R6), R5
|
||||||
|
B doCopy
|
||||||
|
|
||||||
|
tagCopy2:
|
||||||
|
// case tagCopy2:
|
||||||
|
// s += 3
|
||||||
|
ADD $3, R6, R6
|
||||||
|
|
||||||
|
// if uint(s) > uint(len(src)) { etc }
|
||||||
|
MOVD R6, R3
|
||||||
|
SUB R11, R3, R3
|
||||||
|
CMP R12, R3
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// length = 1 + int(src[s-3])>>2
|
||||||
|
MOVD $1, R1
|
||||||
|
ADD R4>>2, R1, R4
|
||||||
|
|
||||||
|
// offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8)
|
||||||
|
MOVHU -2(R6), R5
|
||||||
|
B doCopy
|
||||||
|
|
||||||
|
tagCopy:
|
||||||
|
// We have a copy tag. We assume that:
|
||||||
|
// - R3 == src[s] & 0x03
|
||||||
|
// - R4 == src[s]
|
||||||
|
MOVD $2, R1
|
||||||
|
CMP R1, R3
|
||||||
|
BEQ tagCopy2
|
||||||
|
BGT tagCopy4
|
||||||
|
|
||||||
|
// case tagCopy1:
|
||||||
|
// s += 2
|
||||||
|
ADD $2, R6, R6
|
||||||
|
|
||||||
|
// if uint(s) > uint(len(src)) { etc }
|
||||||
|
MOVD R6, R3
|
||||||
|
SUB R11, R3, R3
|
||||||
|
CMP R12, R3
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]))
|
||||||
|
MOVD R4, R5
|
||||||
|
AND $0xe0, R5
|
||||||
|
MOVBU -1(R6), R3
|
||||||
|
ORR R5<<3, R3, R5
|
||||||
|
|
||||||
|
// length = 4 + int(src[s-2])>>2&0x7
|
||||||
|
MOVD $7, R1
|
||||||
|
AND R4>>2, R1, R4
|
||||||
|
ADD $4, R4, R4
|
||||||
|
|
||||||
|
doCopy:
|
||||||
|
// This is the end of the outer "switch", when we have a copy tag.
|
||||||
|
//
|
||||||
|
// We assume that:
|
||||||
|
// - R4 == length && R4 > 0
|
||||||
|
// - R5 == offset
|
||||||
|
|
||||||
|
// if offset <= 0 { etc }
|
||||||
|
MOVD $0, R1
|
||||||
|
CMP R1, R5
|
||||||
|
BLE errCorrupt
|
||||||
|
|
||||||
|
// if d < offset { etc }
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R8, R3, R3
|
||||||
|
CMP R5, R3
|
||||||
|
BLT errCorrupt
|
||||||
|
|
||||||
|
// if length > len(dst)-d { etc }
|
||||||
|
MOVD R10, R3
|
||||||
|
SUB R7, R3, R3
|
||||||
|
CMP R3, R4
|
||||||
|
BGT errCorrupt
|
||||||
|
|
||||||
|
// forwardCopy(dst[d:d+length], dst[d-offset:]); d += length
|
||||||
|
//
|
||||||
|
// Set:
|
||||||
|
// - R14 = len(dst)-d
|
||||||
|
// - R15 = &dst[d-offset]
|
||||||
|
MOVD R10, R14
|
||||||
|
SUB R7, R14, R14
|
||||||
|
MOVD R7, R15
|
||||||
|
SUB R5, R15, R15
|
||||||
|
|
||||||
|
// !!! Try a faster technique for short (16 or fewer bytes) forward copies.
|
||||||
|
//
|
||||||
|
// First, try using two 8-byte load/stores, similar to the doLit technique
|
||||||
|
// above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is
|
||||||
|
// still OK if offset >= 8. Note that this has to be two 8-byte load/stores
|
||||||
|
// and not one 16-byte load/store, and the first store has to be before the
|
||||||
|
// second load, due to the overlap if offset is in the range [8, 16).
|
||||||
|
//
|
||||||
|
// if length > 16 || offset < 8 || len(dst)-d < 16 {
|
||||||
|
// goto slowForwardCopy
|
||||||
|
// }
|
||||||
|
// copy 16 bytes
|
||||||
|
// d += length
|
||||||
|
MOVD $16, R1
|
||||||
|
MOVD $8, R0
|
||||||
|
CMP R1, R4
|
||||||
|
BGT slowForwardCopy
|
||||||
|
CMP R0, R5
|
||||||
|
BLT slowForwardCopy
|
||||||
|
CMP R1, R14
|
||||||
|
BLT slowForwardCopy
|
||||||
|
MOVD 0(R15), R2
|
||||||
|
MOVD R2, 0(R7)
|
||||||
|
MOVD 8(R15), R3
|
||||||
|
MOVD R3, 8(R7)
|
||||||
|
ADD R4, R7, R7
|
||||||
|
B loop
|
||||||
|
|
||||||
|
slowForwardCopy:
|
||||||
|
// !!! If the forward copy is longer than 16 bytes, or if offset < 8, we
|
||||||
|
// can still try 8-byte load stores, provided we can overrun up to 10 extra
|
||||||
|
// bytes. As above, the overrun will be fixed up by subsequent iterations
|
||||||
|
// of the outermost loop.
|
||||||
|
//
|
||||||
|
// The C++ snappy code calls this technique IncrementalCopyFastPath. Its
|
||||||
|
// commentary says:
|
||||||
|
//
|
||||||
|
// ----
|
||||||
|
//
|
||||||
|
// The main part of this loop is a simple copy of eight bytes at a time
|
||||||
|
// until we've copied (at least) the requested amount of bytes. However,
|
||||||
|
// if d and d-offset are less than eight bytes apart (indicating a
|
||||||
|
// repeating pattern of length < 8), we first need to expand the pattern in
|
||||||
|
// order to get the correct results. For instance, if the buffer looks like
|
||||||
|
// this, with the eight-byte <d-offset> and <d> patterns marked as
|
||||||
|
// intervals:
|
||||||
|
//
|
||||||
|
// abxxxxxxxxxxxx
|
||||||
|
// [------] d-offset
|
||||||
|
// [------] d
|
||||||
|
//
|
||||||
|
// a single eight-byte copy from <d-offset> to <d> will repeat the pattern
|
||||||
|
// once, after which we can move <d> two bytes without moving <d-offset>:
|
||||||
|
//
|
||||||
|
// ababxxxxxxxxxx
|
||||||
|
// [------] d-offset
|
||||||
|
// [------] d
|
||||||
|
//
|
||||||
|
// and repeat the exercise until the two no longer overlap.
|
||||||
|
//
|
||||||
|
// This allows us to do very well in the special case of one single byte
|
||||||
|
// repeated many times, without taking a big hit for more general cases.
|
||||||
|
//
|
||||||
|
// The worst case of extra writing past the end of the match occurs when
|
||||||
|
// offset == 1 and length == 1; the last copy will read from byte positions
|
||||||
|
// [0..7] and write to [4..11], whereas it was only supposed to write to
|
||||||
|
// position 1. Thus, ten excess bytes.
|
||||||
|
//
|
||||||
|
// ----
|
||||||
|
//
|
||||||
|
// That "10 byte overrun" worst case is confirmed by Go's
|
||||||
|
// TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy
|
||||||
|
// and finishSlowForwardCopy algorithm.
|
||||||
|
//
|
||||||
|
// if length > len(dst)-d-10 {
|
||||||
|
// goto verySlowForwardCopy
|
||||||
|
// }
|
||||||
|
SUB $10, R14, R14
|
||||||
|
CMP R14, R4
|
||||||
|
BGT verySlowForwardCopy
|
||||||
|
|
||||||
|
makeOffsetAtLeast8:
|
||||||
|
// !!! As above, expand the pattern so that offset >= 8 and we can use
|
||||||
|
// 8-byte load/stores.
|
||||||
|
//
|
||||||
|
// for offset < 8 {
|
||||||
|
// copy 8 bytes from dst[d-offset:] to dst[d:]
|
||||||
|
// length -= offset
|
||||||
|
// d += offset
|
||||||
|
// offset += offset
|
||||||
|
// // The two previous lines together means that d-offset, and therefore
|
||||||
|
// // R15, is unchanged.
|
||||||
|
// }
|
||||||
|
MOVD $8, R1
|
||||||
|
CMP R1, R5
|
||||||
|
BGE fixUpSlowForwardCopy
|
||||||
|
MOVD (R15), R3
|
||||||
|
MOVD R3, (R7)
|
||||||
|
SUB R5, R4, R4
|
||||||
|
ADD R5, R7, R7
|
||||||
|
ADD R5, R5, R5
|
||||||
|
B makeOffsetAtLeast8
|
||||||
|
|
||||||
|
fixUpSlowForwardCopy:
|
||||||
|
// !!! Add length (which might be negative now) to d (implied by R7 being
|
||||||
|
// &dst[d]) so that d ends up at the right place when we jump back to the
|
||||||
|
// top of the loop. Before we do that, though, we save R7 to R2 so that, if
|
||||||
|
// length is positive, copying the remaining length bytes will write to the
|
||||||
|
// right place.
|
||||||
|
MOVD R7, R2
|
||||||
|
ADD R4, R7, R7
|
||||||
|
|
||||||
|
finishSlowForwardCopy:
|
||||||
|
// !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative
|
||||||
|
// length means that we overrun, but as above, that will be fixed up by
|
||||||
|
// subsequent iterations of the outermost loop.
|
||||||
|
MOVD $0, R1
|
||||||
|
CMP R1, R4
|
||||||
|
BLE loop
|
||||||
|
MOVD (R15), R3
|
||||||
|
MOVD R3, (R2)
|
||||||
|
ADD $8, R15, R15
|
||||||
|
ADD $8, R2, R2
|
||||||
|
SUB $8, R4, R4
|
||||||
|
B finishSlowForwardCopy
|
||||||
|
|
||||||
|
verySlowForwardCopy:
|
||||||
|
// verySlowForwardCopy is a simple implementation of forward copy. In C
|
||||||
|
// parlance, this is a do/while loop instead of a while loop, since we know
|
||||||
|
// that length > 0. In Go syntax:
|
||||||
|
//
|
||||||
|
// for {
|
||||||
|
// dst[d] = dst[d - offset]
|
||||||
|
// d++
|
||||||
|
// length--
|
||||||
|
// if length == 0 {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
MOVB (R15), R3
|
||||||
|
MOVB R3, (R7)
|
||||||
|
ADD $1, R15, R15
|
||||||
|
ADD $1, R7, R7
|
||||||
|
SUB $1, R4, R4
|
||||||
|
MOVD $0, R1
|
||||||
|
CMP R1, R4
|
||||||
|
BNE verySlowForwardCopy
|
||||||
|
B loop
|
||||||
|
|
||||||
|
// The code above handles copy tags.
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
end:
|
||||||
|
// This is the end of the "for s < len(src)".
|
||||||
|
//
|
||||||
|
// if d != len(dst) { etc }
|
||||||
|
CMP R10, R7
|
||||||
|
BNE errCorrupt
|
||||||
|
|
||||||
|
// return 0
|
||||||
|
MOVD $0, ret+48(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
errCorrupt:
|
||||||
|
// return decodeErrCodeCorrupt
|
||||||
|
MOVD $1, R2
|
||||||
|
MOVD R2, ret+48(FP)
|
||||||
|
RET
|
@ -5,6 +5,7 @@
|
|||||||
// +build !appengine
|
// +build !appengine
|
||||||
// +build gc
|
// +build gc
|
||||||
// +build !noasm
|
// +build !noasm
|
||||||
|
// +build amd64 arm64
|
||||||
|
|
||||||
package snappy
|
package snappy
|
||||||
|
|
24
vendor/github.com/golang/snappy/decode_other.go
generated
vendored
24
vendor/github.com/golang/snappy/decode_other.go
generated
vendored
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !amd64 appengine !gc noasm
|
// +build !amd64,!arm64 appengine !gc noasm
|
||||||
|
|
||||||
package snappy
|
package snappy
|
||||||
|
|
||||||
@ -85,14 +85,28 @@ func decode(dst, src []byte) int {
|
|||||||
if offset <= 0 || d < offset || length > len(dst)-d {
|
if offset <= 0 || d < offset || length > len(dst)-d {
|
||||||
return decodeErrCodeCorrupt
|
return decodeErrCodeCorrupt
|
||||||
}
|
}
|
||||||
// Copy from an earlier sub-slice of dst to a later sub-slice. Unlike
|
// Copy from an earlier sub-slice of dst to a later sub-slice.
|
||||||
// the built-in copy function, this byte-by-byte copy always runs
|
// If no overlap, use the built-in copy:
|
||||||
|
if offset >= length {
|
||||||
|
copy(dst[d:d+length], dst[d-offset:])
|
||||||
|
d += length
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike the built-in copy function, this byte-by-byte copy always runs
|
||||||
// forwards, even if the slices overlap. Conceptually, this is:
|
// forwards, even if the slices overlap. Conceptually, this is:
|
||||||
//
|
//
|
||||||
// d += forwardCopy(dst[d:d+length], dst[d-offset:])
|
// d += forwardCopy(dst[d:d+length], dst[d-offset:])
|
||||||
for end := d + length; d != end; d++ {
|
//
|
||||||
dst[d] = dst[d-offset]
|
// We align the slices into a and b and show the compiler they are the same size.
|
||||||
|
// This allows the loop to run without bounds checks.
|
||||||
|
a := dst[d : d+length]
|
||||||
|
b := dst[d-offset:]
|
||||||
|
b = b[:len(a)]
|
||||||
|
for i := range a {
|
||||||
|
a[i] = b[i]
|
||||||
}
|
}
|
||||||
|
d += length
|
||||||
}
|
}
|
||||||
if d != len(dst) {
|
if d != len(dst) {
|
||||||
return decodeErrCodeCorrupt
|
return decodeErrCodeCorrupt
|
||||||
|
4
vendor/github.com/golang/snappy/encode.go
generated
vendored
4
vendor/github.com/golang/snappy/encode.go
generated
vendored
@ -15,6 +15,8 @@ import (
|
|||||||
// Otherwise, a newly allocated slice will be returned.
|
// Otherwise, a newly allocated slice will be returned.
|
||||||
//
|
//
|
||||||
// The dst and src must not overlap. It is valid to pass a nil dst.
|
// The dst and src must not overlap. It is valid to pass a nil dst.
|
||||||
|
//
|
||||||
|
// Encode handles the Snappy block format, not the Snappy stream format.
|
||||||
func Encode(dst, src []byte) []byte {
|
func Encode(dst, src []byte) []byte {
|
||||||
if n := MaxEncodedLen(len(src)); n < 0 {
|
if n := MaxEncodedLen(len(src)); n < 0 {
|
||||||
panic(ErrTooLarge)
|
panic(ErrTooLarge)
|
||||||
@ -139,6 +141,8 @@ func NewBufferedWriter(w io.Writer) *Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Writer is an io.Writer that can write Snappy-compressed bytes.
|
// Writer is an io.Writer that can write Snappy-compressed bytes.
|
||||||
|
//
|
||||||
|
// Writer handles the Snappy stream format, not the Snappy block format.
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
w io.Writer
|
w io.Writer
|
||||||
err error
|
err error
|
||||||
|
729
vendor/github.com/golang/snappy/encode_arm64.s
generated
vendored
Normal file
729
vendor/github.com/golang/snappy/encode_arm64.s
generated
vendored
Normal file
@ -0,0 +1,729 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !appengine
|
||||||
|
// +build gc
|
||||||
|
// +build !noasm
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// The asm code generally follows the pure Go code in encode_other.go, except
|
||||||
|
// where marked with a "!!!".
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// func emitLiteral(dst, lit []byte) int
|
||||||
|
//
|
||||||
|
// All local variables fit into registers. The register allocation:
|
||||||
|
// - R3 len(lit)
|
||||||
|
// - R4 n
|
||||||
|
// - R6 return value
|
||||||
|
// - R8 &dst[i]
|
||||||
|
// - R10 &lit[0]
|
||||||
|
//
|
||||||
|
// The 32 bytes of stack space is to call runtime·memmove.
|
||||||
|
//
|
||||||
|
// The unusual register allocation of local variables, such as R10 for the
|
||||||
|
// source pointer, matches the allocation used at the call site in encodeBlock,
|
||||||
|
// which makes it easier to manually inline this function.
|
||||||
|
TEXT ·emitLiteral(SB), NOSPLIT, $32-56
|
||||||
|
MOVD dst_base+0(FP), R8
|
||||||
|
MOVD lit_base+24(FP), R10
|
||||||
|
MOVD lit_len+32(FP), R3
|
||||||
|
MOVD R3, R6
|
||||||
|
MOVW R3, R4
|
||||||
|
SUBW $1, R4, R4
|
||||||
|
|
||||||
|
MOVW $60, R2
|
||||||
|
CMPW R2, R4
|
||||||
|
BLT oneByte
|
||||||
|
MOVW $256, R2
|
||||||
|
CMPW R2, R4
|
||||||
|
BLT twoBytes
|
||||||
|
|
||||||
|
threeBytes:
|
||||||
|
MOVD $0xf4, R2
|
||||||
|
MOVB R2, 0(R8)
|
||||||
|
MOVW R4, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
ADD $3, R6, R6
|
||||||
|
B memmove
|
||||||
|
|
||||||
|
twoBytes:
|
||||||
|
MOVD $0xf0, R2
|
||||||
|
MOVB R2, 0(R8)
|
||||||
|
MOVB R4, 1(R8)
|
||||||
|
ADD $2, R8, R8
|
||||||
|
ADD $2, R6, R6
|
||||||
|
B memmove
|
||||||
|
|
||||||
|
oneByte:
|
||||||
|
LSLW $2, R4, R4
|
||||||
|
MOVB R4, 0(R8)
|
||||||
|
ADD $1, R8, R8
|
||||||
|
ADD $1, R6, R6
|
||||||
|
|
||||||
|
memmove:
|
||||||
|
MOVD R6, ret+48(FP)
|
||||||
|
|
||||||
|
// copy(dst[i:], lit)
|
||||||
|
//
|
||||||
|
// This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push
|
||||||
|
// R8, R10 and R3 as arguments.
|
||||||
|
MOVD R8, 8(RSP)
|
||||||
|
MOVD R10, 16(RSP)
|
||||||
|
MOVD R3, 24(RSP)
|
||||||
|
CALL runtime·memmove(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// func emitCopy(dst []byte, offset, length int) int
|
||||||
|
//
|
||||||
|
// All local variables fit into registers. The register allocation:
|
||||||
|
// - R3 length
|
||||||
|
// - R7 &dst[0]
|
||||||
|
// - R8 &dst[i]
|
||||||
|
// - R11 offset
|
||||||
|
//
|
||||||
|
// The unusual register allocation of local variables, such as R11 for the
|
||||||
|
// offset, matches the allocation used at the call site in encodeBlock, which
|
||||||
|
// makes it easier to manually inline this function.
|
||||||
|
TEXT ·emitCopy(SB), NOSPLIT, $0-48
|
||||||
|
MOVD dst_base+0(FP), R8
|
||||||
|
MOVD R8, R7
|
||||||
|
MOVD offset+24(FP), R11
|
||||||
|
MOVD length+32(FP), R3
|
||||||
|
|
||||||
|
loop0:
|
||||||
|
// for length >= 68 { etc }
|
||||||
|
MOVW $68, R2
|
||||||
|
CMPW R2, R3
|
||||||
|
BLT step1
|
||||||
|
|
||||||
|
// Emit a length 64 copy, encoded as 3 bytes.
|
||||||
|
MOVD $0xfe, R2
|
||||||
|
MOVB R2, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
SUB $64, R3, R3
|
||||||
|
B loop0
|
||||||
|
|
||||||
|
step1:
|
||||||
|
// if length > 64 { etc }
|
||||||
|
MOVD $64, R2
|
||||||
|
CMP R2, R3
|
||||||
|
BLE step2
|
||||||
|
|
||||||
|
// Emit a length 60 copy, encoded as 3 bytes.
|
||||||
|
MOVD $0xee, R2
|
||||||
|
MOVB R2, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
SUB $60, R3, R3
|
||||||
|
|
||||||
|
step2:
|
||||||
|
// if length >= 12 || offset >= 2048 { goto step3 }
|
||||||
|
MOVD $12, R2
|
||||||
|
CMP R2, R3
|
||||||
|
BGE step3
|
||||||
|
MOVW $2048, R2
|
||||||
|
CMPW R2, R11
|
||||||
|
BGE step3
|
||||||
|
|
||||||
|
// Emit the remaining copy, encoded as 2 bytes.
|
||||||
|
MOVB R11, 1(R8)
|
||||||
|
LSRW $3, R11, R11
|
||||||
|
AND $0xe0, R11, R11
|
||||||
|
SUB $4, R3, R3
|
||||||
|
LSLW $2, R3
|
||||||
|
AND $0xff, R3, R3
|
||||||
|
ORRW R3, R11, R11
|
||||||
|
ORRW $1, R11, R11
|
||||||
|
MOVB R11, 0(R8)
|
||||||
|
ADD $2, R8, R8
|
||||||
|
|
||||||
|
// Return the number of bytes written.
|
||||||
|
SUB R7, R8, R8
|
||||||
|
MOVD R8, ret+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
step3:
|
||||||
|
// Emit the remaining copy, encoded as 3 bytes.
|
||||||
|
SUB $1, R3, R3
|
||||||
|
AND $0xff, R3, R3
|
||||||
|
LSLW $2, R3, R3
|
||||||
|
ORRW $2, R3, R3
|
||||||
|
MOVB R3, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
|
||||||
|
// Return the number of bytes written.
|
||||||
|
SUB R7, R8, R8
|
||||||
|
MOVD R8, ret+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// func extendMatch(src []byte, i, j int) int
|
||||||
|
//
|
||||||
|
// All local variables fit into registers. The register allocation:
|
||||||
|
// - R6 &src[0]
|
||||||
|
// - R7 &src[j]
|
||||||
|
// - R13 &src[len(src) - 8]
|
||||||
|
// - R14 &src[len(src)]
|
||||||
|
// - R15 &src[i]
|
||||||
|
//
|
||||||
|
// The unusual register allocation of local variables, such as R15 for a source
|
||||||
|
// pointer, matches the allocation used at the call site in encodeBlock, which
|
||||||
|
// makes it easier to manually inline this function.
|
||||||
|
TEXT ·extendMatch(SB), NOSPLIT, $0-48
|
||||||
|
MOVD src_base+0(FP), R6
|
||||||
|
MOVD src_len+8(FP), R14
|
||||||
|
MOVD i+24(FP), R15
|
||||||
|
MOVD j+32(FP), R7
|
||||||
|
ADD R6, R14, R14
|
||||||
|
ADD R6, R15, R15
|
||||||
|
ADD R6, R7, R7
|
||||||
|
MOVD R14, R13
|
||||||
|
SUB $8, R13, R13
|
||||||
|
|
||||||
|
cmp8:
|
||||||
|
// As long as we are 8 or more bytes before the end of src, we can load and
|
||||||
|
// compare 8 bytes at a time. If those 8 bytes are equal, repeat.
|
||||||
|
CMP R13, R7
|
||||||
|
BHI cmp1
|
||||||
|
MOVD (R15), R3
|
||||||
|
MOVD (R7), R4
|
||||||
|
CMP R4, R3
|
||||||
|
BNE bsf
|
||||||
|
ADD $8, R15, R15
|
||||||
|
ADD $8, R7, R7
|
||||||
|
B cmp8
|
||||||
|
|
||||||
|
bsf:
|
||||||
|
// If those 8 bytes were not equal, XOR the two 8 byte values, and return
|
||||||
|
// the index of the first byte that differs.
|
||||||
|
// RBIT reverses the bit order, then CLZ counts the leading zeros, the
|
||||||
|
// combination of which finds the least significant bit which is set.
|
||||||
|
// The arm64 architecture is little-endian, and the shift by 3 converts
|
||||||
|
// a bit index to a byte index.
|
||||||
|
EOR R3, R4, R4
|
||||||
|
RBIT R4, R4
|
||||||
|
CLZ R4, R4
|
||||||
|
ADD R4>>3, R7, R7
|
||||||
|
|
||||||
|
// Convert from &src[ret] to ret.
|
||||||
|
SUB R6, R7, R7
|
||||||
|
MOVD R7, ret+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
cmp1:
|
||||||
|
// In src's tail, compare 1 byte at a time.
|
||||||
|
CMP R7, R14
|
||||||
|
BLS extendMatchEnd
|
||||||
|
MOVB (R15), R3
|
||||||
|
MOVB (R7), R4
|
||||||
|
CMP R4, R3
|
||||||
|
BNE extendMatchEnd
|
||||||
|
ADD $1, R15, R15
|
||||||
|
ADD $1, R7, R7
|
||||||
|
B cmp1
|
||||||
|
|
||||||
|
extendMatchEnd:
|
||||||
|
// Convert from &src[ret] to ret.
|
||||||
|
SUB R6, R7, R7
|
||||||
|
MOVD R7, ret+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// func encodeBlock(dst, src []byte) (d int)
|
||||||
|
//
|
||||||
|
// All local variables fit into registers, other than "var table". The register
|
||||||
|
// allocation:
|
||||||
|
// - R3 . .
|
||||||
|
// - R4 . .
|
||||||
|
// - R5 64 shift
|
||||||
|
// - R6 72 &src[0], tableSize
|
||||||
|
// - R7 80 &src[s]
|
||||||
|
// - R8 88 &dst[d]
|
||||||
|
// - R9 96 sLimit
|
||||||
|
// - R10 . &src[nextEmit]
|
||||||
|
// - R11 104 prevHash, currHash, nextHash, offset
|
||||||
|
// - R12 112 &src[base], skip
|
||||||
|
// - R13 . &src[nextS], &src[len(src) - 8]
|
||||||
|
// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x
|
||||||
|
// - R15 120 candidate
|
||||||
|
// - R16 . hash constant, 0x1e35a7bd
|
||||||
|
// - R17 . &table
|
||||||
|
// - . 128 table
|
||||||
|
//
|
||||||
|
// The second column (64, 72, etc) is the stack offset to spill the registers
|
||||||
|
// when calling other functions. We could pack this slightly tighter, but it's
|
||||||
|
// simpler to have a dedicated spill map independent of the function called.
|
||||||
|
//
|
||||||
|
// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An
|
||||||
|
// extra 64 bytes, to call other functions, and an extra 64 bytes, to spill
|
||||||
|
// local variables (registers) during calls gives 32768 + 64 + 64 = 32896.
|
||||||
|
TEXT ·encodeBlock(SB), 0, $32896-56
|
||||||
|
MOVD dst_base+0(FP), R8
|
||||||
|
MOVD src_base+24(FP), R7
|
||||||
|
MOVD src_len+32(FP), R14
|
||||||
|
|
||||||
|
// shift, tableSize := uint32(32-8), 1<<8
|
||||||
|
MOVD $24, R5
|
||||||
|
MOVD $256, R6
|
||||||
|
MOVW $0xa7bd, R16
|
||||||
|
MOVKW $(0x1e35<<16), R16
|
||||||
|
|
||||||
|
calcShift:
|
||||||
|
// for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 {
|
||||||
|
// shift--
|
||||||
|
// }
|
||||||
|
MOVD $16384, R2
|
||||||
|
CMP R2, R6
|
||||||
|
BGE varTable
|
||||||
|
CMP R14, R6
|
||||||
|
BGE varTable
|
||||||
|
SUB $1, R5, R5
|
||||||
|
LSL $1, R6, R6
|
||||||
|
B calcShift
|
||||||
|
|
||||||
|
varTable:
|
||||||
|
// var table [maxTableSize]uint16
|
||||||
|
//
|
||||||
|
// In the asm code, unlike the Go code, we can zero-initialize only the
|
||||||
|
// first tableSize elements. Each uint16 element is 2 bytes and each VST1
|
||||||
|
// writes 64 bytes, so we can do only tableSize/32 writes instead of the
|
||||||
|
// 2048 writes that would zero-initialize all of table's 32768 bytes.
|
||||||
|
// This clear could overrun the first tableSize elements, but it won't
|
||||||
|
// overrun the allocated stack size.
|
||||||
|
ADD $128, RSP, R17
|
||||||
|
MOVD R17, R4
|
||||||
|
|
||||||
|
// !!! R6 = &src[tableSize]
|
||||||
|
ADD R6<<1, R17, R6
|
||||||
|
|
||||||
|
// zero the SIMD registers
|
||||||
|
VEOR V0.B16, V0.B16, V0.B16
|
||||||
|
VEOR V1.B16, V1.B16, V1.B16
|
||||||
|
VEOR V2.B16, V2.B16, V2.B16
|
||||||
|
VEOR V3.B16, V3.B16, V3.B16
|
||||||
|
|
||||||
|
memclr:
|
||||||
|
VST1.P [V0.B16, V1.B16, V2.B16, V3.B16], 64(R4)
|
||||||
|
CMP R4, R6
|
||||||
|
BHI memclr
|
||||||
|
|
||||||
|
// !!! R6 = &src[0]
|
||||||
|
MOVD R7, R6
|
||||||
|
|
||||||
|
// sLimit := len(src) - inputMargin
|
||||||
|
MOVD R14, R9
|
||||||
|
SUB $15, R9, R9
|
||||||
|
|
||||||
|
// !!! Pre-emptively spill R5, R6 and R9 to the stack. Their values don't
|
||||||
|
// change for the rest of the function.
|
||||||
|
MOVD R5, 64(RSP)
|
||||||
|
MOVD R6, 72(RSP)
|
||||||
|
MOVD R9, 96(RSP)
|
||||||
|
|
||||||
|
// nextEmit := 0
|
||||||
|
MOVD R6, R10
|
||||||
|
|
||||||
|
// s := 1
|
||||||
|
ADD $1, R7, R7
|
||||||
|
|
||||||
|
// nextHash := hash(load32(src, s), shift)
|
||||||
|
MOVW 0(R7), R11
|
||||||
|
MULW R16, R11, R11
|
||||||
|
LSRW R5, R11, R11
|
||||||
|
|
||||||
|
outer:
|
||||||
|
// for { etc }
|
||||||
|
|
||||||
|
// skip := 32
|
||||||
|
MOVD $32, R12
|
||||||
|
|
||||||
|
// nextS := s
|
||||||
|
MOVD R7, R13
|
||||||
|
|
||||||
|
// candidate := 0
|
||||||
|
MOVD $0, R15
|
||||||
|
|
||||||
|
inner0:
|
||||||
|
// for { etc }
|
||||||
|
|
||||||
|
// s := nextS
|
||||||
|
MOVD R13, R7
|
||||||
|
|
||||||
|
// bytesBetweenHashLookups := skip >> 5
|
||||||
|
MOVD R12, R14
|
||||||
|
LSR $5, R14, R14
|
||||||
|
|
||||||
|
// nextS = s + bytesBetweenHashLookups
|
||||||
|
ADD R14, R13, R13
|
||||||
|
|
||||||
|
// skip += bytesBetweenHashLookups
|
||||||
|
ADD R14, R12, R12
|
||||||
|
|
||||||
|
// if nextS > sLimit { goto emitRemainder }
|
||||||
|
MOVD R13, R3
|
||||||
|
SUB R6, R3, R3
|
||||||
|
CMP R9, R3
|
||||||
|
BHI emitRemainder
|
||||||
|
|
||||||
|
// candidate = int(table[nextHash])
|
||||||
|
MOVHU 0(R17)(R11<<1), R15
|
||||||
|
|
||||||
|
// table[nextHash] = uint16(s)
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R6, R3, R3
|
||||||
|
|
||||||
|
MOVH R3, 0(R17)(R11<<1)
|
||||||
|
|
||||||
|
// nextHash = hash(load32(src, nextS), shift)
|
||||||
|
MOVW 0(R13), R11
|
||||||
|
MULW R16, R11
|
||||||
|
LSRW R5, R11, R11
|
||||||
|
|
||||||
|
// if load32(src, s) != load32(src, candidate) { continue } break
|
||||||
|
MOVW 0(R7), R3
|
||||||
|
MOVW (R6)(R15*1), R4
|
||||||
|
CMPW R4, R3
|
||||||
|
BNE inner0
|
||||||
|
|
||||||
|
fourByteMatch:
|
||||||
|
// As per the encode_other.go code:
|
||||||
|
//
|
||||||
|
// A 4-byte match has been found. We'll later see etc.
|
||||||
|
|
||||||
|
// !!! Jump to a fast path for short (<= 16 byte) literals. See the comment
|
||||||
|
// on inputMargin in encode.go.
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R10, R3, R3
|
||||||
|
MOVD $16, R2
|
||||||
|
CMP R2, R3
|
||||||
|
BLE emitLiteralFastPath
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Begin inline of the emitLiteral call.
|
||||||
|
//
|
||||||
|
// d += emitLiteral(dst[d:], src[nextEmit:s])
|
||||||
|
|
||||||
|
MOVW R3, R4
|
||||||
|
SUBW $1, R4, R4
|
||||||
|
|
||||||
|
MOVW $60, R2
|
||||||
|
CMPW R2, R4
|
||||||
|
BLT inlineEmitLiteralOneByte
|
||||||
|
MOVW $256, R2
|
||||||
|
CMPW R2, R4
|
||||||
|
BLT inlineEmitLiteralTwoBytes
|
||||||
|
|
||||||
|
inlineEmitLiteralThreeBytes:
|
||||||
|
MOVD $0xf4, R1
|
||||||
|
MOVB R1, 0(R8)
|
||||||
|
MOVW R4, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
B inlineEmitLiteralMemmove
|
||||||
|
|
||||||
|
inlineEmitLiteralTwoBytes:
|
||||||
|
MOVD $0xf0, R1
|
||||||
|
MOVB R1, 0(R8)
|
||||||
|
MOVB R4, 1(R8)
|
||||||
|
ADD $2, R8, R8
|
||||||
|
B inlineEmitLiteralMemmove
|
||||||
|
|
||||||
|
inlineEmitLiteralOneByte:
|
||||||
|
LSLW $2, R4, R4
|
||||||
|
MOVB R4, 0(R8)
|
||||||
|
ADD $1, R8, R8
|
||||||
|
|
||||||
|
inlineEmitLiteralMemmove:
|
||||||
|
// Spill local variables (registers) onto the stack; call; unspill.
|
||||||
|
//
|
||||||
|
// copy(dst[i:], lit)
|
||||||
|
//
|
||||||
|
// This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push
|
||||||
|
// R8, R10 and R3 as arguments.
|
||||||
|
MOVD R8, 8(RSP)
|
||||||
|
MOVD R10, 16(RSP)
|
||||||
|
MOVD R3, 24(RSP)
|
||||||
|
|
||||||
|
// Finish the "d +=" part of "d += emitLiteral(etc)".
|
||||||
|
ADD R3, R8, R8
|
||||||
|
MOVD R7, 80(RSP)
|
||||||
|
MOVD R8, 88(RSP)
|
||||||
|
MOVD R15, 120(RSP)
|
||||||
|
CALL runtime·memmove(SB)
|
||||||
|
MOVD 64(RSP), R5
|
||||||
|
MOVD 72(RSP), R6
|
||||||
|
MOVD 80(RSP), R7
|
||||||
|
MOVD 88(RSP), R8
|
||||||
|
MOVD 96(RSP), R9
|
||||||
|
MOVD 120(RSP), R15
|
||||||
|
B inner1
|
||||||
|
|
||||||
|
inlineEmitLiteralEnd:
|
||||||
|
// End inline of the emitLiteral call.
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
emitLiteralFastPath:
|
||||||
|
// !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2".
|
||||||
|
MOVB R3, R4
|
||||||
|
SUBW $1, R4, R4
|
||||||
|
AND $0xff, R4, R4
|
||||||
|
LSLW $2, R4, R4
|
||||||
|
MOVB R4, (R8)
|
||||||
|
ADD $1, R8, R8
|
||||||
|
|
||||||
|
// !!! Implement the copy from lit to dst as a 16-byte load and store.
|
||||||
|
// (Encode's documentation says that dst and src must not overlap.)
|
||||||
|
//
|
||||||
|
// This always copies 16 bytes, instead of only len(lit) bytes, but that's
|
||||||
|
// OK. Subsequent iterations will fix up the overrun.
|
||||||
|
//
|
||||||
|
// Note that on arm64, it is legal and cheap to issue unaligned 8-byte or
|
||||||
|
// 16-byte loads and stores. This technique probably wouldn't be as
|
||||||
|
// effective on architectures that are fussier about alignment.
|
||||||
|
VLD1 0(R10), [V0.B16]
|
||||||
|
VST1 [V0.B16], 0(R8)
|
||||||
|
ADD R3, R8, R8
|
||||||
|
|
||||||
|
inner1:
|
||||||
|
// for { etc }
|
||||||
|
|
||||||
|
// base := s
|
||||||
|
MOVD R7, R12
|
||||||
|
|
||||||
|
// !!! offset := base - candidate
|
||||||
|
MOVD R12, R11
|
||||||
|
SUB R15, R11, R11
|
||||||
|
SUB R6, R11, R11
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Begin inline of the extendMatch call.
|
||||||
|
//
|
||||||
|
// s = extendMatch(src, candidate+4, s+4)
|
||||||
|
|
||||||
|
// !!! R14 = &src[len(src)]
|
||||||
|
MOVD src_len+32(FP), R14
|
||||||
|
ADD R6, R14, R14
|
||||||
|
|
||||||
|
// !!! R13 = &src[len(src) - 8]
|
||||||
|
MOVD R14, R13
|
||||||
|
SUB $8, R13, R13
|
||||||
|
|
||||||
|
// !!! R15 = &src[candidate + 4]
|
||||||
|
ADD $4, R15, R15
|
||||||
|
ADD R6, R15, R15
|
||||||
|
|
||||||
|
// !!! s += 4
|
||||||
|
ADD $4, R7, R7
|
||||||
|
|
||||||
|
inlineExtendMatchCmp8:
|
||||||
|
// As long as we are 8 or more bytes before the end of src, we can load and
|
||||||
|
// compare 8 bytes at a time. If those 8 bytes are equal, repeat.
|
||||||
|
CMP R13, R7
|
||||||
|
BHI inlineExtendMatchCmp1
|
||||||
|
MOVD (R15), R3
|
||||||
|
MOVD (R7), R4
|
||||||
|
CMP R4, R3
|
||||||
|
BNE inlineExtendMatchBSF
|
||||||
|
ADD $8, R15, R15
|
||||||
|
ADD $8, R7, R7
|
||||||
|
B inlineExtendMatchCmp8
|
||||||
|
|
||||||
|
inlineExtendMatchBSF:
|
||||||
|
// If those 8 bytes were not equal, XOR the two 8 byte values, and return
|
||||||
|
// the index of the first byte that differs.
|
||||||
|
// RBIT reverses the bit order, then CLZ counts the leading zeros, the
|
||||||
|
// combination of which finds the least significant bit which is set.
|
||||||
|
// The arm64 architecture is little-endian, and the shift by 3 converts
|
||||||
|
// a bit index to a byte index.
|
||||||
|
EOR R3, R4, R4
|
||||||
|
RBIT R4, R4
|
||||||
|
CLZ R4, R4
|
||||||
|
ADD R4>>3, R7, R7
|
||||||
|
B inlineExtendMatchEnd
|
||||||
|
|
||||||
|
inlineExtendMatchCmp1:
|
||||||
|
// In src's tail, compare 1 byte at a time.
|
||||||
|
CMP R7, R14
|
||||||
|
BLS inlineExtendMatchEnd
|
||||||
|
MOVB (R15), R3
|
||||||
|
MOVB (R7), R4
|
||||||
|
CMP R4, R3
|
||||||
|
BNE inlineExtendMatchEnd
|
||||||
|
ADD $1, R15, R15
|
||||||
|
ADD $1, R7, R7
|
||||||
|
B inlineExtendMatchCmp1
|
||||||
|
|
||||||
|
inlineExtendMatchEnd:
|
||||||
|
// End inline of the extendMatch call.
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Begin inline of the emitCopy call.
|
||||||
|
//
|
||||||
|
// d += emitCopy(dst[d:], base-candidate, s-base)
|
||||||
|
|
||||||
|
// !!! length := s - base
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R12, R3, R3
|
||||||
|
|
||||||
|
inlineEmitCopyLoop0:
|
||||||
|
// for length >= 68 { etc }
|
||||||
|
MOVW $68, R2
|
||||||
|
CMPW R2, R3
|
||||||
|
BLT inlineEmitCopyStep1
|
||||||
|
|
||||||
|
// Emit a length 64 copy, encoded as 3 bytes.
|
||||||
|
MOVD $0xfe, R1
|
||||||
|
MOVB R1, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
SUBW $64, R3, R3
|
||||||
|
B inlineEmitCopyLoop0
|
||||||
|
|
||||||
|
inlineEmitCopyStep1:
|
||||||
|
// if length > 64 { etc }
|
||||||
|
MOVW $64, R2
|
||||||
|
CMPW R2, R3
|
||||||
|
BLE inlineEmitCopyStep2
|
||||||
|
|
||||||
|
// Emit a length 60 copy, encoded as 3 bytes.
|
||||||
|
MOVD $0xee, R1
|
||||||
|
MOVB R1, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
SUBW $60, R3, R3
|
||||||
|
|
||||||
|
inlineEmitCopyStep2:
|
||||||
|
// if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 }
|
||||||
|
MOVW $12, R2
|
||||||
|
CMPW R2, R3
|
||||||
|
BGE inlineEmitCopyStep3
|
||||||
|
MOVW $2048, R2
|
||||||
|
CMPW R2, R11
|
||||||
|
BGE inlineEmitCopyStep3
|
||||||
|
|
||||||
|
// Emit the remaining copy, encoded as 2 bytes.
|
||||||
|
MOVB R11, 1(R8)
|
||||||
|
LSRW $8, R11, R11
|
||||||
|
LSLW $5, R11, R11
|
||||||
|
SUBW $4, R3, R3
|
||||||
|
AND $0xff, R3, R3
|
||||||
|
LSLW $2, R3, R3
|
||||||
|
ORRW R3, R11, R11
|
||||||
|
ORRW $1, R11, R11
|
||||||
|
MOVB R11, 0(R8)
|
||||||
|
ADD $2, R8, R8
|
||||||
|
B inlineEmitCopyEnd
|
||||||
|
|
||||||
|
inlineEmitCopyStep3:
|
||||||
|
// Emit the remaining copy, encoded as 3 bytes.
|
||||||
|
SUBW $1, R3, R3
|
||||||
|
LSLW $2, R3, R3
|
||||||
|
ORRW $2, R3, R3
|
||||||
|
MOVB R3, 0(R8)
|
||||||
|
MOVW R11, 1(R8)
|
||||||
|
ADD $3, R8, R8
|
||||||
|
|
||||||
|
inlineEmitCopyEnd:
|
||||||
|
// End inline of the emitCopy call.
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
// nextEmit = s
|
||||||
|
MOVD R7, R10
|
||||||
|
|
||||||
|
// if s >= sLimit { goto emitRemainder }
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R6, R3, R3
|
||||||
|
CMP R3, R9
|
||||||
|
BLS emitRemainder
|
||||||
|
|
||||||
|
// As per the encode_other.go code:
|
||||||
|
//
|
||||||
|
// We could immediately etc.
|
||||||
|
|
||||||
|
// x := load64(src, s-1)
|
||||||
|
MOVD -1(R7), R14
|
||||||
|
|
||||||
|
// prevHash := hash(uint32(x>>0), shift)
|
||||||
|
MOVW R14, R11
|
||||||
|
MULW R16, R11, R11
|
||||||
|
LSRW R5, R11, R11
|
||||||
|
|
||||||
|
// table[prevHash] = uint16(s-1)
|
||||||
|
MOVD R7, R3
|
||||||
|
SUB R6, R3, R3
|
||||||
|
SUB $1, R3, R3
|
||||||
|
|
||||||
|
MOVHU R3, 0(R17)(R11<<1)
|
||||||
|
|
||||||
|
// currHash := hash(uint32(x>>8), shift)
|
||||||
|
LSR $8, R14, R14
|
||||||
|
MOVW R14, R11
|
||||||
|
MULW R16, R11, R11
|
||||||
|
LSRW R5, R11, R11
|
||||||
|
|
||||||
|
// candidate = int(table[currHash])
|
||||||
|
MOVHU 0(R17)(R11<<1), R15
|
||||||
|
|
||||||
|
// table[currHash] = uint16(s)
|
||||||
|
ADD $1, R3, R3
|
||||||
|
MOVHU R3, 0(R17)(R11<<1)
|
||||||
|
|
||||||
|
// if uint32(x>>8) == load32(src, candidate) { continue }
|
||||||
|
MOVW (R6)(R15*1), R4
|
||||||
|
CMPW R4, R14
|
||||||
|
BEQ inner1
|
||||||
|
|
||||||
|
// nextHash = hash(uint32(x>>16), shift)
|
||||||
|
LSR $8, R14, R14
|
||||||
|
MOVW R14, R11
|
||||||
|
MULW R16, R11, R11
|
||||||
|
LSRW R5, R11, R11
|
||||||
|
|
||||||
|
// s++
|
||||||
|
ADD $1, R7, R7
|
||||||
|
|
||||||
|
// break out of the inner1 for loop, i.e. continue the outer loop.
|
||||||
|
B outer
|
||||||
|
|
||||||
|
emitRemainder:
|
||||||
|
// if nextEmit < len(src) { etc }
|
||||||
|
MOVD src_len+32(FP), R3
|
||||||
|
ADD R6, R3, R3
|
||||||
|
CMP R3, R10
|
||||||
|
BEQ encodeBlockEnd
|
||||||
|
|
||||||
|
// d += emitLiteral(dst[d:], src[nextEmit:])
|
||||||
|
//
|
||||||
|
// Push args.
|
||||||
|
MOVD R8, 8(RSP)
|
||||||
|
MOVD $0, 16(RSP) // Unnecessary, as the callee ignores it, but conservative.
|
||||||
|
MOVD $0, 24(RSP) // Unnecessary, as the callee ignores it, but conservative.
|
||||||
|
MOVD R10, 32(RSP)
|
||||||
|
SUB R10, R3, R3
|
||||||
|
MOVD R3, 40(RSP)
|
||||||
|
MOVD R3, 48(RSP) // Unnecessary, as the callee ignores it, but conservative.
|
||||||
|
|
||||||
|
// Spill local variables (registers) onto the stack; call; unspill.
|
||||||
|
MOVD R8, 88(RSP)
|
||||||
|
CALL ·emitLiteral(SB)
|
||||||
|
MOVD 88(RSP), R8
|
||||||
|
|
||||||
|
// Finish the "d +=" part of "d += emitLiteral(etc)".
|
||||||
|
MOVD 56(RSP), R1
|
||||||
|
ADD R1, R8, R8
|
||||||
|
|
||||||
|
encodeBlockEnd:
|
||||||
|
MOVD dst_base+0(FP), R3
|
||||||
|
SUB R3, R8, R8
|
||||||
|
MOVD R8, d+48(FP)
|
||||||
|
RET
|
@ -5,6 +5,7 @@
|
|||||||
// +build !appengine
|
// +build !appengine
|
||||||
// +build gc
|
// +build gc
|
||||||
// +build !noasm
|
// +build !noasm
|
||||||
|
// +build amd64 arm64
|
||||||
|
|
||||||
package snappy
|
package snappy
|
||||||
|
|
2
vendor/github.com/golang/snappy/encode_other.go
generated
vendored
2
vendor/github.com/golang/snappy/encode_other.go
generated
vendored
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !amd64 appengine !gc noasm
|
// +build !amd64,!arm64 appengine !gc noasm
|
||||||
|
|
||||||
package snappy
|
package snappy
|
||||||
|
|
||||||
|
1
vendor/github.com/golang/snappy/go.mod
generated
vendored
Normal file
1
vendor/github.com/golang/snappy/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module github.com/golang/snappy
|
12
vendor/github.com/hashicorp/go-uuid/.travis.yml
generated
vendored
12
vendor/github.com/hashicorp/go-uuid/.travis.yml
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- 1.6
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -bench . -benchmem -v ./...
|
|
363
vendor/github.com/hashicorp/go-uuid/LICENSE
generated
vendored
363
vendor/github.com/hashicorp/go-uuid/LICENSE
generated
vendored
@ -1,363 +0,0 @@
|
|||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
|
|
8
vendor/github.com/hashicorp/go-uuid/README.md
generated
vendored
8
vendor/github.com/hashicorp/go-uuid/README.md
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# uuid [![Build Status](https://travis-ci.org/hashicorp/go-uuid.svg?branch=master)](https://travis-ci.org/hashicorp/go-uuid)
|
|
||||||
|
|
||||||
Generates UUID-format strings using high quality, _purely random_ bytes. It is **not** intended to be RFC compliant, merely to use a well-understood string representation of a 128-bit value. It can also parse UUID-format strings into their component bytes.
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
=============
|
|
||||||
|
|
||||||
The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/go-uuid).
|
|
1
vendor/github.com/hashicorp/go-uuid/go.mod
generated
vendored
1
vendor/github.com/hashicorp/go-uuid/go.mod
generated
vendored
@ -1 +0,0 @@
|
|||||||
module github.com/hashicorp/go-uuid
|
|
83
vendor/github.com/hashicorp/go-uuid/uuid.go
generated
vendored
83
vendor/github.com/hashicorp/go-uuid/uuid.go
generated
vendored
@ -1,83 +0,0 @@
|
|||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenerateRandomBytes is used to generate random bytes of given size.
|
|
||||||
func GenerateRandomBytes(size int) ([]byte, error) {
|
|
||||||
return GenerateRandomBytesWithReader(size, rand.Reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateRandomBytesWithReader is used to generate random bytes of given size read from a given reader.
|
|
||||||
func GenerateRandomBytesWithReader(size int, reader io.Reader) ([]byte, error) {
|
|
||||||
if reader == nil {
|
|
||||||
return nil, fmt.Errorf("provided reader is nil")
|
|
||||||
}
|
|
||||||
buf := make([]byte, size)
|
|
||||||
if _, err := io.ReadFull(reader, buf); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read random bytes: %v", err)
|
|
||||||
}
|
|
||||||
return buf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const uuidLen = 16
|
|
||||||
|
|
||||||
// GenerateUUID is used to generate a random UUID
|
|
||||||
func GenerateUUID() (string, error) {
|
|
||||||
return GenerateUUIDWithReader(rand.Reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateUUIDWithReader is used to generate a random UUID with a given Reader
|
|
||||||
func GenerateUUIDWithReader(reader io.Reader) (string, error) {
|
|
||||||
if reader == nil {
|
|
||||||
return "", fmt.Errorf("provided reader is nil")
|
|
||||||
}
|
|
||||||
buf, err := GenerateRandomBytesWithReader(uuidLen, reader)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return FormatUUID(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatUUID(buf []byte) (string, error) {
|
|
||||||
if buflen := len(buf); buflen != uuidLen {
|
|
||||||
return "", fmt.Errorf("wrong length byte slice (%d)", buflen)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%x-%x-%x-%x-%x",
|
|
||||||
buf[0:4],
|
|
||||||
buf[4:6],
|
|
||||||
buf[6:8],
|
|
||||||
buf[8:10],
|
|
||||||
buf[10:16]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseUUID(uuid string) ([]byte, error) {
|
|
||||||
if len(uuid) != 2 * uuidLen + 4 {
|
|
||||||
return nil, fmt.Errorf("uuid string is wrong length")
|
|
||||||
}
|
|
||||||
|
|
||||||
if uuid[8] != '-' ||
|
|
||||||
uuid[13] != '-' ||
|
|
||||||
uuid[18] != '-' ||
|
|
||||||
uuid[23] != '-' {
|
|
||||||
return nil, fmt.Errorf("uuid is improperly formatted")
|
|
||||||
}
|
|
||||||
|
|
||||||
hexStr := uuid[0:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
|
|
||||||
|
|
||||||
ret, err := hex.DecodeString(hexStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(ret) != uuidLen {
|
|
||||||
return nil, fmt.Errorf("decoded hex is the wrong length")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
201
vendor/github.com/jcmturner/aescts/v2/LICENSE
generated
vendored
201
vendor/github.com/jcmturner/aescts/v2/LICENSE
generated
vendored
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
186
vendor/github.com/jcmturner/aescts/v2/aescts.go
generated
vendored
186
vendor/github.com/jcmturner/aescts/v2/aescts.go
generated
vendored
@ -1,186 +0,0 @@
|
|||||||
// Package aescts provides AES CBC CipherText Stealing encryption and decryption methods
|
|
||||||
package aescts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Encrypt the message with the key and the initial vector.
|
|
||||||
// Returns: next iv, ciphertext bytes, error
|
|
||||||
func Encrypt(key, iv, plaintext []byte) ([]byte, []byte, error) {
|
|
||||||
l := len(plaintext)
|
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("error creating cipher: %v", err)
|
|
||||||
}
|
|
||||||
mode := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
|
|
||||||
m := make([]byte, len(plaintext))
|
|
||||||
copy(m, plaintext)
|
|
||||||
|
|
||||||
/*For consistency, ciphertext stealing is always used for the last two
|
|
||||||
blocks of the data to be encrypted, as in [RC5]. If the data length
|
|
||||||
is a multiple of the block size, this is equivalent to plain CBC mode
|
|
||||||
with the last two ciphertext blocks swapped.*/
|
|
||||||
/*The initial vector carried out from one encryption for use in a
|
|
||||||
subsequent encryption is the next-to-last block of the encryption
|
|
||||||
output; this is the encrypted form of the last plaintext block.*/
|
|
||||||
if l <= aes.BlockSize {
|
|
||||||
m, _ = zeroPad(m, aes.BlockSize)
|
|
||||||
mode.CryptBlocks(m, m)
|
|
||||||
return m, m, nil
|
|
||||||
}
|
|
||||||
if l%aes.BlockSize == 0 {
|
|
||||||
mode.CryptBlocks(m, m)
|
|
||||||
iv = m[len(m)-aes.BlockSize:]
|
|
||||||
rb, _ := swapLastTwoBlocks(m, aes.BlockSize)
|
|
||||||
return iv, rb, nil
|
|
||||||
}
|
|
||||||
m, _ = zeroPad(m, aes.BlockSize)
|
|
||||||
rb, pb, lb, err := tailBlocks(m, aes.BlockSize)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("error tailing blocks: %v", err)
|
|
||||||
}
|
|
||||||
var ct []byte
|
|
||||||
if rb != nil {
|
|
||||||
// Encrpt all but the lats 2 blocks and update the rolling iv
|
|
||||||
mode.CryptBlocks(rb, rb)
|
|
||||||
iv = rb[len(rb)-aes.BlockSize:]
|
|
||||||
mode = cipher.NewCBCEncrypter(block, iv)
|
|
||||||
ct = append(ct, rb...)
|
|
||||||
}
|
|
||||||
mode.CryptBlocks(pb, pb)
|
|
||||||
mode = cipher.NewCBCEncrypter(block, pb)
|
|
||||||
mode.CryptBlocks(lb, lb)
|
|
||||||
// Cipher Text Stealing (CTS) - Ref: https://en.wikipedia.org/wiki/Ciphertext_stealing#CBC_ciphertext_stealing
|
|
||||||
// Swap the last two cipher blocks
|
|
||||||
// Truncate the ciphertext to the length of the original plaintext
|
|
||||||
ct = append(ct, lb...)
|
|
||||||
ct = append(ct, pb...)
|
|
||||||
return lb, ct[:l], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt the ciphertext with the key and the initial vector.
|
|
||||||
func Decrypt(key, iv, ciphertext []byte) ([]byte, error) {
|
|
||||||
// Copy the cipher text as golang slices even when passed by value to this method can result in the backing arrays of the calling code value being updated.
|
|
||||||
ct := make([]byte, len(ciphertext))
|
|
||||||
copy(ct, ciphertext)
|
|
||||||
if len(ct) < aes.BlockSize {
|
|
||||||
return []byte{}, fmt.Errorf("ciphertext is not large enough. It is less that one block size. Blocksize:%v; Ciphertext:%v", aes.BlockSize, len(ct))
|
|
||||||
}
|
|
||||||
// Configure the CBC
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error creating cipher: %v", err)
|
|
||||||
}
|
|
||||||
var mode cipher.BlockMode
|
|
||||||
|
|
||||||
//If ciphertext is multiple of blocksize we just need to swap back the last two blocks and then do CBC
|
|
||||||
//If the ciphertext is just one block we can't swap so we just decrypt
|
|
||||||
if len(ct)%aes.BlockSize == 0 {
|
|
||||||
if len(ct) > aes.BlockSize {
|
|
||||||
ct, _ = swapLastTwoBlocks(ct, aes.BlockSize)
|
|
||||||
}
|
|
||||||
mode = cipher.NewCBCDecrypter(block, iv)
|
|
||||||
message := make([]byte, len(ct))
|
|
||||||
mode.CryptBlocks(message, ct)
|
|
||||||
return message[:len(ct)], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cipher Text Stealing (CTS) using CBC interface. Ref: https://en.wikipedia.org/wiki/Ciphertext_stealing#CBC_ciphertext_stealing
|
|
||||||
// Get ciphertext of the 2nd to last (penultimate) block (cpb), the last block (clb) and the rest (crb)
|
|
||||||
crb, cpb, clb, _ := tailBlocks(ct, aes.BlockSize)
|
|
||||||
v := make([]byte, len(iv), len(iv))
|
|
||||||
copy(v, iv)
|
|
||||||
var message []byte
|
|
||||||
if crb != nil {
|
|
||||||
//If there is more than just the last and the penultimate block we decrypt it and the last bloc of this becomes the iv for later
|
|
||||||
rb := make([]byte, len(crb))
|
|
||||||
mode = cipher.NewCBCDecrypter(block, v)
|
|
||||||
v = crb[len(crb)-aes.BlockSize:]
|
|
||||||
mode.CryptBlocks(rb, crb)
|
|
||||||
message = append(message, rb...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to modify the cipher text
|
|
||||||
// Decryt the 2nd to last (penultimate) block with a the original iv
|
|
||||||
pb := make([]byte, aes.BlockSize)
|
|
||||||
mode = cipher.NewCBCDecrypter(block, iv)
|
|
||||||
mode.CryptBlocks(pb, cpb)
|
|
||||||
// number of byte needed to pad
|
|
||||||
npb := aes.BlockSize - len(ct)%aes.BlockSize
|
|
||||||
//pad last block using the number of bytes needed from the tail of the plaintext 2nd to last (penultimate) block
|
|
||||||
clb = append(clb, pb[len(pb)-npb:]...)
|
|
||||||
|
|
||||||
// Now decrypt the last block in the penultimate position (iv will be from the crb, if the is no crb it's zeros)
|
|
||||||
// iv for the penultimate block decrypted in the last position becomes the modified last block
|
|
||||||
lb := make([]byte, aes.BlockSize)
|
|
||||||
mode = cipher.NewCBCDecrypter(block, v)
|
|
||||||
v = clb
|
|
||||||
mode.CryptBlocks(lb, clb)
|
|
||||||
message = append(message, lb...)
|
|
||||||
|
|
||||||
// Now decrypt the penultimate block in the last position (iv will be from the modified last block)
|
|
||||||
mode = cipher.NewCBCDecrypter(block, v)
|
|
||||||
mode.CryptBlocks(cpb, cpb)
|
|
||||||
message = append(message, cpb...)
|
|
||||||
|
|
||||||
// Truncate to the size of the original cipher text
|
|
||||||
return message[:len(ct)], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func tailBlocks(b []byte, c int) ([]byte, []byte, []byte, error) {
|
|
||||||
if len(b) <= c {
|
|
||||||
return []byte{}, []byte{}, []byte{}, errors.New("bytes slice is not larger than one block so cannot tail")
|
|
||||||
}
|
|
||||||
// Get size of last block
|
|
||||||
var lbs int
|
|
||||||
if l := len(b) % aes.BlockSize; l == 0 {
|
|
||||||
lbs = aes.BlockSize
|
|
||||||
} else {
|
|
||||||
lbs = l
|
|
||||||
}
|
|
||||||
// Get last block
|
|
||||||
lb := b[len(b)-lbs:]
|
|
||||||
// Get 2nd to last (penultimate) block
|
|
||||||
pb := b[len(b)-lbs-c : len(b)-lbs]
|
|
||||||
if len(b) > 2*c {
|
|
||||||
rb := b[:len(b)-lbs-c]
|
|
||||||
return rb, pb, lb, nil
|
|
||||||
}
|
|
||||||
return nil, pb, lb, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func swapLastTwoBlocks(b []byte, c int) ([]byte, error) {
|
|
||||||
rb, pb, lb, err := tailBlocks(b, c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var out []byte
|
|
||||||
if rb != nil {
|
|
||||||
out = append(out, rb...)
|
|
||||||
}
|
|
||||||
out = append(out, lb...)
|
|
||||||
out = append(out, pb...)
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// zeroPad pads bytes with zeros to nearest multiple of message size m.
|
|
||||||
func zeroPad(b []byte, m int) ([]byte, error) {
|
|
||||||
if m <= 0 {
|
|
||||||
return nil, errors.New("invalid message block size when padding")
|
|
||||||
}
|
|
||||||
if b == nil || len(b) == 0 {
|
|
||||||
return nil, errors.New("data not valid to pad: Zero size")
|
|
||||||
}
|
|
||||||
if l := len(b) % m; l != 0 {
|
|
||||||
n := m - l
|
|
||||||
z := make([]byte, n)
|
|
||||||
b = append(b, z...)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
5
vendor/github.com/jcmturner/aescts/v2/go.mod
generated
vendored
5
vendor/github.com/jcmturner/aescts/v2/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
module github.com/jcmturner/aescts/v2
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require github.com/stretchr/testify v1.4.0
|
|
10
vendor/github.com/jcmturner/aescts/v2/go.sum
generated
vendored
10
vendor/github.com/jcmturner/aescts/v2/go.sum
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
201
vendor/github.com/jcmturner/dnsutils/v2/LICENSE
generated
vendored
201
vendor/github.com/jcmturner/dnsutils/v2/LICENSE
generated
vendored
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
5
vendor/github.com/jcmturner/dnsutils/v2/go.mod
generated
vendored
5
vendor/github.com/jcmturner/dnsutils/v2/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
module github.com/jcmturner/dnsutils/v2
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require github.com/stretchr/testify v1.4.0
|
|
10
vendor/github.com/jcmturner/dnsutils/v2/go.sum
generated
vendored
10
vendor/github.com/jcmturner/dnsutils/v2/go.sum
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
95
vendor/github.com/jcmturner/dnsutils/v2/srv.go
generated
vendored
95
vendor/github.com/jcmturner/dnsutils/v2/srv.go
generated
vendored
@ -1,95 +0,0 @@
|
|||||||
package dnsutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OrderedSRV returns a count of the results and a map keyed on the order they should be used.
|
|
||||||
// This based on the records' priority and randomised selection based on their relative weighting.
|
|
||||||
// The function's inputs are the same as those for net.LookupSRV
|
|
||||||
// To use in the correct order:
|
|
||||||
//
|
|
||||||
// count, orderedSRV, err := OrderedSRV(service, proto, name)
|
|
||||||
// i := 1
|
|
||||||
// for i <= count {
|
|
||||||
// srv := orderedSRV[i]
|
|
||||||
// // Do something such as dial this SRV. If fails move on the the next or break if it succeeds.
|
|
||||||
// i += 1
|
|
||||||
// }
|
|
||||||
func OrderedSRV(service, proto, name string) (int, map[int]*net.SRV, error) {
|
|
||||||
_, addrs, err := net.LookupSRV(service, proto, name)
|
|
||||||
if err != nil {
|
|
||||||
return 0, make(map[int]*net.SRV), err
|
|
||||||
}
|
|
||||||
index, osrv := orderSRV(addrs)
|
|
||||||
return index, osrv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func orderSRV(addrs []*net.SRV) (int, map[int]*net.SRV) {
|
|
||||||
// Initialise the ordered map
|
|
||||||
var o int
|
|
||||||
osrv := make(map[int]*net.SRV)
|
|
||||||
|
|
||||||
prioMap := make(map[int][]*net.SRV, 0)
|
|
||||||
for _, srv := range addrs {
|
|
||||||
prioMap[int(srv.Priority)] = append(prioMap[int(srv.Priority)], srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
priorities := make([]int, 0)
|
|
||||||
for p := range prioMap {
|
|
||||||
priorities = append(priorities, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
var count int
|
|
||||||
sort.Ints(priorities)
|
|
||||||
for _, p := range priorities {
|
|
||||||
tos := weightedOrder(prioMap[p])
|
|
||||||
for i, s := range tos {
|
|
||||||
count += 1
|
|
||||||
osrv[o+i] = s
|
|
||||||
}
|
|
||||||
o += len(tos)
|
|
||||||
}
|
|
||||||
return count, osrv
|
|
||||||
}
|
|
||||||
|
|
||||||
func weightedOrder(srvs []*net.SRV) map[int]*net.SRV {
|
|
||||||
// Get the total weight
|
|
||||||
var tw int
|
|
||||||
for _, s := range srvs {
|
|
||||||
tw += int(s.Weight)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise the ordered map
|
|
||||||
o := 1
|
|
||||||
osrv := make(map[int]*net.SRV)
|
|
||||||
|
|
||||||
// Whilst there are still entries to be ordered
|
|
||||||
l := len(srvs)
|
|
||||||
for l > 0 {
|
|
||||||
i := rand.Intn(l)
|
|
||||||
s := srvs[i]
|
|
||||||
var rw int
|
|
||||||
if tw > 0 {
|
|
||||||
// Greater the weight the more likely this will be zero or less
|
|
||||||
rw = rand.Intn(tw) - int(s.Weight)
|
|
||||||
}
|
|
||||||
if rw <= 0 {
|
|
||||||
// Put entry in position
|
|
||||||
osrv[o] = s
|
|
||||||
if len(srvs) > 1 {
|
|
||||||
// Remove the entry from the source slice by swapping with the last entry and truncating
|
|
||||||
srvs[len(srvs)-1], srvs[i] = srvs[i], srvs[len(srvs)-1]
|
|
||||||
srvs = srvs[:len(srvs)-1]
|
|
||||||
l = len(srvs)
|
|
||||||
} else {
|
|
||||||
l = 0
|
|
||||||
}
|
|
||||||
o += 1
|
|
||||||
tw = tw - int(s.Weight)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return osrv
|
|
||||||
}
|
|
27
vendor/github.com/jcmturner/gofork/LICENSE
generated
vendored
27
vendor/github.com/jcmturner/gofork/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5
vendor/github.com/jcmturner/gofork/encoding/asn1/README.md
generated
vendored
5
vendor/github.com/jcmturner/gofork/encoding/asn1/README.md
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
This is a temporary repository that will be removed when the issues below are fixed in the core golang code.
|
|
||||||
|
|
||||||
## Issues
|
|
||||||
* [encoding/asn1: cannot marshal into a GeneralString](https://github.com/golang/go/issues/18832)
|
|
||||||
* [encoding/asn1: cannot marshal into slice of strings and pass stringtype parameter tags to members](https://github.com/golang/go/issues/18834)
|
|
1003
vendor/github.com/jcmturner/gofork/encoding/asn1/asn1.go
generated
vendored
1003
vendor/github.com/jcmturner/gofork/encoding/asn1/asn1.go
generated
vendored
File diff suppressed because it is too large
Load Diff
173
vendor/github.com/jcmturner/gofork/encoding/asn1/common.go
generated
vendored
173
vendor/github.com/jcmturner/gofork/encoding/asn1/common.go
generated
vendored
@ -1,173 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package asn1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ASN.1 objects have metadata preceding them:
|
|
||||||
// the tag: the type of the object
|
|
||||||
// a flag denoting if this object is compound or not
|
|
||||||
// the class type: the namespace of the tag
|
|
||||||
// the length of the object, in bytes
|
|
||||||
|
|
||||||
// Here are some standard tags and classes
|
|
||||||
|
|
||||||
// ASN.1 tags represent the type of the following object.
|
|
||||||
const (
|
|
||||||
TagBoolean = 1
|
|
||||||
TagInteger = 2
|
|
||||||
TagBitString = 3
|
|
||||||
TagOctetString = 4
|
|
||||||
TagOID = 6
|
|
||||||
TagEnum = 10
|
|
||||||
TagUTF8String = 12
|
|
||||||
TagSequence = 16
|
|
||||||
TagSet = 17
|
|
||||||
TagPrintableString = 19
|
|
||||||
TagT61String = 20
|
|
||||||
TagIA5String = 22
|
|
||||||
TagUTCTime = 23
|
|
||||||
TagGeneralizedTime = 24
|
|
||||||
TagGeneralString = 27
|
|
||||||
)
|
|
||||||
|
|
||||||
// ASN.1 class types represent the namespace of the tag.
|
|
||||||
const (
|
|
||||||
ClassUniversal = 0
|
|
||||||
ClassApplication = 1
|
|
||||||
ClassContextSpecific = 2
|
|
||||||
ClassPrivate = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
type tagAndLength struct {
|
|
||||||
class, tag, length int
|
|
||||||
isCompound bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
|
|
||||||
// of" and "in addition to". When not specified, every primitive type has a
|
|
||||||
// default tag in the UNIVERSAL class.
|
|
||||||
//
|
|
||||||
// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
|
|
||||||
// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
|
|
||||||
// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
|
|
||||||
//
|
|
||||||
// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
|
|
||||||
// /additional/ tag would wrap the default tag. This explicit tag will have the
|
|
||||||
// compound flag set.
|
|
||||||
//
|
|
||||||
// (This is used in order to remove ambiguity with optional elements.)
|
|
||||||
//
|
|
||||||
// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
|
|
||||||
// don't support that here. We support a single layer of EXPLICIT or IMPLICIT
|
|
||||||
// tagging with tag strings on the fields of a structure.
|
|
||||||
|
|
||||||
// fieldParameters is the parsed representation of tag string from a structure field.
|
|
||||||
type fieldParameters struct {
|
|
||||||
optional bool // true iff the field is OPTIONAL
|
|
||||||
explicit bool // true iff an EXPLICIT tag is in use.
|
|
||||||
application bool // true iff an APPLICATION tag is in use.
|
|
||||||
defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
|
|
||||||
tag *int // the EXPLICIT or IMPLICIT tag (maybe nil).
|
|
||||||
stringType int // the string tag to use when marshaling.
|
|
||||||
timeType int // the time tag to use when marshaling.
|
|
||||||
set bool // true iff this should be encoded as a SET
|
|
||||||
omitEmpty bool // true iff this should be omitted if empty when marshaling.
|
|
||||||
|
|
||||||
// Invariants:
|
|
||||||
// if explicit is set, tag is non-nil.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a tag string with the format specified in the package comment,
|
|
||||||
// parseFieldParameters will parse it into a fieldParameters structure,
|
|
||||||
// ignoring unknown parts of the string.
|
|
||||||
func parseFieldParameters(str string) (ret fieldParameters) {
|
|
||||||
for _, part := range strings.Split(str, ",") {
|
|
||||||
switch {
|
|
||||||
case part == "optional":
|
|
||||||
ret.optional = true
|
|
||||||
case part == "explicit":
|
|
||||||
ret.explicit = true
|
|
||||||
if ret.tag == nil {
|
|
||||||
ret.tag = new(int)
|
|
||||||
}
|
|
||||||
case part == "generalized":
|
|
||||||
ret.timeType = TagGeneralizedTime
|
|
||||||
case part == "utc":
|
|
||||||
ret.timeType = TagUTCTime
|
|
||||||
case part == "ia5":
|
|
||||||
ret.stringType = TagIA5String
|
|
||||||
// jtasn1 case below added
|
|
||||||
case part == "generalstring":
|
|
||||||
ret.stringType = TagGeneralString
|
|
||||||
case part == "printable":
|
|
||||||
ret.stringType = TagPrintableString
|
|
||||||
case part == "utf8":
|
|
||||||
ret.stringType = TagUTF8String
|
|
||||||
case strings.HasPrefix(part, "default:"):
|
|
||||||
i, err := strconv.ParseInt(part[8:], 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
ret.defaultValue = new(int64)
|
|
||||||
*ret.defaultValue = i
|
|
||||||
}
|
|
||||||
case strings.HasPrefix(part, "tag:"):
|
|
||||||
i, err := strconv.Atoi(part[4:])
|
|
||||||
if err == nil {
|
|
||||||
ret.tag = new(int)
|
|
||||||
*ret.tag = i
|
|
||||||
}
|
|
||||||
case part == "set":
|
|
||||||
ret.set = true
|
|
||||||
case part == "application":
|
|
||||||
ret.application = true
|
|
||||||
if ret.tag == nil {
|
|
||||||
ret.tag = new(int)
|
|
||||||
}
|
|
||||||
case part == "omitempty":
|
|
||||||
ret.omitEmpty = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a reflected Go type, getUniversalType returns the default tag number
|
|
||||||
// and expected compound flag.
|
|
||||||
func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
|
|
||||||
switch t {
|
|
||||||
case objectIdentifierType:
|
|
||||||
return TagOID, false, true
|
|
||||||
case bitStringType:
|
|
||||||
return TagBitString, false, true
|
|
||||||
case timeType:
|
|
||||||
return TagUTCTime, false, true
|
|
||||||
case enumeratedType:
|
|
||||||
return TagEnum, false, true
|
|
||||||
case bigIntType:
|
|
||||||
return TagInteger, false, true
|
|
||||||
}
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return TagBoolean, false, true
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return TagInteger, false, true
|
|
||||||
case reflect.Struct:
|
|
||||||
return TagSequence, true, true
|
|
||||||
case reflect.Slice:
|
|
||||||
if t.Elem().Kind() == reflect.Uint8 {
|
|
||||||
return TagOctetString, false, true
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(t.Name(), "SET") {
|
|
||||||
return TagSet, true, true
|
|
||||||
}
|
|
||||||
return TagSequence, true, true
|
|
||||||
case reflect.String:
|
|
||||||
return TagPrintableString, false, true
|
|
||||||
}
|
|
||||||
return 0, false, false
|
|
||||||
}
|
|
659
vendor/github.com/jcmturner/gofork/encoding/asn1/marshal.go
generated
vendored
659
vendor/github.com/jcmturner/gofork/encoding/asn1/marshal.go
generated
vendored
@ -1,659 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package asn1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A forkableWriter is an in-memory buffer that can be
|
|
||||||
// 'forked' to create new forkableWriters that bracket the
|
|
||||||
// original. After
|
|
||||||
// pre, post := w.fork()
|
|
||||||
// the overall sequence of bytes represented is logically w+pre+post.
|
|
||||||
type forkableWriter struct {
|
|
||||||
*bytes.Buffer
|
|
||||||
pre, post *forkableWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func newForkableWriter() *forkableWriter {
|
|
||||||
return &forkableWriter{new(bytes.Buffer), nil, nil}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *forkableWriter) fork() (pre, post *forkableWriter) {
|
|
||||||
if f.pre != nil || f.post != nil {
|
|
||||||
panic("have already forked")
|
|
||||||
}
|
|
||||||
f.pre = newForkableWriter()
|
|
||||||
f.post = newForkableWriter()
|
|
||||||
return f.pre, f.post
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *forkableWriter) Len() (l int) {
|
|
||||||
l += f.Buffer.Len()
|
|
||||||
if f.pre != nil {
|
|
||||||
l += f.pre.Len()
|
|
||||||
}
|
|
||||||
if f.post != nil {
|
|
||||||
l += f.post.Len()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
|
|
||||||
n, err = out.Write(f.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var nn int
|
|
||||||
|
|
||||||
if f.pre != nil {
|
|
||||||
nn, err = f.pre.writeTo(out)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.post != nil {
|
|
||||||
nn, err = f.post.writeTo(out)
|
|
||||||
n += nn
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBase128Int(out *forkableWriter, n int64) (err error) {
|
|
||||||
if n == 0 {
|
|
||||||
err = out.WriteByte(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l := 0
|
|
||||||
for i := n; i > 0; i >>= 7 {
|
|
||||||
l++
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := l - 1; i >= 0; i-- {
|
|
||||||
o := byte(n >> uint(i*7))
|
|
||||||
o &= 0x7f
|
|
||||||
if i != 0 {
|
|
||||||
o |= 0x80
|
|
||||||
}
|
|
||||||
err = out.WriteByte(o)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalInt64(out *forkableWriter, i int64) (err error) {
|
|
||||||
n := int64Length(i)
|
|
||||||
|
|
||||||
for ; n > 0; n-- {
|
|
||||||
err = out.WriteByte(byte(i >> uint((n-1)*8)))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func int64Length(i int64) (numBytes int) {
|
|
||||||
numBytes = 1
|
|
||||||
|
|
||||||
for i > 127 {
|
|
||||||
numBytes++
|
|
||||||
i >>= 8
|
|
||||||
}
|
|
||||||
|
|
||||||
for i < -128 {
|
|
||||||
numBytes++
|
|
||||||
i >>= 8
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
|
|
||||||
if n.Sign() < 0 {
|
|
||||||
// A negative number has to be converted to two's-complement
|
|
||||||
// form. So we'll subtract 1 and invert. If the
|
|
||||||
// most-significant-bit isn't set then we'll need to pad the
|
|
||||||
// beginning with 0xff in order to keep the number negative.
|
|
||||||
nMinus1 := new(big.Int).Neg(n)
|
|
||||||
nMinus1.Sub(nMinus1, bigOne)
|
|
||||||
bytes := nMinus1.Bytes()
|
|
||||||
for i := range bytes {
|
|
||||||
bytes[i] ^= 0xff
|
|
||||||
}
|
|
||||||
if len(bytes) == 0 || bytes[0]&0x80 == 0 {
|
|
||||||
err = out.WriteByte(0xff)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err = out.Write(bytes)
|
|
||||||
} else if n.Sign() == 0 {
|
|
||||||
// Zero is written as a single 0 zero rather than no bytes.
|
|
||||||
err = out.WriteByte(0x00)
|
|
||||||
} else {
|
|
||||||
bytes := n.Bytes()
|
|
||||||
if len(bytes) > 0 && bytes[0]&0x80 != 0 {
|
|
||||||
// We'll have to pad this with 0x00 in order to stop it
|
|
||||||
// looking like a negative number.
|
|
||||||
err = out.WriteByte(0)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err = out.Write(bytes)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalLength(out *forkableWriter, i int) (err error) {
|
|
||||||
n := lengthLength(i)
|
|
||||||
|
|
||||||
for ; n > 0; n-- {
|
|
||||||
err = out.WriteByte(byte(i >> uint((n-1)*8)))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func lengthLength(i int) (numBytes int) {
|
|
||||||
numBytes = 1
|
|
||||||
for i > 255 {
|
|
||||||
numBytes++
|
|
||||||
i >>= 8
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
|
|
||||||
b := uint8(t.class) << 6
|
|
||||||
if t.isCompound {
|
|
||||||
b |= 0x20
|
|
||||||
}
|
|
||||||
if t.tag >= 31 {
|
|
||||||
b |= 0x1f
|
|
||||||
err = out.WriteByte(b)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = marshalBase128Int(out, int64(t.tag))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b |= uint8(t.tag)
|
|
||||||
err = out.WriteByte(b)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.length >= 128 {
|
|
||||||
l := lengthLength(t.length)
|
|
||||||
err = out.WriteByte(0x80 | byte(l))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = marshalLength(out, t.length)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = out.WriteByte(byte(t.length))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBitString(out *forkableWriter, b BitString) (err error) {
|
|
||||||
paddingBits := byte((8 - b.BitLength%8) % 8)
|
|
||||||
err = out.WriteByte(paddingBits)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = out.Write(b.Bytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
|
|
||||||
if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
|
|
||||||
return StructuralError{"invalid object identifier"}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 2; i < len(oid); i++ {
|
|
||||||
err = marshalBase128Int(out, int64(oid[i]))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalPrintableString(out *forkableWriter, s string) (err error) {
|
|
||||||
b := []byte(s)
|
|
||||||
for _, c := range b {
|
|
||||||
if !isPrintable(c) {
|
|
||||||
return StructuralError{"PrintableString contains invalid character"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = out.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalIA5String(out *forkableWriter, s string) (err error) {
|
|
||||||
b := []byte(s)
|
|
||||||
for _, c := range b {
|
|
||||||
if c > 127 {
|
|
||||||
return StructuralError{"IA5String contains invalid character"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = out.Write(b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalUTF8String(out *forkableWriter, s string) (err error) {
|
|
||||||
_, err = out.Write([]byte(s))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalTwoDigits(out *forkableWriter, v int) (err error) {
|
|
||||||
err = out.WriteByte(byte('0' + (v/10)%10))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return out.WriteByte(byte('0' + v%10))
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalFourDigits(out *forkableWriter, v int) (err error) {
|
|
||||||
var bytes [4]byte
|
|
||||||
for i := range bytes {
|
|
||||||
bytes[3-i] = '0' + byte(v%10)
|
|
||||||
v /= 10
|
|
||||||
}
|
|
||||||
_, err = out.Write(bytes[:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func outsideUTCRange(t time.Time) bool {
|
|
||||||
year := t.Year()
|
|
||||||
return year < 1950 || year >= 2050
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
|
|
||||||
year := t.Year()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case 1950 <= year && year < 2000:
|
|
||||||
err = marshalTwoDigits(out, year-1900)
|
|
||||||
case 2000 <= year && year < 2050:
|
|
||||||
err = marshalTwoDigits(out, year-2000)
|
|
||||||
default:
|
|
||||||
return StructuralError{"cannot represent time as UTCTime"}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return marshalTimeCommon(out, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) {
|
|
||||||
year := t.Year()
|
|
||||||
if year < 0 || year > 9999 {
|
|
||||||
return StructuralError{"cannot represent time as GeneralizedTime"}
|
|
||||||
}
|
|
||||||
if err = marshalFourDigits(out, year); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return marshalTimeCommon(out, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) {
|
|
||||||
_, month, day := t.Date()
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, int(month))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, day)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hour, min, sec := t.Clock()
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, hour)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, min)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, sec)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, offset := t.Zone()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case offset/60 == 0:
|
|
||||||
err = out.WriteByte('Z')
|
|
||||||
return
|
|
||||||
case offset > 0:
|
|
||||||
err = out.WriteByte('+')
|
|
||||||
case offset < 0:
|
|
||||||
err = out.WriteByte('-')
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetMinutes := offset / 60
|
|
||||||
if offsetMinutes < 0 {
|
|
||||||
offsetMinutes = -offsetMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, offsetMinutes/60)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTwoDigits(out, offsetMinutes%60)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func stripTagAndLength(in []byte) []byte {
|
|
||||||
_, offset, err := parseTagAndLength(in, 0)
|
|
||||||
if err != nil {
|
|
||||||
return in
|
|
||||||
}
|
|
||||||
return in[offset:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
|
|
||||||
switch value.Type() {
|
|
||||||
case flagType:
|
|
||||||
return nil
|
|
||||||
case timeType:
|
|
||||||
t := value.Interface().(time.Time)
|
|
||||||
if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
|
|
||||||
return marshalGeneralizedTime(out, t)
|
|
||||||
} else {
|
|
||||||
return marshalUTCTime(out, t)
|
|
||||||
}
|
|
||||||
case bitStringType:
|
|
||||||
return marshalBitString(out, value.Interface().(BitString))
|
|
||||||
case objectIdentifierType:
|
|
||||||
return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
|
|
||||||
case bigIntType:
|
|
||||||
return marshalBigInt(out, value.Interface().(*big.Int))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := value; v.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
if v.Bool() {
|
|
||||||
return out.WriteByte(255)
|
|
||||||
} else {
|
|
||||||
return out.WriteByte(0)
|
|
||||||
}
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return marshalInt64(out, v.Int())
|
|
||||||
case reflect.Struct:
|
|
||||||
t := v.Type()
|
|
||||||
|
|
||||||
startingField := 0
|
|
||||||
|
|
||||||
// If the first element of the structure is a non-empty
|
|
||||||
// RawContents, then we don't bother serializing the rest.
|
|
||||||
if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
|
|
||||||
s := v.Field(0)
|
|
||||||
if s.Len() > 0 {
|
|
||||||
bytes := make([]byte, s.Len())
|
|
||||||
for i := 0; i < s.Len(); i++ {
|
|
||||||
bytes[i] = uint8(s.Index(i).Uint())
|
|
||||||
}
|
|
||||||
/* The RawContents will contain the tag and
|
|
||||||
* length fields but we'll also be writing
|
|
||||||
* those ourselves, so we strip them out of
|
|
||||||
* bytes */
|
|
||||||
_, err = out.Write(stripTagAndLength(bytes))
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
startingField = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := startingField; i < t.NumField(); i++ {
|
|
||||||
var pre *forkableWriter
|
|
||||||
pre, out = out.fork()
|
|
||||||
err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case reflect.Slice:
|
|
||||||
sliceType := v.Type()
|
|
||||||
if sliceType.Elem().Kind() == reflect.Uint8 {
|
|
||||||
bytes := make([]byte, v.Len())
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
bytes[i] = uint8(v.Index(i).Uint())
|
|
||||||
}
|
|
||||||
_, err = out.Write(bytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// jtasn1 Pass on the tags to the members but need to unset explicit switch and implicit value
|
|
||||||
//var fp fieldParameters
|
|
||||||
params.explicit = false
|
|
||||||
params.tag = nil
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
var pre *forkableWriter
|
|
||||||
pre, out = out.fork()
|
|
||||||
err = marshalField(pre, v.Index(i), params)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case reflect.String:
|
|
||||||
switch params.stringType {
|
|
||||||
case TagIA5String:
|
|
||||||
return marshalIA5String(out, v.String())
|
|
||||||
case TagPrintableString:
|
|
||||||
return marshalPrintableString(out, v.String())
|
|
||||||
default:
|
|
||||||
return marshalUTF8String(out, v.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return StructuralError{"unknown Go type"}
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
|
|
||||||
if !v.IsValid() {
|
|
||||||
return fmt.Errorf("asn1: cannot marshal nil value")
|
|
||||||
}
|
|
||||||
// If the field is an interface{} then recurse into it.
|
|
||||||
if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
|
|
||||||
return marshalField(out, v.Elem(), params)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
|
|
||||||
defaultValue := reflect.New(v.Type()).Elem()
|
|
||||||
defaultValue.SetInt(*params.defaultValue)
|
|
||||||
|
|
||||||
if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no default value is given then the zero value for the type is
|
|
||||||
// assumed to be the default value. This isn't obviously the correct
|
|
||||||
// behaviour, but it's what Go has traditionally done.
|
|
||||||
if params.optional && params.defaultValue == nil {
|
|
||||||
if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Type() == rawValueType {
|
|
||||||
rv := v.Interface().(RawValue)
|
|
||||||
if len(rv.FullBytes) != 0 {
|
|
||||||
_, err = out.Write(rv.FullBytes)
|
|
||||||
} else {
|
|
||||||
err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = out.Write(rv.Bytes)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tag, isCompound, ok := getUniversalType(v.Type())
|
|
||||||
if !ok {
|
|
||||||
err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
class := ClassUniversal
|
|
||||||
|
|
||||||
if params.timeType != 0 && tag != TagUTCTime {
|
|
||||||
return StructuralError{"explicit time type given to non-time member"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jtasn1 updated to allow slices of strings
|
|
||||||
if params.stringType != 0 && !(tag == TagPrintableString || (v.Kind() == reflect.Slice && tag == 16 && v.Type().Elem().Kind() == reflect.String)) {
|
|
||||||
return StructuralError{"explicit string type given to non-string member"}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tag {
|
|
||||||
case TagPrintableString:
|
|
||||||
if params.stringType == 0 {
|
|
||||||
// This is a string without an explicit string type. We'll use
|
|
||||||
// a PrintableString if the character set in the string is
|
|
||||||
// sufficiently limited, otherwise we'll use a UTF8String.
|
|
||||||
for _, r := range v.String() {
|
|
||||||
if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
|
|
||||||
if !utf8.ValidString(v.String()) {
|
|
||||||
return errors.New("asn1: string not valid UTF-8")
|
|
||||||
}
|
|
||||||
tag = TagUTF8String
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tag = params.stringType
|
|
||||||
}
|
|
||||||
case TagUTCTime:
|
|
||||||
if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
|
|
||||||
tag = TagGeneralizedTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if params.set {
|
|
||||||
if tag != TagSequence {
|
|
||||||
return StructuralError{"non sequence tagged as set"}
|
|
||||||
}
|
|
||||||
tag = TagSet
|
|
||||||
}
|
|
||||||
|
|
||||||
tags, body := out.fork()
|
|
||||||
|
|
||||||
err = marshalBody(body, v, params)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
bodyLen := body.Len()
|
|
||||||
|
|
||||||
var explicitTag *forkableWriter
|
|
||||||
if params.explicit {
|
|
||||||
explicitTag, tags = tags.fork()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !params.explicit && params.tag != nil {
|
|
||||||
// implicit tag.
|
|
||||||
tag = *params.tag
|
|
||||||
class = ClassContextSpecific
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if params.explicit {
|
|
||||||
err = marshalTagAndLength(explicitTag, tagAndLength{
|
|
||||||
class: ClassContextSpecific,
|
|
||||||
tag: *params.tag,
|
|
||||||
length: bodyLen + tags.Len(),
|
|
||||||
isCompound: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal returns the ASN.1 encoding of val.
|
|
||||||
//
|
|
||||||
// In addition to the struct tags recognised by Unmarshal, the following can be
|
|
||||||
// used:
|
|
||||||
//
|
|
||||||
// ia5: causes strings to be marshaled as ASN.1, IA5 strings
|
|
||||||
// omitempty: causes empty slices to be skipped
|
|
||||||
// printable: causes strings to be marshaled as ASN.1, PrintableString strings.
|
|
||||||
// utf8: causes strings to be marshaled as ASN.1, UTF8 strings
|
|
||||||
func Marshal(val interface{}) ([]byte, error) {
|
|
||||||
var out bytes.Buffer
|
|
||||||
v := reflect.ValueOf(val)
|
|
||||||
f := newForkableWriter()
|
|
||||||
err := marshalField(f, v, fieldParameters{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = f.writeTo(&out)
|
|
||||||
return out.Bytes(), err
|
|
||||||
}
|
|
98
vendor/github.com/jcmturner/gofork/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
98
vendor/github.com/jcmturner/gofork/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
@ -1,98 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
|
|
||||||
2898 / PKCS #5 v2.0.
|
|
||||||
|
|
||||||
A key derivation function is useful when encrypting data based on a password
|
|
||||||
or any other not-fully-random data. It uses a pseudorandom function to derive
|
|
||||||
a secure encryption key based on the password.
|
|
||||||
|
|
||||||
While v2.0 of the standard defines only one pseudorandom function to use,
|
|
||||||
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
|
|
||||||
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
|
||||||
choose, you can pass the `New` functions from the different SHA packages to
|
|
||||||
pbkdf2.Key.
|
|
||||||
*/
|
|
||||||
package pbkdf2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Key derives a key from the password, salt and iteration count, returning a
|
|
||||||
// []byte of length keylen that can be used as cryptographic key. The key is
|
|
||||||
// derived based on the method described as PBKDF2 with the HMAC variant using
|
|
||||||
// the supplied hash function.
|
|
||||||
//
|
|
||||||
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
|
|
||||||
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
|
|
||||||
// doing:
|
|
||||||
//
|
|
||||||
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
|
|
||||||
//
|
|
||||||
// Remember to get a good random salt. At least 8 bytes is recommended by the
|
|
||||||
// RFC.
|
|
||||||
//
|
|
||||||
// Using a higher iteration count will increase the cost of an exhaustive
|
|
||||||
// search but will also make derivation proportionally slower.
|
|
||||||
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
|
||||||
return Key64(password, salt, int64(iter), int64(keyLen), h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key64 derives a key from the password, salt and iteration count, returning a
|
|
||||||
// []byte of length keylen that can be used as cryptographic key. Key64 uses
|
|
||||||
// int64 for the iteration count and key length to allow larger values.
|
|
||||||
// The key is derived based on the method described as PBKDF2 with the HMAC
|
|
||||||
// variant using the supplied hash function.
|
|
||||||
//
|
|
||||||
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
|
|
||||||
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
|
|
||||||
// doing:
|
|
||||||
//
|
|
||||||
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
|
|
||||||
//
|
|
||||||
// Remember to get a good random salt. At least 8 bytes is recommended by the
|
|
||||||
// RFC.
|
|
||||||
//
|
|
||||||
// Using a higher iteration count will increase the cost of an exhaustive
|
|
||||||
// search but will also make derivation proportionally slower.
|
|
||||||
func Key64(password, salt []byte, iter, keyLen int64, h func() hash.Hash) []byte {
|
|
||||||
prf := hmac.New(h, password)
|
|
||||||
hashLen := int64(prf.Size())
|
|
||||||
numBlocks := (keyLen + hashLen - 1) / hashLen
|
|
||||||
|
|
||||||
var buf [4]byte
|
|
||||||
dk := make([]byte, 0, numBlocks*hashLen)
|
|
||||||
U := make([]byte, hashLen)
|
|
||||||
for block := int64(1); block <= numBlocks; block++ {
|
|
||||||
// N.B.: || means concatenation, ^ means XOR
|
|
||||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
|
||||||
// U_1 = PRF(password, salt || uint(i))
|
|
||||||
prf.Reset()
|
|
||||||
prf.Write(salt)
|
|
||||||
buf[0] = byte(block >> 24)
|
|
||||||
buf[1] = byte(block >> 16)
|
|
||||||
buf[2] = byte(block >> 8)
|
|
||||||
buf[3] = byte(block)
|
|
||||||
prf.Write(buf[:4])
|
|
||||||
dk = prf.Sum(dk)
|
|
||||||
T := dk[int64(len(dk))-hashLen:]
|
|
||||||
copy(U, T)
|
|
||||||
|
|
||||||
// U_n = PRF(password, U_(n-1))
|
|
||||||
for n := int64(2); n <= iter; n++ {
|
|
||||||
prf.Reset()
|
|
||||||
prf.Write(U)
|
|
||||||
U = U[:0]
|
|
||||||
U = prf.Sum(U)
|
|
||||||
for x := range U {
|
|
||||||
T[x] ^= U[x]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dk[:keyLen]
|
|
||||||
}
|
|
201
vendor/github.com/jcmturner/goidentity/v6/LICENSE
generated
vendored
201
vendor/github.com/jcmturner/goidentity/v6/LICENSE
generated
vendored
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
7
vendor/github.com/jcmturner/goidentity/v6/README.md
generated
vendored
7
vendor/github.com/jcmturner/goidentity/v6/README.md
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
# goidentity
|
|
||||||
[![GoDoc](https://godoc.org/github.com/jcmturner/goidentity/v6?status.svg)](https://godoc.org/github.com/jcmturner/goidentity/v6) [![Go Report Card](https://goreportcard.com/badge/github.com/jcmturner/goidentity/v6)](https://goreportcard.com/report/github.com/jcmturner/goidentity/v6)
|
|
||||||
|
|
||||||
Please import as below
|
|
||||||
```
|
|
||||||
import "github.com/jcmturner/goidentity/v6"
|
|
||||||
```
|
|
6
vendor/github.com/jcmturner/goidentity/v6/authenticator.go
generated
vendored
6
vendor/github.com/jcmturner/goidentity/v6/authenticator.go
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
package goidentity
|
|
||||||
|
|
||||||
type Authenticator interface {
|
|
||||||
Authenticate() (Identity, bool, error)
|
|
||||||
Mechanism() string // gives the name of the type of authentication mechanism
|
|
||||||
}
|
|
8
vendor/github.com/jcmturner/goidentity/v6/go.mod
generated
vendored
8
vendor/github.com/jcmturner/goidentity/v6/go.mod
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
module github.com/jcmturner/goidentity/v6
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/hashicorp/go-uuid v1.0.2
|
|
||||||
github.com/stretchr/testify v1.4.0
|
|
||||||
)
|
|
12
vendor/github.com/jcmturner/goidentity/v6/go.sum
generated
vendored
12
vendor/github.com/jcmturner/goidentity/v6/go.sum
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
|
||||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
52
vendor/github.com/jcmturner/goidentity/v6/identity.go
generated
vendored
52
vendor/github.com/jcmturner/goidentity/v6/identity.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
package goidentity
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
CTXKey = "jcmturner/goidentity"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Identity interface {
|
|
||||||
UserName() string
|
|
||||||
SetUserName(s string)
|
|
||||||
Domain() string
|
|
||||||
SetDomain(s string)
|
|
||||||
DisplayName() string
|
|
||||||
SetDisplayName(s string)
|
|
||||||
Human() bool
|
|
||||||
SetHuman(b bool)
|
|
||||||
AuthTime() time.Time
|
|
||||||
SetAuthTime(t time.Time)
|
|
||||||
AuthzAttributes() []string
|
|
||||||
AddAuthzAttribute(a string)
|
|
||||||
RemoveAuthzAttribute(a string)
|
|
||||||
Authenticated() bool
|
|
||||||
SetAuthenticated(b bool)
|
|
||||||
Authorized(a string) bool
|
|
||||||
SessionID() string
|
|
||||||
Expired() bool
|
|
||||||
Attributes() map[string]interface{}
|
|
||||||
SetAttribute(k string, v interface{})
|
|
||||||
SetAttributes(map[string]interface{})
|
|
||||||
RemoveAttribute(k string)
|
|
||||||
Marshal() ([]byte, error)
|
|
||||||
Unmarshal([]byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddToHTTPRequestContext(id Identity, r *http.Request) *http.Request {
|
|
||||||
ctx := r.Context()
|
|
||||||
ctx = context.WithValue(ctx, CTXKey, id)
|
|
||||||
return r.WithContext(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromHTTPRequestContext(r *http.Request) Identity {
|
|
||||||
ctx := r.Context()
|
|
||||||
if id, ok := ctx.Value(CTXKey).(Identity); ok {
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
172
vendor/github.com/jcmturner/goidentity/v6/user.go
generated
vendored
172
vendor/github.com/jcmturner/goidentity/v6/user.go
generated
vendored
@ -1,172 +0,0 @@
|
|||||||
package goidentity
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"github.com/hashicorp/go-uuid"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
authenticated bool
|
|
||||||
domain string
|
|
||||||
userName string
|
|
||||||
displayName string
|
|
||||||
email string
|
|
||||||
human bool
|
|
||||||
groupMembership map[string]bool
|
|
||||||
authTime time.Time
|
|
||||||
sessionID string
|
|
||||||
expiry time.Time
|
|
||||||
attributes map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUser(username string) User {
|
|
||||||
uuid, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
uuid = "00unique-sess-ions-uuid-unavailable0"
|
|
||||||
}
|
|
||||||
return User{
|
|
||||||
userName: username,
|
|
||||||
groupMembership: make(map[string]bool),
|
|
||||||
sessionID: uuid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) UserName() string {
|
|
||||||
return u.userName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetUserName(s string) {
|
|
||||||
u.userName = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Domain() string {
|
|
||||||
return u.domain
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetDomain(s string) {
|
|
||||||
u.domain = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) DisplayName() string {
|
|
||||||
if u.displayName == "" {
|
|
||||||
return u.userName
|
|
||||||
}
|
|
||||||
return u.displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetDisplayName(s string) {
|
|
||||||
u.displayName = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Human() bool {
|
|
||||||
return u.human
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetHuman(b bool) {
|
|
||||||
u.human = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) AuthTime() time.Time {
|
|
||||||
return u.authTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetAuthTime(t time.Time) {
|
|
||||||
u.authTime = t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) AuthzAttributes() []string {
|
|
||||||
s := make([]string, len(u.groupMembership))
|
|
||||||
i := 0
|
|
||||||
for a := range u.groupMembership {
|
|
||||||
s[i] = a
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Authenticated() bool {
|
|
||||||
return u.authenticated
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetAuthenticated(b bool) {
|
|
||||||
u.authenticated = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) AddAuthzAttribute(a string) {
|
|
||||||
u.groupMembership[a] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) RemoveAuthzAttribute(a string) {
|
|
||||||
if _, ok := u.groupMembership[a]; !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
delete(u.groupMembership, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) EnableAuthzAttribute(a string) {
|
|
||||||
if enabled, ok := u.groupMembership[a]; ok && !enabled {
|
|
||||||
u.groupMembership[a] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) DisableAuthzAttribute(a string) {
|
|
||||||
if enabled, ok := u.groupMembership[a]; ok && enabled {
|
|
||||||
u.groupMembership[a] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Authorized(a string) bool {
|
|
||||||
if enabled, ok := u.groupMembership[a]; ok && enabled {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SessionID() string {
|
|
||||||
return u.sessionID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetExpiry(t time.Time) {
|
|
||||||
u.expiry = t
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Expired() bool {
|
|
||||||
if !u.expiry.IsZero() && time.Now().UTC().After(u.expiry) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Attributes() map[string]interface{} {
|
|
||||||
return u.attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetAttribute(k string, v interface{}) {
|
|
||||||
u.attributes[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) SetAttributes(a map[string]interface{}) {
|
|
||||||
u.attributes = a
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) RemoveAttribute(k string) {
|
|
||||||
delete(u.attributes, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Marshal() ([]byte, error) {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
enc := gob.NewEncoder(buf)
|
|
||||||
err := enc.Encode(u)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Unmarshal(b []byte) error {
|
|
||||||
buf := bytes.NewBuffer(b)
|
|
||||||
dec := gob.NewDecoder(buf)
|
|
||||||
return dec.Decode(u)
|
|
||||||
}
|
|
201
vendor/github.com/jcmturner/gokrb5/v8/LICENSE
generated
vendored
201
vendor/github.com/jcmturner/gokrb5/v8/LICENSE
generated
vendored
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
86
vendor/github.com/jcmturner/gokrb5/v8/asn1tools/tools.go
generated
vendored
86
vendor/github.com/jcmturner/gokrb5/v8/asn1tools/tools.go
generated
vendored
@ -1,86 +0,0 @@
|
|||||||
// Package asn1tools provides tools for managing ASN1 marshaled data.
|
|
||||||
package asn1tools
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jcmturner/gofork/encoding/asn1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MarshalLengthBytes returns the ASN1 encoded bytes for the length 'l'
|
|
||||||
//
|
|
||||||
// There are two forms: short (for lengths between 0 and 127), and long definite (for lengths between 0 and 2^1008 -1).
|
|
||||||
//
|
|
||||||
// Short form: One octet. Bit 8 has value "0" and bits 7-1 give the length.
|
|
||||||
//
|
|
||||||
// Long form: Two to 127 octets. Bit 8 of first octet has value "1" and bits 7-1 give the number of additional length octets. Second and following octets give the length, base 256, most significant digit first.
|
|
||||||
func MarshalLengthBytes(l int) []byte {
|
|
||||||
if l <= 127 {
|
|
||||||
return []byte{byte(l)}
|
|
||||||
}
|
|
||||||
var b []byte
|
|
||||||
p := 1
|
|
||||||
for i := 1; i < 127; {
|
|
||||||
b = append([]byte{byte((l % (p * 256)) / p)}, b...)
|
|
||||||
p = p * 256
|
|
||||||
l = l - l%p
|
|
||||||
if l <= 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return append([]byte{byte(128 + len(b))}, b...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLengthFromASN returns the length of a slice of ASN1 encoded bytes from the ASN1 length header it contains.
|
|
||||||
func GetLengthFromASN(b []byte) int {
|
|
||||||
if int(b[1]) <= 127 {
|
|
||||||
return int(b[1])
|
|
||||||
}
|
|
||||||
// The bytes that indicate the length
|
|
||||||
lb := b[2 : 2+int(b[1])-128]
|
|
||||||
base := 1
|
|
||||||
l := 0
|
|
||||||
for i := len(lb) - 1; i >= 0; i-- {
|
|
||||||
l += int(lb[i]) * base
|
|
||||||
base = base * 256
|
|
||||||
}
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNumberBytesInLengthHeader returns the number of bytes in the ASn1 header that indicate the length.
|
|
||||||
func GetNumberBytesInLengthHeader(b []byte) int {
|
|
||||||
if int(b[1]) <= 127 {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
// The bytes that indicate the length
|
|
||||||
return 1 + int(b[1]) - 128
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddASNAppTag adds an ASN1 encoding application tag value to the raw bytes provided.
|
|
||||||
func AddASNAppTag(b []byte, tag int) []byte {
|
|
||||||
r := asn1.RawValue{
|
|
||||||
Class: asn1.ClassApplication,
|
|
||||||
IsCompound: true,
|
|
||||||
Tag: tag,
|
|
||||||
Bytes: b,
|
|
||||||
}
|
|
||||||
ab, _ := asn1.Marshal(r)
|
|
||||||
return ab
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// The Marshal method of golang's asn1 package does not enable you to define wrapping the output in an application tag.
|
|
||||||
// This method adds that wrapping tag.
|
|
||||||
func AddASNAppTag(b []byte, tag int) []byte {
|
|
||||||
// The ASN1 wrapping consists of 2 bytes:
|
|
||||||
// 1st byte -> Identifier Octet - Application Tag
|
|
||||||
// 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here.
|
|
||||||
// Application Tag:
|
|
||||||
//| Bit: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|
|
||||||
//| Value: | 0 | 1 | 1 | From the RFC spec 4120 |
|
|
||||||
//| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value |
|
|
||||||
// Therefore the value of the byte is an integer = ( Application tag value + 96 )
|
|
||||||
//b = append(MarshalLengthBytes(int(b[1])+2), b...)
|
|
||||||
b = append(MarshalLengthBytes(len(b)), b...)
|
|
||||||
b = append([]byte{byte(96 + tag)}, b...)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
*/
|
|
182
vendor/github.com/jcmturner/gokrb5/v8/client/ASExchange.go
generated
vendored
182
vendor/github.com/jcmturner/gokrb5/v8/client/ASExchange.go
generated
vendored
@ -1,182 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/patype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ASExchange performs an AS exchange for the client to retrieve a TGT.
|
|
||||||
func (cl *Client) ASExchange(realm string, ASReq messages.ASReq, referral int) (messages.ASRep, error) {
|
|
||||||
if ok, err := cl.IsConfigured(); !ok {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.ConfigError, "AS Exchange cannot be performed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set PAData if required
|
|
||||||
err := setPAData(cl, nil, &ASReq)
|
|
||||||
if err != nil {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KRBMsgError, "AS Exchange Error: issue with setting PAData on AS_REQ")
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ASReq.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.EncodingError, "AS Exchange Error: failed marshaling AS_REQ")
|
|
||||||
}
|
|
||||||
var ASRep messages.ASRep
|
|
||||||
|
|
||||||
rb, err := cl.sendToKDC(b, realm)
|
|
||||||
if err != nil {
|
|
||||||
if e, ok := err.(messages.KRBError); ok {
|
|
||||||
switch e.ErrorCode {
|
|
||||||
case errorcode.KDC_ERR_PREAUTH_REQUIRED, errorcode.KDC_ERR_PREAUTH_FAILED:
|
|
||||||
// From now on assume this client will need to do this pre-auth and set the PAData
|
|
||||||
cl.settings.assumePreAuthentication = true
|
|
||||||
err = setPAData(cl, &e, &ASReq)
|
|
||||||
if err != nil {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KRBMsgError, "AS Exchange Error: failed setting AS_REQ PAData for pre-authentication required")
|
|
||||||
}
|
|
||||||
b, err := ASReq.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.EncodingError, "AS Exchange Error: failed marshaling AS_REQ with PAData")
|
|
||||||
}
|
|
||||||
rb, err = cl.sendToKDC(b, realm)
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(messages.KRBError); ok {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KDCError, "AS Exchange Error: kerberos error response from KDC")
|
|
||||||
}
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.NetworkingError, "AS Exchange Error: failed sending AS_REQ to KDC")
|
|
||||||
}
|
|
||||||
case errorcode.KDC_ERR_WRONG_REALM:
|
|
||||||
// Client referral https://tools.ietf.org/html/rfc6806.html#section-7
|
|
||||||
if referral > 5 {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KRBMsgError, "maximum number of client referrals exceeded")
|
|
||||||
}
|
|
||||||
referral++
|
|
||||||
return cl.ASExchange(e.CRealm, ASReq, referral)
|
|
||||||
default:
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KDCError, "AS Exchange Error: kerberos error response from KDC")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.NetworkingError, "AS Exchange Error: failed sending AS_REQ to KDC")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = ASRep.Unmarshal(rb)
|
|
||||||
if err != nil {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.EncodingError, "AS Exchange Error: failed to process the AS_REP")
|
|
||||||
}
|
|
||||||
if ok, err := ASRep.Verify(cl.Config, cl.Credentials, ASReq); !ok {
|
|
||||||
return messages.ASRep{}, krberror.Errorf(err, krberror.KRBMsgError, "AS Exchange Error: AS_REP is not valid or client password/keytab incorrect")
|
|
||||||
}
|
|
||||||
return ASRep, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPAData adds pre-authentication data to the AS_REQ.
|
|
||||||
func setPAData(cl *Client, krberr *messages.KRBError, ASReq *messages.ASReq) error {
|
|
||||||
if !cl.settings.DisablePAFXFAST() {
|
|
||||||
pa := types.PAData{PADataType: patype.PA_REQ_ENC_PA_REP}
|
|
||||||
ASReq.PAData = append(ASReq.PAData, pa)
|
|
||||||
}
|
|
||||||
if cl.settings.AssumePreAuthentication() {
|
|
||||||
// Identify the etype to use to encrypt the PA Data
|
|
||||||
var et etype.EType
|
|
||||||
var err error
|
|
||||||
var key types.EncryptionKey
|
|
||||||
var kvno int
|
|
||||||
if krberr == nil {
|
|
||||||
// This is not in response to an error from the KDC. It is preemptive or renewal
|
|
||||||
// There is no KRB Error that tells us the etype to use
|
|
||||||
etn := cl.settings.preAuthEType // Use the etype that may have previously been negotiated
|
|
||||||
if etn == 0 {
|
|
||||||
etn = int32(cl.Config.LibDefaults.PreferredPreauthTypes[0]) // Resort to config
|
|
||||||
}
|
|
||||||
et, err = crypto.GetEtype(etn)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncryptingError, "error getting etype for pre-auth encryption")
|
|
||||||
}
|
|
||||||
key, kvno, err = cl.Key(et, 0, nil)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncryptingError, "error getting key from credentials")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Get the etype to use from the PA data in the KRBError e-data
|
|
||||||
et, err = preAuthEType(krberr)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncryptingError, "error getting etype for pre-auth encryption")
|
|
||||||
}
|
|
||||||
cl.settings.preAuthEType = et.GetETypeID() // Set the etype that has been defined for potential future use
|
|
||||||
key, kvno, err = cl.Key(et, 0, krberr)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncryptingError, "error getting key from credentials")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Generate the PA data
|
|
||||||
paTSb, err := types.GetPAEncTSEncAsnMarshalled()
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.KRBMsgError, "error creating PAEncTSEnc for Pre-Authentication")
|
|
||||||
}
|
|
||||||
paEncTS, err := crypto.GetEncryptedData(paTSb, key, keyusage.AS_REQ_PA_ENC_TIMESTAMP, kvno)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncryptingError, "error encrypting pre-authentication timestamp")
|
|
||||||
}
|
|
||||||
pb, err := paEncTS.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.EncodingError, "error marshaling the PAEncTSEnc encrypted data")
|
|
||||||
}
|
|
||||||
pa := types.PAData{
|
|
||||||
PADataType: patype.PA_ENC_TIMESTAMP,
|
|
||||||
PADataValue: pb,
|
|
||||||
}
|
|
||||||
// Look for and delete any exiting patype.PA_ENC_TIMESTAMP
|
|
||||||
for i, pa := range ASReq.PAData {
|
|
||||||
if pa.PADataType == patype.PA_ENC_TIMESTAMP {
|
|
||||||
ASReq.PAData[i] = ASReq.PAData[len(ASReq.PAData)-1]
|
|
||||||
ASReq.PAData = ASReq.PAData[:len(ASReq.PAData)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASReq.PAData = append(ASReq.PAData, pa)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// preAuthEType establishes what encryption type to use for pre-authentication from the KRBError returned from the KDC.
|
|
||||||
func preAuthEType(krberr *messages.KRBError) (etype etype.EType, err error) {
|
|
||||||
//RFC 4120 5.2.7.5 covers the preference order of ETYPE-INFO2 and ETYPE-INFO.
|
|
||||||
var etypeID int32
|
|
||||||
var pas types.PADataSequence
|
|
||||||
e := pas.Unmarshal(krberr.EData)
|
|
||||||
if e != nil {
|
|
||||||
err = krberror.Errorf(e, krberror.EncodingError, "error unmashalling KRBError data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Loop:
|
|
||||||
for _, pa := range pas {
|
|
||||||
switch pa.PADataType {
|
|
||||||
case patype.PA_ETYPE_INFO2:
|
|
||||||
info, e := pa.GetETypeInfo2()
|
|
||||||
if e != nil {
|
|
||||||
err = krberror.Errorf(e, krberror.EncodingError, "error unmashalling ETYPE-INFO2 data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
etypeID = info[0].EType
|
|
||||||
break Loop
|
|
||||||
case patype.PA_ETYPE_INFO:
|
|
||||||
info, e := pa.GetETypeInfo()
|
|
||||||
if e != nil {
|
|
||||||
err = krberror.Errorf(e, krberror.EncodingError, "error unmashalling ETYPE-INFO data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
etypeID = info[0].EType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
etype, e = crypto.GetEtype(etypeID)
|
|
||||||
if e != nil {
|
|
||||||
err = krberror.Errorf(e, krberror.EncryptingError, "error creating etype")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return etype, nil
|
|
||||||
}
|
|
103
vendor/github.com/jcmturner/gokrb5/v8/client/TGSExchange.go
generated
vendored
103
vendor/github.com/jcmturner/gokrb5/v8/client/TGSExchange.go
generated
vendored
@ -1,103 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/flags"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/nametype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TGSREQGenerateAndExchange generates the TGS_REQ and performs a TGS exchange to retrieve a ticket to the specified SPN.
|
|
||||||
func (cl *Client) TGSREQGenerateAndExchange(spn types.PrincipalName, kdcRealm string, tgt messages.Ticket, sessionKey types.EncryptionKey, renewal bool) (tgsReq messages.TGSReq, tgsRep messages.TGSRep, err error) {
|
|
||||||
tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), kdcRealm, cl.Config, tgt, sessionKey, spn, renewal)
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.KRBMsgError, "TGS Exchange Error: failed to generate a new TGS_REQ")
|
|
||||||
}
|
|
||||||
return cl.TGSExchange(tgsReq, kdcRealm, tgsRep.Ticket, sessionKey, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TGSExchange exchanges the provided TGS_REQ with the KDC to retrieve a TGS_REP.
|
|
||||||
// Referrals are automatically handled.
|
|
||||||
// The client's cache is updated with the ticket received.
|
|
||||||
func (cl *Client) TGSExchange(tgsReq messages.TGSReq, kdcRealm string, tgt messages.Ticket, sessionKey types.EncryptionKey, referral int) (messages.TGSReq, messages.TGSRep, error) {
|
|
||||||
var tgsRep messages.TGSRep
|
|
||||||
b, err := tgsReq.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.EncodingError, "TGS Exchange Error: failed to marshal TGS_REQ")
|
|
||||||
}
|
|
||||||
r, err := cl.sendToKDC(b, kdcRealm)
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(messages.KRBError); ok {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.KDCError, "TGS Exchange Error: kerberos error response from KDC when requesting for %s", tgsReq.ReqBody.SName.PrincipalNameString())
|
|
||||||
}
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.NetworkingError, "TGS Exchange Error: issue sending TGS_REQ to KDC")
|
|
||||||
}
|
|
||||||
err = tgsRep.Unmarshal(r)
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.EncodingError, "TGS Exchange Error: failed to process the TGS_REP")
|
|
||||||
}
|
|
||||||
err = tgsRep.DecryptEncPart(sessionKey)
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.EncodingError, "TGS Exchange Error: failed to process the TGS_REP")
|
|
||||||
}
|
|
||||||
if ok, err := tgsRep.Verify(cl.Config, tgsReq); !ok {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.EncodingError, "TGS Exchange Error: TGS_REP is not valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if tgsRep.Ticket.SName.NameString[0] == "krbtgt" && !tgsRep.Ticket.SName.Equal(tgsReq.ReqBody.SName) {
|
|
||||||
if referral > 5 {
|
|
||||||
return tgsReq, tgsRep, krberror.Errorf(err, krberror.KRBMsgError, "TGS Exchange Error: maximum number of referrals exceeded")
|
|
||||||
}
|
|
||||||
// Server referral https://tools.ietf.org/html/rfc6806.html#section-8
|
|
||||||
// The TGS Rep contains a TGT for another domain as the service resides in that domain.
|
|
||||||
cl.addSession(tgsRep.Ticket, tgsRep.DecryptedEncPart)
|
|
||||||
realm := tgsRep.Ticket.SName.NameString[len(tgsRep.Ticket.SName.NameString)-1]
|
|
||||||
referral++
|
|
||||||
if types.IsFlagSet(&tgsReq.ReqBody.KDCOptions, flags.EncTktInSkey) && len(tgsReq.ReqBody.AdditionalTickets) > 0 {
|
|
||||||
tgsReq, err = messages.NewUser2UserTGSReq(cl.Credentials.CName(), kdcRealm, cl.Config, tgt, sessionKey, tgsReq.ReqBody.SName, tgsReq.Renewal, tgsReq.ReqBody.AdditionalTickets[0])
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), realm, cl.Config, tgsRep.Ticket, tgsRep.DecryptedEncPart.Key, tgsReq.ReqBody.SName, tgsReq.Renewal)
|
|
||||||
if err != nil {
|
|
||||||
return tgsReq, tgsRep, err
|
|
||||||
}
|
|
||||||
return cl.TGSExchange(tgsReq, realm, tgsRep.Ticket, tgsRep.DecryptedEncPart.Key, referral)
|
|
||||||
}
|
|
||||||
cl.cache.addEntry(
|
|
||||||
tgsRep.Ticket,
|
|
||||||
tgsRep.DecryptedEncPart.AuthTime,
|
|
||||||
tgsRep.DecryptedEncPart.StartTime,
|
|
||||||
tgsRep.DecryptedEncPart.EndTime,
|
|
||||||
tgsRep.DecryptedEncPart.RenewTill,
|
|
||||||
tgsRep.DecryptedEncPart.Key,
|
|
||||||
)
|
|
||||||
cl.Log("ticket added to cache for %s (EndTime: %v)", tgsRep.Ticket.SName.PrincipalNameString(), tgsRep.DecryptedEncPart.EndTime)
|
|
||||||
return tgsReq, tgsRep, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetServiceTicket makes a request to get a service ticket for the SPN specified
|
|
||||||
// SPN format: <SERVICE>/<FQDN> Eg. HTTP/www.example.com
|
|
||||||
// The ticket will be added to the client's ticket cache
|
|
||||||
func (cl *Client) GetServiceTicket(spn string) (messages.Ticket, types.EncryptionKey, error) {
|
|
||||||
var tkt messages.Ticket
|
|
||||||
var skey types.EncryptionKey
|
|
||||||
if tkt, skey, ok := cl.GetCachedTicket(spn); ok {
|
|
||||||
// Already a valid ticket in the cache
|
|
||||||
return tkt, skey, nil
|
|
||||||
}
|
|
||||||
princ := types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, spn)
|
|
||||||
realm := cl.Config.ResolveRealm(princ.NameString[len(princ.NameString)-1])
|
|
||||||
|
|
||||||
tgt, skey, err := cl.sessionTGT(realm)
|
|
||||||
if err != nil {
|
|
||||||
return tkt, skey, err
|
|
||||||
}
|
|
||||||
_, tgsRep, err := cl.TGSREQGenerateAndExchange(princ, realm, tgt, skey, false)
|
|
||||||
if err != nil {
|
|
||||||
return tkt, skey, err
|
|
||||||
}
|
|
||||||
return tgsRep.Ticket, tgsRep.DecryptedEncPart.Key, nil
|
|
||||||
}
|
|
134
vendor/github.com/jcmturner/gokrb5/v8/client/cache.go
generated
vendored
134
vendor/github.com/jcmturner/gokrb5/v8/client/cache.go
generated
vendored
@ -1,134 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cache for service tickets held by the client.
|
|
||||||
type Cache struct {
|
|
||||||
Entries map[string]CacheEntry
|
|
||||||
mux sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheEntry holds details for a cache entry.
|
|
||||||
type CacheEntry struct {
|
|
||||||
SPN string
|
|
||||||
Ticket messages.Ticket `json:"-"`
|
|
||||||
AuthTime time.Time
|
|
||||||
StartTime time.Time
|
|
||||||
EndTime time.Time
|
|
||||||
RenewTill time.Time
|
|
||||||
SessionKey types.EncryptionKey `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCache creates a new client ticket cache instance.
|
|
||||||
func NewCache() *Cache {
|
|
||||||
return &Cache{
|
|
||||||
Entries: map[string]CacheEntry{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getEntry returns a cache entry that matches the SPN.
|
|
||||||
func (c *Cache) getEntry(spn string) (CacheEntry, bool) {
|
|
||||||
c.mux.RLock()
|
|
||||||
defer c.mux.RUnlock()
|
|
||||||
e, ok := (*c).Entries[spn]
|
|
||||||
return e, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON returns information about the cached service tickets in a JSON format.
|
|
||||||
func (c *Cache) JSON() (string, error) {
|
|
||||||
c.mux.RLock()
|
|
||||||
defer c.mux.RUnlock()
|
|
||||||
var es []CacheEntry
|
|
||||||
keys := make([]string, 0, len(c.Entries))
|
|
||||||
for k := range c.Entries {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
for _, k := range keys {
|
|
||||||
es = append(es, c.Entries[k])
|
|
||||||
}
|
|
||||||
b, err := json.MarshalIndent(&es, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// addEntry adds a ticket to the cache.
|
|
||||||
func (c *Cache) addEntry(tkt messages.Ticket, authTime, startTime, endTime, renewTill time.Time, sessionKey types.EncryptionKey) CacheEntry {
|
|
||||||
spn := tkt.SName.PrincipalNameString()
|
|
||||||
c.mux.Lock()
|
|
||||||
defer c.mux.Unlock()
|
|
||||||
(*c).Entries[spn] = CacheEntry{
|
|
||||||
SPN: spn,
|
|
||||||
Ticket: tkt,
|
|
||||||
AuthTime: authTime,
|
|
||||||
StartTime: startTime,
|
|
||||||
EndTime: endTime,
|
|
||||||
RenewTill: renewTill,
|
|
||||||
SessionKey: sessionKey,
|
|
||||||
}
|
|
||||||
return c.Entries[spn]
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear deletes all the cache entries
|
|
||||||
func (c *Cache) clear() {
|
|
||||||
c.mux.Lock()
|
|
||||||
defer c.mux.Unlock()
|
|
||||||
for k := range c.Entries {
|
|
||||||
delete(c.Entries, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveEntry removes the cache entry for the defined SPN.
|
|
||||||
func (c *Cache) RemoveEntry(spn string) {
|
|
||||||
c.mux.Lock()
|
|
||||||
defer c.mux.Unlock()
|
|
||||||
delete(c.Entries, spn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCachedTicket returns a ticket from the cache for the SPN.
|
|
||||||
// Only a ticket that is currently valid will be returned.
|
|
||||||
func (cl *Client) GetCachedTicket(spn string) (messages.Ticket, types.EncryptionKey, bool) {
|
|
||||||
if e, ok := cl.cache.getEntry(spn); ok {
|
|
||||||
//If within time window of ticket return it
|
|
||||||
if time.Now().UTC().After(e.StartTime) && time.Now().UTC().Before(e.EndTime) {
|
|
||||||
cl.Log("ticket received from cache for %s", spn)
|
|
||||||
return e.Ticket, e.SessionKey, true
|
|
||||||
} else if time.Now().UTC().Before(e.RenewTill) {
|
|
||||||
e, err := cl.renewTicket(e)
|
|
||||||
if err != nil {
|
|
||||||
return e.Ticket, e.SessionKey, false
|
|
||||||
}
|
|
||||||
return e.Ticket, e.SessionKey, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var tkt messages.Ticket
|
|
||||||
var key types.EncryptionKey
|
|
||||||
return tkt, key, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// renewTicket renews a cache entry ticket.
|
|
||||||
// To renew from outside the client package use GetCachedTicket
|
|
||||||
func (cl *Client) renewTicket(e CacheEntry) (CacheEntry, error) {
|
|
||||||
spn := e.Ticket.SName
|
|
||||||
_, _, err := cl.TGSREQGenerateAndExchange(spn, e.Ticket.Realm, e.Ticket, e.SessionKey, true)
|
|
||||||
if err != nil {
|
|
||||||
return e, err
|
|
||||||
}
|
|
||||||
e, ok := cl.cache.getEntry(e.Ticket.SName.PrincipalNameString())
|
|
||||||
if !ok {
|
|
||||||
return e, errors.New("ticket was not added to cache")
|
|
||||||
}
|
|
||||||
cl.Log("ticket renewed for %s (EndTime: %v)", spn.PrincipalNameString(), e.EndTime)
|
|
||||||
return e, nil
|
|
||||||
}
|
|
329
vendor/github.com/jcmturner/gokrb5/v8/client/client.go
generated
vendored
329
vendor/github.com/jcmturner/gokrb5/v8/client/client.go
generated
vendored
@ -1,329 +0,0 @@
|
|||||||
// Package client provides a client library and methods for Kerberos 5 authentication.
|
|
||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/config"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/credentials"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/nametype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/keytab"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client side configuration and state.
|
|
||||||
type Client struct {
|
|
||||||
Credentials *credentials.Credentials
|
|
||||||
Config *config.Config
|
|
||||||
settings *Settings
|
|
||||||
sessions *sessions
|
|
||||||
cache *Cache
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWithPassword creates a new client from a password credential.
|
|
||||||
// Set the realm to empty string to use the default realm from config.
|
|
||||||
func NewWithPassword(username, realm, password string, krb5conf *config.Config, settings ...func(*Settings)) *Client {
|
|
||||||
creds := credentials.New(username, realm)
|
|
||||||
return &Client{
|
|
||||||
Credentials: creds.WithPassword(password),
|
|
||||||
Config: krb5conf,
|
|
||||||
settings: NewSettings(settings...),
|
|
||||||
sessions: &sessions{
|
|
||||||
Entries: make(map[string]*session),
|
|
||||||
},
|
|
||||||
cache: NewCache(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWithKeytab creates a new client from a keytab credential.
|
|
||||||
func NewWithKeytab(username, realm string, kt *keytab.Keytab, krb5conf *config.Config, settings ...func(*Settings)) *Client {
|
|
||||||
creds := credentials.New(username, realm)
|
|
||||||
return &Client{
|
|
||||||
Credentials: creds.WithKeytab(kt),
|
|
||||||
Config: krb5conf,
|
|
||||||
settings: NewSettings(settings...),
|
|
||||||
sessions: &sessions{
|
|
||||||
Entries: make(map[string]*session),
|
|
||||||
},
|
|
||||||
cache: NewCache(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFromCCache create a client from a populated client cache.
|
|
||||||
//
|
|
||||||
// WARNING: A client created from CCache does not automatically renew TGTs and a failure will occur after the TGT expires.
|
|
||||||
func NewFromCCache(c *credentials.CCache, krb5conf *config.Config, settings ...func(*Settings)) (*Client, error) {
|
|
||||||
cl := &Client{
|
|
||||||
Credentials: c.GetClientCredentials(),
|
|
||||||
Config: krb5conf,
|
|
||||||
settings: NewSettings(settings...),
|
|
||||||
sessions: &sessions{
|
|
||||||
Entries: make(map[string]*session),
|
|
||||||
},
|
|
||||||
cache: NewCache(),
|
|
||||||
}
|
|
||||||
spn := types.PrincipalName{
|
|
||||||
NameType: nametype.KRB_NT_SRV_INST,
|
|
||||||
NameString: []string{"krbtgt", c.DefaultPrincipal.Realm},
|
|
||||||
}
|
|
||||||
cred, ok := c.GetEntry(spn)
|
|
||||||
if !ok {
|
|
||||||
return cl, errors.New("TGT not found in CCache")
|
|
||||||
}
|
|
||||||
var tgt messages.Ticket
|
|
||||||
err := tgt.Unmarshal(cred.Ticket)
|
|
||||||
if err != nil {
|
|
||||||
return cl, fmt.Errorf("TGT bytes in cache are not valid: %v", err)
|
|
||||||
}
|
|
||||||
cl.sessions.Entries[c.DefaultPrincipal.Realm] = &session{
|
|
||||||
realm: c.DefaultPrincipal.Realm,
|
|
||||||
authTime: cred.AuthTime,
|
|
||||||
endTime: cred.EndTime,
|
|
||||||
renewTill: cred.RenewTill,
|
|
||||||
tgt: tgt,
|
|
||||||
sessionKey: cred.Key,
|
|
||||||
}
|
|
||||||
for _, cred := range c.GetEntries() {
|
|
||||||
var tkt messages.Ticket
|
|
||||||
err = tkt.Unmarshal(cred.Ticket)
|
|
||||||
if err != nil {
|
|
||||||
return cl, fmt.Errorf("cache entry ticket bytes are not valid: %v", err)
|
|
||||||
}
|
|
||||||
cl.cache.addEntry(
|
|
||||||
tkt,
|
|
||||||
cred.AuthTime,
|
|
||||||
cred.StartTime,
|
|
||||||
cred.EndTime,
|
|
||||||
cred.RenewTill,
|
|
||||||
cred.Key,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return cl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key returns the client's encryption key for the specified encryption type and its kvno (kvno of zero will find latest).
|
|
||||||
// The key can be retrieved either from the keytab or generated from the client's password.
|
|
||||||
// If the client has both a keytab and a password defined the keytab is favoured as the source for the key
|
|
||||||
// A KRBError can be passed in the event the KDC returns one of type KDC_ERR_PREAUTH_REQUIRED and is required to derive
|
|
||||||
// the key for pre-authentication from the client's password. If a KRBError is not available, pass nil to this argument.
|
|
||||||
func (cl *Client) Key(etype etype.EType, kvno int, krberr *messages.KRBError) (types.EncryptionKey, int, error) {
|
|
||||||
if cl.Credentials.HasKeytab() && etype != nil {
|
|
||||||
return cl.Credentials.Keytab().GetEncryptionKey(cl.Credentials.CName(), cl.Credentials.Domain(), kvno, etype.GetETypeID())
|
|
||||||
} else if cl.Credentials.HasPassword() {
|
|
||||||
if krberr != nil && krberr.ErrorCode == errorcode.KDC_ERR_PREAUTH_REQUIRED {
|
|
||||||
var pas types.PADataSequence
|
|
||||||
err := pas.Unmarshal(krberr.EData)
|
|
||||||
if err != nil {
|
|
||||||
return types.EncryptionKey{}, 0, fmt.Errorf("could not get PAData from KRBError to generate key from password: %v", err)
|
|
||||||
}
|
|
||||||
key, _, err := crypto.GetKeyFromPassword(cl.Credentials.Password(), krberr.CName, krberr.CRealm, etype.GetETypeID(), pas)
|
|
||||||
return key, 0, err
|
|
||||||
}
|
|
||||||
key, _, err := crypto.GetKeyFromPassword(cl.Credentials.Password(), cl.Credentials.CName(), cl.Credentials.Domain(), etype.GetETypeID(), types.PADataSequence{})
|
|
||||||
return key, 0, err
|
|
||||||
}
|
|
||||||
return types.EncryptionKey{}, 0, errors.New("credential has neither keytab or password to generate key")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsConfigured indicates if the client has the values required set.
|
|
||||||
func (cl *Client) IsConfigured() (bool, error) {
|
|
||||||
if cl.Credentials.UserName() == "" {
|
|
||||||
return false, errors.New("client does not have a username")
|
|
||||||
}
|
|
||||||
if cl.Credentials.Domain() == "" {
|
|
||||||
return false, errors.New("client does not have a define realm")
|
|
||||||
}
|
|
||||||
// Client needs to have either a password, keytab or a session already (later when loading from CCache)
|
|
||||||
if !cl.Credentials.HasPassword() && !cl.Credentials.HasKeytab() {
|
|
||||||
authTime, _, _, _, err := cl.sessionTimes(cl.Credentials.Domain())
|
|
||||||
if err != nil || authTime.IsZero() {
|
|
||||||
return false, errors.New("client has neither a keytab nor a password set and no session")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !cl.Config.LibDefaults.DNSLookupKDC {
|
|
||||||
for _, r := range cl.Config.Realms {
|
|
||||||
if r.Realm == cl.Credentials.Domain() {
|
|
||||||
if len(r.KDC) > 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, errors.New("client krb5 config does not have any defined KDCs for the default realm")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Login the client with the KDC via an AS exchange.
|
|
||||||
func (cl *Client) Login() error {
|
|
||||||
if ok, err := cl.IsConfigured(); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !cl.Credentials.HasPassword() && !cl.Credentials.HasKeytab() {
|
|
||||||
_, endTime, _, _, err := cl.sessionTimes(cl.Credentials.Domain())
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.KRBMsgError, "no user credentials available and error getting any existing session")
|
|
||||||
}
|
|
||||||
if time.Now().UTC().After(endTime) {
|
|
||||||
return krberror.New(krberror.KRBMsgError, "cannot login, no user credentials available and no valid existing session")
|
|
||||||
}
|
|
||||||
// no credentials but there is a session with tgt already
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ASReq, err := messages.NewASReqForTGT(cl.Credentials.Domain(), cl.Config, cl.Credentials.CName())
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.KRBMsgError, "error generating new AS_REQ")
|
|
||||||
}
|
|
||||||
ASRep, err := cl.ASExchange(cl.Credentials.Domain(), ASReq, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cl.addSession(ASRep.Ticket, ASRep.DecryptedEncPart)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AffirmLogin will only perform an AS exchange with the KDC if the client does not already have a TGT.
|
|
||||||
func (cl *Client) AffirmLogin() error {
|
|
||||||
_, endTime, _, _, err := cl.sessionTimes(cl.Credentials.Domain())
|
|
||||||
if err != nil || time.Now().UTC().After(endTime) {
|
|
||||||
err := cl.Login()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not get valid TGT for client's realm: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// realmLogin obtains or renews a TGT and establishes a session for the realm specified.
|
|
||||||
func (cl *Client) realmLogin(realm string) error {
|
|
||||||
if realm == cl.Credentials.Domain() {
|
|
||||||
return cl.Login()
|
|
||||||
}
|
|
||||||
_, endTime, _, _, err := cl.sessionTimes(cl.Credentials.Domain())
|
|
||||||
if err != nil || time.Now().UTC().After(endTime) {
|
|
||||||
err := cl.Login()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not get valid TGT for client's realm: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tgt, skey, err := cl.sessionTGT(cl.Credentials.Domain())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
spn := types.PrincipalName{
|
|
||||||
NameType: nametype.KRB_NT_SRV_INST,
|
|
||||||
NameString: []string{"krbtgt", realm},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, tgsRep, err := cl.TGSREQGenerateAndExchange(spn, cl.Credentials.Domain(), tgt, skey, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cl.addSession(tgsRep.Ticket, tgsRep.DecryptedEncPart)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy stops the auto-renewal of all sessions and removes the sessions and cache entries from the client.
|
|
||||||
func (cl *Client) Destroy() {
|
|
||||||
creds := credentials.New("", "")
|
|
||||||
cl.sessions.destroy()
|
|
||||||
cl.cache.clear()
|
|
||||||
cl.Credentials = creds
|
|
||||||
cl.Log("client destroyed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Diagnostics runs a set of checks that the client is properly configured and writes details to the io.Writer provided.
|
|
||||||
func (cl *Client) Diagnostics(w io.Writer) error {
|
|
||||||
cl.Print(w)
|
|
||||||
var errs []string
|
|
||||||
if cl.Credentials.HasKeytab() {
|
|
||||||
var loginRealmEncTypes []int32
|
|
||||||
for _, e := range cl.Credentials.Keytab().Entries {
|
|
||||||
if e.Principal.Realm == cl.Credentials.Realm() {
|
|
||||||
loginRealmEncTypes = append(loginRealmEncTypes, e.Key.KeyType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, et := range cl.Config.LibDefaults.DefaultTktEnctypeIDs {
|
|
||||||
var etInKt bool
|
|
||||||
for _, val := range loginRealmEncTypes {
|
|
||||||
if val == et {
|
|
||||||
etInKt = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !etInKt {
|
|
||||||
errs = append(errs, fmt.Sprintf("default_tkt_enctypes specifies %d but this enctype is not available in the client's keytab", et))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, et := range cl.Config.LibDefaults.PreferredPreauthTypes {
|
|
||||||
var etInKt bool
|
|
||||||
for _, val := range loginRealmEncTypes {
|
|
||||||
if int(val) == et {
|
|
||||||
etInKt = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !etInKt {
|
|
||||||
errs = append(errs, fmt.Sprintf("preferred_preauth_types specifies %d but this enctype is not available in the client's keytab", et))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
udpCnt, udpKDC, err := cl.Config.GetKDCs(cl.Credentials.Realm(), false)
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, fmt.Sprintf("error when resolving KDCs for UDP communication: %v", err))
|
|
||||||
}
|
|
||||||
if udpCnt < 1 {
|
|
||||||
errs = append(errs, "no KDCs resolved for communication via UDP.")
|
|
||||||
} else {
|
|
||||||
b, _ := json.MarshalIndent(&udpKDC, "", " ")
|
|
||||||
fmt.Fprintf(w, "UDP KDCs: %s\n", string(b))
|
|
||||||
}
|
|
||||||
tcpCnt, tcpKDC, err := cl.Config.GetKDCs(cl.Credentials.Realm(), false)
|
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, fmt.Sprintf("error when resolving KDCs for TCP communication: %v", err))
|
|
||||||
}
|
|
||||||
if tcpCnt < 1 {
|
|
||||||
errs = append(errs, "no KDCs resolved for communication via TCP.")
|
|
||||||
} else {
|
|
||||||
b, _ := json.MarshalIndent(&tcpKDC, "", " ")
|
|
||||||
fmt.Fprintf(w, "TCP KDCs: %s\n", string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
if errs == nil || len(errs) < 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = fmt.Errorf(strings.Join(errs, "\n"))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print writes the details of the client to the io.Writer provided.
|
|
||||||
func (cl *Client) Print(w io.Writer) {
|
|
||||||
c, _ := cl.Credentials.JSON()
|
|
||||||
fmt.Fprintf(w, "Credentials:\n%s\n", c)
|
|
||||||
|
|
||||||
s, _ := cl.sessions.JSON()
|
|
||||||
fmt.Fprintf(w, "TGT Sessions:\n%s\n", s)
|
|
||||||
|
|
||||||
c, _ = cl.cache.JSON()
|
|
||||||
fmt.Fprintf(w, "Service ticket cache:\n%s\n", c)
|
|
||||||
|
|
||||||
s, _ = cl.settings.JSON()
|
|
||||||
fmt.Fprintf(w, "Settings:\n%s\n", s)
|
|
||||||
|
|
||||||
j, _ := cl.Config.JSON()
|
|
||||||
fmt.Fprintf(w, "Krb5 config:\n%s\n", j)
|
|
||||||
|
|
||||||
k, _ := cl.Credentials.Keytab().JSON()
|
|
||||||
fmt.Fprintf(w, "Keytab:\n%s\n", k)
|
|
||||||
}
|
|
213
vendor/github.com/jcmturner/gokrb5/v8/client/network.go
generated
vendored
213
vendor/github.com/jcmturner/gokrb5/v8/client/network.go
generated
vendored
@ -1,213 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SendToKDC performs network actions to send data to the KDC.
|
|
||||||
func (cl *Client) sendToKDC(b []byte, realm string) ([]byte, error) {
|
|
||||||
var rb []byte
|
|
||||||
if cl.Config.LibDefaults.UDPPreferenceLimit == 1 {
|
|
||||||
//1 means we should always use TCP
|
|
||||||
rb, errtcp := cl.sendKDCTCP(realm, b)
|
|
||||||
if errtcp != nil {
|
|
||||||
if e, ok := errtcp.(messages.KRBError); ok {
|
|
||||||
return rb, e
|
|
||||||
}
|
|
||||||
return rb, fmt.Errorf("communication error with KDC via TCP: %v", errtcp)
|
|
||||||
}
|
|
||||||
return rb, nil
|
|
||||||
}
|
|
||||||
if len(b) <= cl.Config.LibDefaults.UDPPreferenceLimit {
|
|
||||||
//Try UDP first, TCP second
|
|
||||||
rb, errudp := cl.sendKDCUDP(realm, b)
|
|
||||||
if errudp != nil {
|
|
||||||
if e, ok := errudp.(messages.KRBError); ok && e.ErrorCode != errorcode.KRB_ERR_RESPONSE_TOO_BIG {
|
|
||||||
// Got a KRBError from KDC
|
|
||||||
// If this is not a KRB_ERR_RESPONSE_TOO_BIG we will return immediately otherwise will try TCP.
|
|
||||||
return rb, e
|
|
||||||
}
|
|
||||||
// Try TCP
|
|
||||||
r, errtcp := cl.sendKDCTCP(realm, b)
|
|
||||||
if errtcp != nil {
|
|
||||||
if e, ok := errtcp.(messages.KRBError); ok {
|
|
||||||
// Got a KRBError
|
|
||||||
return r, e
|
|
||||||
}
|
|
||||||
return r, fmt.Errorf("failed to communicate with KDC. Attempts made with UDP (%v) and then TCP (%v)", errudp, errtcp)
|
|
||||||
}
|
|
||||||
rb = r
|
|
||||||
}
|
|
||||||
return rb, nil
|
|
||||||
}
|
|
||||||
//Try TCP first, UDP second
|
|
||||||
rb, errtcp := cl.sendKDCTCP(realm, b)
|
|
||||||
if errtcp != nil {
|
|
||||||
if e, ok := errtcp.(messages.KRBError); ok {
|
|
||||||
// Got a KRBError from KDC so returning and not trying UDP.
|
|
||||||
return rb, e
|
|
||||||
}
|
|
||||||
rb, errudp := cl.sendKDCUDP(realm, b)
|
|
||||||
if errudp != nil {
|
|
||||||
if e, ok := errudp.(messages.KRBError); ok {
|
|
||||||
// Got a KRBError
|
|
||||||
return rb, e
|
|
||||||
}
|
|
||||||
return rb, fmt.Errorf("failed to communicate with KDC. Attempts made with TCP (%v) and then UDP (%v)", errtcp, errudp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rb, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// dialKDCTCP establishes a UDP connection to a KDC.
|
|
||||||
func dialKDCUDP(count int, kdcs map[int]string) (*net.UDPConn, error) {
|
|
||||||
i := 1
|
|
||||||
for i <= count {
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", kdcs[i])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error resolving KDC address: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := net.DialTimeout("udp", udpAddr.String(), 5*time.Second)
|
|
||||||
if err == nil {
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// conn is guaranteed to be a UDPConn
|
|
||||||
return conn.(*net.UDPConn), nil
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return nil, errors.New("error in getting a UDP connection to any of the KDCs")
|
|
||||||
}
|
|
||||||
|
|
||||||
// dialKDCTCP establishes a TCP connection to a KDC.
|
|
||||||
func dialKDCTCP(count int, kdcs map[int]string) (*net.TCPConn, error) {
|
|
||||||
i := 1
|
|
||||||
for i <= count {
|
|
||||||
tcpAddr, err := net.ResolveTCPAddr("tcp", kdcs[i])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error resolving KDC address: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := net.DialTimeout("tcp", tcpAddr.String(), 5*time.Second)
|
|
||||||
if err == nil {
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// conn is guaranteed to be a TCPConn
|
|
||||||
return conn.(*net.TCPConn), nil
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return nil, errors.New("error in getting a TCP connection to any of the KDCs")
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendKDCUDP sends bytes to the KDC via UDP.
|
|
||||||
func (cl *Client) sendKDCUDP(realm string, b []byte) ([]byte, error) {
|
|
||||||
var r []byte
|
|
||||||
count, kdcs, err := cl.Config.GetKDCs(realm, false)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
conn, err := dialKDCUDP(count, kdcs)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
r, err = cl.sendUDP(conn, b)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
return checkForKRBError(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendKDCTCP sends bytes to the KDC via TCP.
|
|
||||||
func (cl *Client) sendKDCTCP(realm string, b []byte) ([]byte, error) {
|
|
||||||
var r []byte
|
|
||||||
count, kdcs, err := cl.Config.GetKDCs(realm, true)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
conn, err := dialKDCTCP(count, kdcs)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
rb, err := cl.sendTCP(conn, b)
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
return checkForKRBError(rb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendUDP sends bytes to connection over UDP.
|
|
||||||
func (cl *Client) sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) {
|
|
||||||
var r []byte
|
|
||||||
defer conn.Close()
|
|
||||||
_, err := conn.Write(b)
|
|
||||||
if err != nil {
|
|
||||||
return r, fmt.Errorf("error sending to (%s): %v", conn.RemoteAddr().String(), err)
|
|
||||||
}
|
|
||||||
udpbuf := make([]byte, 4096)
|
|
||||||
n, _, err := conn.ReadFrom(udpbuf)
|
|
||||||
r = udpbuf[:n]
|
|
||||||
if err != nil {
|
|
||||||
return r, fmt.Errorf("sending over UDP failed to %s: %v", conn.RemoteAddr().String(), err)
|
|
||||||
}
|
|
||||||
if len(r) < 1 {
|
|
||||||
return r, fmt.Errorf("no response data from %s", conn.RemoteAddr().String())
|
|
||||||
}
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendTCP sends bytes to connection over TCP.
|
|
||||||
func (cl *Client) sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) {
|
|
||||||
defer conn.Close()
|
|
||||||
var r []byte
|
|
||||||
// RFC 4120 7.2.2 specifies the first 4 bytes indicate the length of the message in big endian order.
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err := binary.Write(&buf, binary.BigEndian, uint32(len(b)))
|
|
||||||
if err != nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
b = append(buf.Bytes(), b...)
|
|
||||||
|
|
||||||
_, err = conn.Write(b)
|
|
||||||
if err != nil {
|
|
||||||
return r, fmt.Errorf("error sending to KDC (%s): %v", conn.RemoteAddr().String(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sh := make([]byte, 4, 4)
|
|
||||||
_, err = conn.Read(sh)
|
|
||||||
if err != nil {
|
|
||||||
return r, fmt.Errorf("error reading response size header: %v", err)
|
|
||||||
}
|
|
||||||
s := binary.BigEndian.Uint32(sh)
|
|
||||||
|
|
||||||
rb := make([]byte, s, s)
|
|
||||||
_, err = io.ReadFull(conn, rb)
|
|
||||||
if err != nil {
|
|
||||||
return r, fmt.Errorf("error reading response: %v", err)
|
|
||||||
}
|
|
||||||
if len(rb) < 1 {
|
|
||||||
return r, fmt.Errorf("no response data from KDC %s", conn.RemoteAddr().String())
|
|
||||||
}
|
|
||||||
return rb, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForKRBError checks if the response bytes from the KDC are a KRBError.
|
|
||||||
func checkForKRBError(b []byte) ([]byte, error) {
|
|
||||||
var KRBErr messages.KRBError
|
|
||||||
if err := KRBErr.Unmarshal(b); err == nil {
|
|
||||||
return b, KRBErr
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
95
vendor/github.com/jcmturner/gokrb5/v8/client/passwd.go
generated
vendored
95
vendor/github.com/jcmturner/gokrb5/v8/client/passwd.go
generated
vendored
@ -1,95 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/kadmin"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Kpasswd server response codes.
|
|
||||||
const (
|
|
||||||
KRB5_KPASSWD_SUCCESS = 0
|
|
||||||
KRB5_KPASSWD_MALFORMED = 1
|
|
||||||
KRB5_KPASSWD_HARDERROR = 2
|
|
||||||
KRB5_KPASSWD_AUTHERROR = 3
|
|
||||||
KRB5_KPASSWD_SOFTERROR = 4
|
|
||||||
KRB5_KPASSWD_ACCESSDENIED = 5
|
|
||||||
KRB5_KPASSWD_BAD_VERSION = 6
|
|
||||||
KRB5_KPASSWD_INITIAL_FLAG_NEEDED = 7
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChangePasswd changes the password of the client to the value provided.
|
|
||||||
func (cl *Client) ChangePasswd(newPasswd string) (bool, error) {
|
|
||||||
ASReq, err := messages.NewASReqForChgPasswd(cl.Credentials.Domain(), cl.Config, cl.Credentials.CName())
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
ASRep, err := cl.ASExchange(cl.Credentials.Domain(), ASReq, 0)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, key, err := kadmin.ChangePasswdMsg(cl.Credentials.CName(), cl.Credentials.Domain(), newPasswd, ASRep.Ticket, ASRep.DecryptedEncPart.Key)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
r, err := cl.sendToKPasswd(msg)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
err = r.Decrypt(key)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if r.ResultCode != KRB5_KPASSWD_SUCCESS {
|
|
||||||
return false, fmt.Errorf("error response from kadmin: code: %d; result: %s; krberror: %v", r.ResultCode, r.Result, r.KRBError)
|
|
||||||
}
|
|
||||||
cl.Credentials.WithPassword(newPasswd)
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cl *Client) sendToKPasswd(msg kadmin.Request) (r kadmin.Reply, err error) {
|
|
||||||
_, kps, err := cl.Config.GetKpasswdServers(cl.Credentials.Domain(), true)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
addr := kps[1]
|
|
||||||
b, err := msg.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(b) <= cl.Config.LibDefaults.UDPPreferenceLimit {
|
|
||||||
return cl.sendKPasswdUDP(b, addr)
|
|
||||||
}
|
|
||||||
return cl.sendKPasswdTCP(b, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cl *Client) sendKPasswdTCP(b []byte, kadmindAddr string) (r kadmin.Reply, err error) {
|
|
||||||
tcpAddr, err := net.ResolveTCPAddr("tcp", kadmindAddr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
conn, err := net.DialTCP("tcp", nil, tcpAddr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rb, err := cl.sendTCP(conn, b)
|
|
||||||
err = r.Unmarshal(rb)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cl *Client) sendKPasswdUDP(b []byte, kadmindAddr string) (r kadmin.Reply, err error) {
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", kadmindAddr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
conn, err := net.DialUDP("udp", nil, udpAddr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rb, err := cl.sendUDP(conn, b)
|
|
||||||
err = r.Unmarshal(rb)
|
|
||||||
return
|
|
||||||
}
|
|
295
vendor/github.com/jcmturner/gokrb5/v8/client/session.go
generated
vendored
295
vendor/github.com/jcmturner/gokrb5/v8/client/session.go
generated
vendored
@ -1,295 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/nametype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/messages"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// sessions hold TGTs and are keyed on the realm name
|
|
||||||
type sessions struct {
|
|
||||||
Entries map[string]*session
|
|
||||||
mux sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy erases all sessions
|
|
||||||
func (s *sessions) destroy() {
|
|
||||||
s.mux.Lock()
|
|
||||||
defer s.mux.Unlock()
|
|
||||||
for k, e := range s.Entries {
|
|
||||||
e.destroy()
|
|
||||||
delete(s.Entries, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update replaces a session with the one provided or adds it as a new one
|
|
||||||
func (s *sessions) update(sess *session) {
|
|
||||||
s.mux.Lock()
|
|
||||||
defer s.mux.Unlock()
|
|
||||||
// if a session already exists for this, cancel its auto renew.
|
|
||||||
if i, ok := s.Entries[sess.realm]; ok {
|
|
||||||
if i != sess {
|
|
||||||
// Session in the sessions cache is not the same as one provided.
|
|
||||||
// Cancel the one in the cache and add this one.
|
|
||||||
i.mux.Lock()
|
|
||||||
defer i.mux.Unlock()
|
|
||||||
i.cancel <- true
|
|
||||||
s.Entries[sess.realm] = sess
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No session for this realm was found so just add it
|
|
||||||
s.Entries[sess.realm] = sess
|
|
||||||
}
|
|
||||||
|
|
||||||
// get returns the session for the realm specified
|
|
||||||
func (s *sessions) get(realm string) (*session, bool) {
|
|
||||||
s.mux.RLock()
|
|
||||||
defer s.mux.RUnlock()
|
|
||||||
sess, ok := s.Entries[realm]
|
|
||||||
return sess, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// session holds the TGT details for a realm
|
|
||||||
type session struct {
|
|
||||||
realm string
|
|
||||||
authTime time.Time
|
|
||||||
endTime time.Time
|
|
||||||
renewTill time.Time
|
|
||||||
tgt messages.Ticket
|
|
||||||
sessionKey types.EncryptionKey
|
|
||||||
sessionKeyExpiration time.Time
|
|
||||||
cancel chan bool
|
|
||||||
mux sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// jsonSession is used to enable marshaling some information of a session in a JSON format
|
|
||||||
type jsonSession struct {
|
|
||||||
Realm string
|
|
||||||
AuthTime time.Time
|
|
||||||
EndTime time.Time
|
|
||||||
RenewTill time.Time
|
|
||||||
SessionKeyExpiration time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSession adds a session for a realm with a TGT to the client's session cache.
|
|
||||||
// A goroutine is started to automatically renew the TGT before expiry.
|
|
||||||
func (cl *Client) addSession(tgt messages.Ticket, dep messages.EncKDCRepPart) {
|
|
||||||
if strings.ToLower(tgt.SName.NameString[0]) != "krbtgt" {
|
|
||||||
// Not a TGT
|
|
||||||
return
|
|
||||||
}
|
|
||||||
realm := tgt.SName.NameString[len(tgt.SName.NameString)-1]
|
|
||||||
s := &session{
|
|
||||||
realm: realm,
|
|
||||||
authTime: dep.AuthTime,
|
|
||||||
endTime: dep.EndTime,
|
|
||||||
renewTill: dep.RenewTill,
|
|
||||||
tgt: tgt,
|
|
||||||
sessionKey: dep.Key,
|
|
||||||
sessionKeyExpiration: dep.KeyExpiration,
|
|
||||||
}
|
|
||||||
cl.sessions.update(s)
|
|
||||||
cl.enableAutoSessionRenewal(s)
|
|
||||||
cl.Log("TGT session added for %s (EndTime: %v)", realm, dep.EndTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// update overwrites the session details with those from the TGT and decrypted encPart
|
|
||||||
func (s *session) update(tgt messages.Ticket, dep messages.EncKDCRepPart) {
|
|
||||||
s.mux.Lock()
|
|
||||||
defer s.mux.Unlock()
|
|
||||||
s.authTime = dep.AuthTime
|
|
||||||
s.endTime = dep.EndTime
|
|
||||||
s.renewTill = dep.RenewTill
|
|
||||||
s.tgt = tgt
|
|
||||||
s.sessionKey = dep.Key
|
|
||||||
s.sessionKeyExpiration = dep.KeyExpiration
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy will cancel any auto renewal of the session and set the expiration times to the current time
|
|
||||||
func (s *session) destroy() {
|
|
||||||
s.mux.Lock()
|
|
||||||
defer s.mux.Unlock()
|
|
||||||
if s.cancel != nil {
|
|
||||||
s.cancel <- true
|
|
||||||
}
|
|
||||||
s.endTime = time.Now().UTC()
|
|
||||||
s.renewTill = s.endTime
|
|
||||||
s.sessionKeyExpiration = s.endTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// valid informs if the TGT is still within the valid time window
|
|
||||||
func (s *session) valid() bool {
|
|
||||||
s.mux.RLock()
|
|
||||||
defer s.mux.RUnlock()
|
|
||||||
t := time.Now().UTC()
|
|
||||||
if t.Before(s.endTime) && s.authTime.Before(t) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// tgtDetails is a thread safe way to get the session's realm, TGT and session key values
|
|
||||||
func (s *session) tgtDetails() (string, messages.Ticket, types.EncryptionKey) {
|
|
||||||
s.mux.RLock()
|
|
||||||
defer s.mux.RUnlock()
|
|
||||||
return s.realm, s.tgt, s.sessionKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeDetails is a thread safe way to get the session's validity time values
|
|
||||||
func (s *session) timeDetails() (string, time.Time, time.Time, time.Time, time.Time) {
|
|
||||||
s.mux.RLock()
|
|
||||||
defer s.mux.RUnlock()
|
|
||||||
return s.realm, s.authTime, s.endTime, s.renewTill, s.sessionKeyExpiration
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON return information about the held sessions in a JSON format.
|
|
||||||
func (s *sessions) JSON() (string, error) {
|
|
||||||
s.mux.RLock()
|
|
||||||
defer s.mux.RUnlock()
|
|
||||||
var js []jsonSession
|
|
||||||
keys := make([]string, 0, len(s.Entries))
|
|
||||||
for k := range s.Entries {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
for _, k := range keys {
|
|
||||||
r, at, et, rt, kt := s.Entries[k].timeDetails()
|
|
||||||
j := jsonSession{
|
|
||||||
Realm: r,
|
|
||||||
AuthTime: at,
|
|
||||||
EndTime: et,
|
|
||||||
RenewTill: rt,
|
|
||||||
SessionKeyExpiration: kt,
|
|
||||||
}
|
|
||||||
js = append(js, j)
|
|
||||||
}
|
|
||||||
b, err := json.MarshalIndent(js, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// enableAutoSessionRenewal turns on the automatic renewal for the client's TGT session.
|
|
||||||
func (cl *Client) enableAutoSessionRenewal(s *session) {
|
|
||||||
var timer *time.Timer
|
|
||||||
s.mux.Lock()
|
|
||||||
s.cancel = make(chan bool, 1)
|
|
||||||
s.mux.Unlock()
|
|
||||||
go func(s *session) {
|
|
||||||
for {
|
|
||||||
s.mux.RLock()
|
|
||||||
w := (s.endTime.Sub(time.Now().UTC()) * 5) / 6
|
|
||||||
s.mux.RUnlock()
|
|
||||||
if w < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
timer = time.NewTimer(w)
|
|
||||||
select {
|
|
||||||
case <-timer.C:
|
|
||||||
renewal, err := cl.refreshSession(s)
|
|
||||||
if err != nil {
|
|
||||||
cl.Log("error refreshing session: %v", err)
|
|
||||||
}
|
|
||||||
if !renewal && err == nil {
|
|
||||||
// end this goroutine as there will have been a new login and new auto renewal goroutine created.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-s.cancel:
|
|
||||||
// cancel has been called. Stop the timer and exit.
|
|
||||||
timer.Stop()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// renewTGT renews the client's TGT session.
|
|
||||||
func (cl *Client) renewTGT(s *session) error {
|
|
||||||
realm, tgt, skey := s.tgtDetails()
|
|
||||||
spn := types.PrincipalName{
|
|
||||||
NameType: nametype.KRB_NT_SRV_INST,
|
|
||||||
NameString: []string{"krbtgt", realm},
|
|
||||||
}
|
|
||||||
_, tgsRep, err := cl.TGSREQGenerateAndExchange(spn, cl.Credentials.Domain(), tgt, skey, true)
|
|
||||||
if err != nil {
|
|
||||||
return krberror.Errorf(err, krberror.KRBMsgError, "error renewing TGT for %s", realm)
|
|
||||||
}
|
|
||||||
s.update(tgsRep.Ticket, tgsRep.DecryptedEncPart)
|
|
||||||
cl.sessions.update(s)
|
|
||||||
cl.Log("TGT session renewed for %s (EndTime: %v)", realm, tgsRep.DecryptedEncPart.EndTime)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// refreshSession updates either through renewal or creating a new login.
|
|
||||||
// The boolean indicates if the update was a renewal.
|
|
||||||
func (cl *Client) refreshSession(s *session) (bool, error) {
|
|
||||||
s.mux.RLock()
|
|
||||||
realm := s.realm
|
|
||||||
renewTill := s.renewTill
|
|
||||||
s.mux.RUnlock()
|
|
||||||
cl.Log("refreshing TGT session for %s", realm)
|
|
||||||
if time.Now().UTC().Before(renewTill) {
|
|
||||||
err := cl.renewTGT(s)
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
err := cl.realmLogin(realm)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensureValidSession makes sure there is a valid session for the realm
|
|
||||||
func (cl *Client) ensureValidSession(realm string) error {
|
|
||||||
s, ok := cl.sessions.get(realm)
|
|
||||||
if ok {
|
|
||||||
s.mux.RLock()
|
|
||||||
d := s.endTime.Sub(s.authTime) / 6
|
|
||||||
if s.endTime.Sub(time.Now().UTC()) > d {
|
|
||||||
s.mux.RUnlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s.mux.RUnlock()
|
|
||||||
_, err := cl.refreshSession(s)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return cl.realmLogin(realm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sessionTGTDetails is a thread safe way to get the TGT and session key values for a realm
|
|
||||||
func (cl *Client) sessionTGT(realm string) (tgt messages.Ticket, sessionKey types.EncryptionKey, err error) {
|
|
||||||
err = cl.ensureValidSession(realm)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s, ok := cl.sessions.get(realm)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("could not find TGT session for %s", realm)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, tgt, sessionKey = s.tgtDetails()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sessionTimes provides the timing information with regards to a session for the realm specified.
|
|
||||||
func (cl *Client) sessionTimes(realm string) (authTime, endTime, renewTime, sessionExp time.Time, err error) {
|
|
||||||
s, ok := cl.sessions.get(realm)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("could not find TGT session for %s", realm)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, authTime, endTime, renewTime, sessionExp = s.timeDetails()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// spnRealm resolves the realm name of a service principal name
|
|
||||||
func (cl *Client) spnRealm(spn types.PrincipalName) string {
|
|
||||||
return cl.Config.ResolveRealm(spn.NameString[len(spn.NameString)-1])
|
|
||||||
}
|
|
93
vendor/github.com/jcmturner/gokrb5/v8/client/settings.go
generated
vendored
93
vendor/github.com/jcmturner/gokrb5/v8/client/settings.go
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Settings holds optional client settings.
|
|
||||||
type Settings struct {
|
|
||||||
disablePAFXFast bool
|
|
||||||
assumePreAuthentication bool
|
|
||||||
preAuthEType int32
|
|
||||||
logger *log.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// jsonSettings is used when marshaling the Settings details to JSON format.
|
|
||||||
type jsonSettings struct {
|
|
||||||
DisablePAFXFast bool
|
|
||||||
AssumePreAuthentication bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSettings creates a new client settings struct.
|
|
||||||
func NewSettings(settings ...func(*Settings)) *Settings {
|
|
||||||
s := new(Settings)
|
|
||||||
for _, set := range settings {
|
|
||||||
set(s)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisablePAFXFAST used to configure the client to not use PA_FX_FAST.
|
|
||||||
//
|
|
||||||
// s := NewSettings(DisablePAFXFAST(true))
|
|
||||||
func DisablePAFXFAST(b bool) func(*Settings) {
|
|
||||||
return func(s *Settings) {
|
|
||||||
s.disablePAFXFast = b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisablePAFXFAST indicates is the client should disable the use of PA_FX_FAST.
|
|
||||||
func (s *Settings) DisablePAFXFAST() bool {
|
|
||||||
return s.disablePAFXFast
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssumePreAuthentication used to configure the client to assume pre-authentication is required.
|
|
||||||
//
|
|
||||||
// s := NewSettings(AssumePreAuthentication(true))
|
|
||||||
func AssumePreAuthentication(b bool) func(*Settings) {
|
|
||||||
return func(s *Settings) {
|
|
||||||
s.assumePreAuthentication = b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssumePreAuthentication indicates if the client should proactively assume using pre-authentication.
|
|
||||||
func (s *Settings) AssumePreAuthentication() bool {
|
|
||||||
return s.assumePreAuthentication
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logger used to configure client with a logger.
|
|
||||||
//
|
|
||||||
// s := NewSettings(kt, Logger(l))
|
|
||||||
func Logger(l *log.Logger) func(*Settings) {
|
|
||||||
return func(s *Settings) {
|
|
||||||
s.logger = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logger returns the client logger instance.
|
|
||||||
func (s *Settings) Logger() *log.Logger {
|
|
||||||
return s.logger
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log will write to the service's logger if it is configured.
|
|
||||||
func (cl *Client) Log(format string, v ...interface{}) {
|
|
||||||
if cl.settings.Logger() != nil {
|
|
||||||
cl.settings.Logger().Output(2, fmt.Sprintf(format, v...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON returns a JSON representation of the settings.
|
|
||||||
func (s *Settings) JSON() (string, error) {
|
|
||||||
js := jsonSettings{
|
|
||||||
DisablePAFXFast: s.disablePAFXFast,
|
|
||||||
AssumePreAuthentication: s.assumePreAuthentication,
|
|
||||||
}
|
|
||||||
b, err := json.MarshalIndent(js, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(b), nil
|
|
||||||
|
|
||||||
}
|
|
30
vendor/github.com/jcmturner/gokrb5/v8/config/error.go
generated
vendored
30
vendor/github.com/jcmturner/gokrb5/v8/config/error.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// UnsupportedDirective error.
|
|
||||||
type UnsupportedDirective struct {
|
|
||||||
text string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface for unsupported directives.
|
|
||||||
func (e UnsupportedDirective) Error() string {
|
|
||||||
return e.text
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalid config error.
|
|
||||||
type Invalid struct {
|
|
||||||
text string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface for invalid config error.
|
|
||||||
func (e Invalid) Error() string {
|
|
||||||
return e.text
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidErrorf creates a new Invalid error.
|
|
||||||
func InvalidErrorf(format string, a ...interface{}) Invalid {
|
|
||||||
return Invalid{
|
|
||||||
text: fmt.Sprintf("invalid krb5 config "+format, a...),
|
|
||||||
}
|
|
||||||
}
|
|
141
vendor/github.com/jcmturner/gokrb5/v8/config/hosts.go
generated
vendored
141
vendor/github.com/jcmturner/gokrb5/v8/config/hosts.go
generated
vendored
@ -1,141 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jcmturner/dnsutils/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetKDCs returns the count of KDCs available and a map of KDC host names keyed on preference order.
|
|
||||||
func (c *Config) GetKDCs(realm string, tcp bool) (int, map[int]string, error) {
|
|
||||||
if realm == "" {
|
|
||||||
realm = c.LibDefaults.DefaultRealm
|
|
||||||
}
|
|
||||||
kdcs := make(map[int]string)
|
|
||||||
var count int
|
|
||||||
|
|
||||||
// Get the KDCs from the krb5.conf.
|
|
||||||
var ks []string
|
|
||||||
for _, r := range c.Realms {
|
|
||||||
if r.Realm != realm {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ks = r.KDC
|
|
||||||
}
|
|
||||||
count = len(ks)
|
|
||||||
|
|
||||||
if count > 0 {
|
|
||||||
// Order the kdcs randomly for preference.
|
|
||||||
kdcs = randServOrder(ks)
|
|
||||||
return count, kdcs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.LibDefaults.DNSLookupKDC {
|
|
||||||
return count, kdcs, fmt.Errorf("no KDCs defined in configuration for realm %s", realm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use DNS to resolve kerberos SRV records.
|
|
||||||
proto := "udp"
|
|
||||||
if tcp {
|
|
||||||
proto = "tcp"
|
|
||||||
}
|
|
||||||
index, addrs, err := dnsutils.OrderedSRV("kerberos", proto, realm)
|
|
||||||
if err != nil {
|
|
||||||
return count, kdcs, err
|
|
||||||
}
|
|
||||||
if len(addrs) < 1 {
|
|
||||||
return count, kdcs, fmt.Errorf("no KDC SRV records found for realm %s", realm)
|
|
||||||
}
|
|
||||||
count = index
|
|
||||||
for k, v := range addrs {
|
|
||||||
kdcs[k] = strings.TrimRight(v.Target, ".") + ":" + strconv.Itoa(int(v.Port))
|
|
||||||
}
|
|
||||||
return count, kdcs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKpasswdServers returns the count of kpasswd servers available and a map of kpasswd host names keyed on preference order.
|
|
||||||
// https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html#realms - see kpasswd_server section
|
|
||||||
func (c *Config) GetKpasswdServers(realm string, tcp bool) (int, map[int]string, error) {
|
|
||||||
kdcs := make(map[int]string)
|
|
||||||
var count int
|
|
||||||
|
|
||||||
// Use DNS to resolve kerberos SRV records if configured to do so in krb5.conf.
|
|
||||||
if c.LibDefaults.DNSLookupKDC {
|
|
||||||
proto := "udp"
|
|
||||||
if tcp {
|
|
||||||
proto = "tcp"
|
|
||||||
}
|
|
||||||
c, addrs, err := dnsutils.OrderedSRV("kpasswd", proto, realm)
|
|
||||||
if err != nil {
|
|
||||||
return count, kdcs, err
|
|
||||||
}
|
|
||||||
if c < 1 {
|
|
||||||
c, addrs, err = dnsutils.OrderedSRV("kerberos-adm", proto, realm)
|
|
||||||
if err != nil {
|
|
||||||
return count, kdcs, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(addrs) < 1 {
|
|
||||||
return count, kdcs, fmt.Errorf("no kpasswd or kadmin SRV records found for realm %s", realm)
|
|
||||||
}
|
|
||||||
count = c
|
|
||||||
for k, v := range addrs {
|
|
||||||
kdcs[k] = strings.TrimRight(v.Target, ".") + ":" + strconv.Itoa(int(v.Port))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Get the KDCs from the krb5.conf an order them randomly for preference.
|
|
||||||
var ks []string
|
|
||||||
var ka []string
|
|
||||||
for _, r := range c.Realms {
|
|
||||||
if r.Realm == realm {
|
|
||||||
ks = r.KPasswdServer
|
|
||||||
ka = r.AdminServer
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(ks) < 1 {
|
|
||||||
for _, k := range ka {
|
|
||||||
h, _, err := net.SplitHostPort(k)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ks = append(ks, h+":464")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count = len(ks)
|
|
||||||
if count < 1 {
|
|
||||||
return count, kdcs, fmt.Errorf("no kpasswd or kadmin defined in configuration for realm %s", realm)
|
|
||||||
}
|
|
||||||
kdcs = randServOrder(ks)
|
|
||||||
}
|
|
||||||
return count, kdcs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func randServOrder(ks []string) map[int]string {
|
|
||||||
kdcs := make(map[int]string)
|
|
||||||
count := len(ks)
|
|
||||||
i := 1
|
|
||||||
if count > 1 {
|
|
||||||
l := len(ks)
|
|
||||||
for l > 0 {
|
|
||||||
ri := rand.Intn(l)
|
|
||||||
kdcs[i] = ks[ri]
|
|
||||||
if l > 1 {
|
|
||||||
// Remove the entry from the source slice by swapping with the last entry and truncating
|
|
||||||
ks[len(ks)-1], ks[ri] = ks[ri], ks[len(ks)-1]
|
|
||||||
ks = ks[:len(ks)-1]
|
|
||||||
l = len(ks)
|
|
||||||
} else {
|
|
||||||
l = 0
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kdcs[i] = ks[0]
|
|
||||||
}
|
|
||||||
return kdcs
|
|
||||||
}
|
|
728
vendor/github.com/jcmturner/gokrb5/v8/config/krb5conf.go
generated
vendored
728
vendor/github.com/jcmturner/gokrb5/v8/config/krb5conf.go
generated
vendored
@ -1,728 +0,0 @@
|
|||||||
// Package config implements KRB5 client and service configuration as described at https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html
|
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gofork/encoding/asn1"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config represents the KRB5 configuration.
|
|
||||||
type Config struct {
|
|
||||||
LibDefaults LibDefaults
|
|
||||||
Realms []Realm
|
|
||||||
DomainRealm DomainRealm
|
|
||||||
//CaPaths
|
|
||||||
//AppDefaults
|
|
||||||
//Plugins
|
|
||||||
}
|
|
||||||
|
|
||||||
// WeakETypeList is a list of encryption types that have been deemed weak.
|
|
||||||
const WeakETypeList = "des-cbc-crc des-cbc-md4 des-cbc-md5 des-cbc-raw des3-cbc-raw des-hmac-sha1 arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp des"
|
|
||||||
|
|
||||||
// New creates a new config struct instance.
|
|
||||||
func New() *Config {
|
|
||||||
d := make(DomainRealm)
|
|
||||||
return &Config{
|
|
||||||
LibDefaults: newLibDefaults(),
|
|
||||||
DomainRealm: d,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LibDefaults represents the [libdefaults] section of the configuration.
|
|
||||||
type LibDefaults struct {
|
|
||||||
AllowWeakCrypto bool //default false
|
|
||||||
// ap_req_checksum_type int //unlikely to support this
|
|
||||||
Canonicalize bool //default false
|
|
||||||
CCacheType int //default is 4. unlikely to implement older
|
|
||||||
Clockskew time.Duration //max allowed skew in seconds, default 300
|
|
||||||
//Default_ccache_name string // default /tmp/krb5cc_%{uid} //Not implementing as will hold in memory
|
|
||||||
DefaultClientKeytabName string //default /usr/local/var/krb5/user/%{euid}/client.keytab
|
|
||||||
DefaultKeytabName string //default /etc/krb5.keytab
|
|
||||||
DefaultRealm string
|
|
||||||
DefaultTGSEnctypes []string //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
|
|
||||||
DefaultTktEnctypes []string //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
|
|
||||||
DefaultTGSEnctypeIDs []int32 //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
|
|
||||||
DefaultTktEnctypeIDs []int32 //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
|
|
||||||
DNSCanonicalizeHostname bool //default true
|
|
||||||
DNSLookupKDC bool //default false
|
|
||||||
DNSLookupRealm bool
|
|
||||||
ExtraAddresses []net.IP //Not implementing yet
|
|
||||||
Forwardable bool //default false
|
|
||||||
IgnoreAcceptorHostname bool //default false
|
|
||||||
K5LoginAuthoritative bool //default false
|
|
||||||
K5LoginDirectory string //default user's home directory. Must be owned by the user or root
|
|
||||||
KDCDefaultOptions asn1.BitString //default 0x00000010 (KDC_OPT_RENEWABLE_OK)
|
|
||||||
KDCTimeSync int //default 1
|
|
||||||
//kdc_req_checksum_type int //unlikely to implement as for very old KDCs
|
|
||||||
NoAddresses bool //default true
|
|
||||||
PermittedEnctypes []string //default aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
|
|
||||||
PermittedEnctypeIDs []int32
|
|
||||||
//plugin_base_dir string //not supporting plugins
|
|
||||||
PreferredPreauthTypes []int //default “17, 16, 15, 14”, which forces libkrb5 to attempt to use PKINIT if it is supported
|
|
||||||
Proxiable bool //default false
|
|
||||||
RDNS bool //default true
|
|
||||||
RealmTryDomains int //default -1
|
|
||||||
RenewLifetime time.Duration //default 0
|
|
||||||
SafeChecksumType int //default 8
|
|
||||||
TicketLifetime time.Duration //default 1 day
|
|
||||||
UDPPreferenceLimit int // 1 means to always use tcp. MIT krb5 has a default value of 1465, and it prevents user setting more than 32700.
|
|
||||||
VerifyAPReqNofail bool //default false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new LibDefaults struct.
|
|
||||||
func newLibDefaults() LibDefaults {
|
|
||||||
uid := "0"
|
|
||||||
var hdir string
|
|
||||||
usr, _ := user.Current()
|
|
||||||
if usr != nil {
|
|
||||||
uid = usr.Uid
|
|
||||||
hdir = usr.HomeDir
|
|
||||||
}
|
|
||||||
opts := asn1.BitString{}
|
|
||||||
opts.Bytes, _ = hex.DecodeString("00000010")
|
|
||||||
opts.BitLength = len(opts.Bytes) * 8
|
|
||||||
return LibDefaults{
|
|
||||||
CCacheType: 4,
|
|
||||||
Clockskew: time.Duration(300) * time.Second,
|
|
||||||
DefaultClientKeytabName: fmt.Sprintf("/usr/local/var/krb5/user/%s/client.keytab", uid),
|
|
||||||
DefaultKeytabName: "/etc/krb5.keytab",
|
|
||||||
DefaultTGSEnctypes: []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
|
|
||||||
DefaultTktEnctypes: []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
|
|
||||||
DNSCanonicalizeHostname: true,
|
|
||||||
K5LoginDirectory: hdir,
|
|
||||||
KDCDefaultOptions: opts,
|
|
||||||
KDCTimeSync: 1,
|
|
||||||
NoAddresses: true,
|
|
||||||
PermittedEnctypes: []string{"aes256-cts-hmac-sha1-96", "aes128-cts-hmac-sha1-96", "des3-cbc-sha1", "arcfour-hmac-md5", "camellia256-cts-cmac", "camellia128-cts-cmac", "des-cbc-crc", "des-cbc-md5", "des-cbc-md4"},
|
|
||||||
RDNS: true,
|
|
||||||
RealmTryDomains: -1,
|
|
||||||
SafeChecksumType: 8,
|
|
||||||
TicketLifetime: time.Duration(24) * time.Hour,
|
|
||||||
UDPPreferenceLimit: 1465,
|
|
||||||
PreferredPreauthTypes: []int{17, 16, 15, 14},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the lines of the [libdefaults] section of the configuration into the LibDefaults struct.
|
|
||||||
func (l *LibDefaults) parseLines(lines []string) error {
|
|
||||||
for _, line := range lines {
|
|
||||||
//Remove comments after the values
|
|
||||||
if idx := strings.IndexAny(line, "#;"); idx != -1 {
|
|
||||||
line = line[:idx]
|
|
||||||
}
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.Contains(line, "=") {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := strings.Split(line, "=")
|
|
||||||
key := strings.TrimSpace(strings.ToLower(p[0]))
|
|
||||||
switch key {
|
|
||||||
case "allow_weak_crypto":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.AllowWeakCrypto = v
|
|
||||||
case "canonicalize":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.Canonicalize = v
|
|
||||||
case "ccache_type":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
v, err := strconv.ParseUint(p[1], 10, 32)
|
|
||||||
if err != nil || v < 0 || v > 4 {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
l.CCacheType = int(v)
|
|
||||||
case "clockskew":
|
|
||||||
d, err := parseDuration(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.Clockskew = d
|
|
||||||
case "default_client_keytab_name":
|
|
||||||
l.DefaultClientKeytabName = strings.TrimSpace(p[1])
|
|
||||||
case "default_keytab_name":
|
|
||||||
l.DefaultKeytabName = strings.TrimSpace(p[1])
|
|
||||||
case "default_realm":
|
|
||||||
l.DefaultRealm = strings.TrimSpace(p[1])
|
|
||||||
case "default_tgs_enctypes":
|
|
||||||
l.DefaultTGSEnctypes = strings.Fields(p[1])
|
|
||||||
case "default_tkt_enctypes":
|
|
||||||
l.DefaultTktEnctypes = strings.Fields(p[1])
|
|
||||||
case "dns_canonicalize_hostname":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.DNSCanonicalizeHostname = v
|
|
||||||
case "dns_lookup_kdc":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.DNSLookupKDC = v
|
|
||||||
case "dns_lookup_realm":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.DNSLookupRealm = v
|
|
||||||
case "extra_addresses":
|
|
||||||
ipStr := strings.TrimSpace(p[1])
|
|
||||||
for _, ip := range strings.Split(ipStr, ",") {
|
|
||||||
if eip := net.ParseIP(ip); eip != nil {
|
|
||||||
l.ExtraAddresses = append(l.ExtraAddresses, eip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "forwardable":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.Forwardable = v
|
|
||||||
case "ignore_acceptor_hostname":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.IgnoreAcceptorHostname = v
|
|
||||||
case "k5login_authoritative":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.K5LoginAuthoritative = v
|
|
||||||
case "k5login_directory":
|
|
||||||
l.K5LoginDirectory = strings.TrimSpace(p[1])
|
|
||||||
case "kdc_default_options":
|
|
||||||
v := strings.TrimSpace(p[1])
|
|
||||||
v = strings.Replace(v, "0x", "", -1)
|
|
||||||
b, err := hex.DecodeString(v)
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.KDCDefaultOptions.Bytes = b
|
|
||||||
l.KDCDefaultOptions.BitLength = len(b) * 8
|
|
||||||
case "kdc_timesync":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
v, err := strconv.ParseInt(p[1], 10, 32)
|
|
||||||
if err != nil || v < 0 {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
l.KDCTimeSync = int(v)
|
|
||||||
case "noaddresses":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.NoAddresses = v
|
|
||||||
case "permitted_enctypes":
|
|
||||||
l.PermittedEnctypes = strings.Fields(p[1])
|
|
||||||
case "preferred_preauth_types":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
t := strings.Split(p[1], ",")
|
|
||||||
var v []int
|
|
||||||
for _, s := range t {
|
|
||||||
i, err := strconv.ParseInt(s, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
v = append(v, int(i))
|
|
||||||
}
|
|
||||||
l.PreferredPreauthTypes = v
|
|
||||||
case "proxiable":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.Proxiable = v
|
|
||||||
case "rdns":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.RDNS = v
|
|
||||||
case "realm_try_domains":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
v, err := strconv.ParseInt(p[1], 10, 32)
|
|
||||||
if err != nil || v < -1 {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
l.RealmTryDomains = int(v)
|
|
||||||
case "renew_lifetime":
|
|
||||||
d, err := parseDuration(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.RenewLifetime = d
|
|
||||||
case "safe_checksum_type":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
v, err := strconv.ParseInt(p[1], 10, 32)
|
|
||||||
if err != nil || v < 0 {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
l.SafeChecksumType = int(v)
|
|
||||||
case "ticket_lifetime":
|
|
||||||
d, err := parseDuration(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.TicketLifetime = d
|
|
||||||
case "udp_preference_limit":
|
|
||||||
p[1] = strings.TrimSpace(p[1])
|
|
||||||
v, err := strconv.ParseUint(p[1], 10, 32)
|
|
||||||
if err != nil || v > 32700 {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s)", line)
|
|
||||||
}
|
|
||||||
l.UDPPreferenceLimit = int(v)
|
|
||||||
case "verify_ap_req_nofail":
|
|
||||||
v, err := parseBoolean(p[1])
|
|
||||||
if err != nil {
|
|
||||||
return InvalidErrorf("libdefaults section line (%s): %v", line, err)
|
|
||||||
}
|
|
||||||
l.VerifyAPReqNofail = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
l.DefaultTGSEnctypeIDs = parseETypes(l.DefaultTGSEnctypes, l.AllowWeakCrypto)
|
|
||||||
l.DefaultTktEnctypeIDs = parseETypes(l.DefaultTktEnctypes, l.AllowWeakCrypto)
|
|
||||||
l.PermittedEnctypeIDs = parseETypes(l.PermittedEnctypes, l.AllowWeakCrypto)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Realm represents an entry in the [realms] section of the configuration.
|
|
||||||
type Realm struct {
|
|
||||||
Realm string
|
|
||||||
AdminServer []string
|
|
||||||
//auth_to_local //Not implementing for now
|
|
||||||
//auth_to_local_names //Not implementing for now
|
|
||||||
DefaultDomain string
|
|
||||||
KDC []string
|
|
||||||
KPasswdServer []string //default admin_server:464
|
|
||||||
MasterKDC []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the lines of a [realms] entry into the Realm struct.
|
|
||||||
func (r *Realm) parseLines(name string, lines []string) (err error) {
|
|
||||||
r.Realm = name
|
|
||||||
var adminServerFinal bool
|
|
||||||
var KDCFinal bool
|
|
||||||
var kpasswdServerFinal bool
|
|
||||||
var masterKDCFinal bool
|
|
||||||
var ignore bool
|
|
||||||
var c int // counts the depth of blocks within brackets { }
|
|
||||||
for _, line := range lines {
|
|
||||||
if ignore && c > 0 && !strings.Contains(line, "{") && !strings.Contains(line, "}") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//Remove comments after the values
|
|
||||||
if idx := strings.IndexAny(line, "#;"); idx != -1 {
|
|
||||||
line = line[:idx]
|
|
||||||
}
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.Contains(line, "=") && !strings.Contains(line, "}") {
|
|
||||||
return InvalidErrorf("realms section line (%s)", line)
|
|
||||||
}
|
|
||||||
if strings.Contains(line, "v4_") {
|
|
||||||
ignore = true
|
|
||||||
err = UnsupportedDirective{"v4 configurations are not supported"}
|
|
||||||
}
|
|
||||||
if strings.Contains(line, "{") {
|
|
||||||
c++
|
|
||||||
if ignore {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.Contains(line, "}") {
|
|
||||||
c--
|
|
||||||
if c < 0 {
|
|
||||||
return InvalidErrorf("unpaired curly brackets")
|
|
||||||
}
|
|
||||||
if ignore {
|
|
||||||
if c < 1 {
|
|
||||||
c = 0
|
|
||||||
ignore = false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p := strings.Split(line, "=")
|
|
||||||
key := strings.TrimSpace(strings.ToLower(p[0]))
|
|
||||||
v := strings.TrimSpace(p[1])
|
|
||||||
switch key {
|
|
||||||
case "admin_server":
|
|
||||||
appendUntilFinal(&r.AdminServer, v, &adminServerFinal)
|
|
||||||
case "default_domain":
|
|
||||||
r.DefaultDomain = v
|
|
||||||
case "kdc":
|
|
||||||
if !strings.Contains(v, ":") {
|
|
||||||
// No port number specified default to 88
|
|
||||||
if strings.HasSuffix(v, `*`) {
|
|
||||||
v = strings.TrimSpace(strings.TrimSuffix(v, `*`)) + ":88*"
|
|
||||||
} else {
|
|
||||||
v = strings.TrimSpace(v) + ":88"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendUntilFinal(&r.KDC, v, &KDCFinal)
|
|
||||||
case "kpasswd_server":
|
|
||||||
appendUntilFinal(&r.KPasswdServer, v, &kpasswdServerFinal)
|
|
||||||
case "master_kdc":
|
|
||||||
appendUntilFinal(&r.MasterKDC, v, &masterKDCFinal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//default for Kpasswd_server = admin_server:464
|
|
||||||
if len(r.KPasswdServer) < 1 {
|
|
||||||
for _, a := range r.AdminServer {
|
|
||||||
s := strings.Split(a, ":")
|
|
||||||
r.KPasswdServer = append(r.KPasswdServer, s[0]+":464")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the lines of the [realms] section of the configuration into an slice of Realm structs.
|
|
||||||
func parseRealms(lines []string) (realms []Realm, err error) {
|
|
||||||
var name string
|
|
||||||
var start int
|
|
||||||
var c int
|
|
||||||
for i, l := range lines {
|
|
||||||
//Remove comments after the values
|
|
||||||
if idx := strings.IndexAny(l, "#;"); idx != -1 {
|
|
||||||
l = l[:idx]
|
|
||||||
}
|
|
||||||
l = strings.TrimSpace(l)
|
|
||||||
if l == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//if strings.Contains(l, "v4_") {
|
|
||||||
// return nil, errors.New("v4 configurations are not supported in Realms section")
|
|
||||||
//}
|
|
||||||
if strings.Contains(l, "{") {
|
|
||||||
c++
|
|
||||||
if !strings.Contains(l, "=") {
|
|
||||||
return nil, fmt.Errorf("realm configuration line invalid: %s", l)
|
|
||||||
}
|
|
||||||
if c == 1 {
|
|
||||||
start = i
|
|
||||||
p := strings.Split(l, "=")
|
|
||||||
name = strings.TrimSpace(p[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.Contains(l, "}") {
|
|
||||||
if c < 1 {
|
|
||||||
// but not started a block!!!
|
|
||||||
return nil, errors.New("invalid Realms section in configuration")
|
|
||||||
}
|
|
||||||
c--
|
|
||||||
if c == 0 {
|
|
||||||
var r Realm
|
|
||||||
e := r.parseLines(name, lines[start+1:i])
|
|
||||||
if e != nil {
|
|
||||||
if _, ok := e.(UnsupportedDirective); !ok {
|
|
||||||
err = e
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = e
|
|
||||||
}
|
|
||||||
realms = append(realms, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainRealm maps the domains to realms representing the [domain_realm] section of the configuration.
|
|
||||||
type DomainRealm map[string]string
|
|
||||||
|
|
||||||
// Parse the lines of the [domain_realm] section of the configuration and add to the mapping.
|
|
||||||
func (d *DomainRealm) parseLines(lines []string) error {
|
|
||||||
for _, line := range lines {
|
|
||||||
//Remove comments after the values
|
|
||||||
if idx := strings.IndexAny(line, "#;"); idx != -1 {
|
|
||||||
line = line[:idx]
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(line) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !strings.Contains(line, "=") {
|
|
||||||
return InvalidErrorf("realm line (%s)", line)
|
|
||||||
}
|
|
||||||
p := strings.Split(line, "=")
|
|
||||||
domain := strings.TrimSpace(strings.ToLower(p[0]))
|
|
||||||
realm := strings.TrimSpace(p[1])
|
|
||||||
d.addMapping(domain, realm)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a domain to realm mapping.
|
|
||||||
func (d *DomainRealm) addMapping(domain, realm string) {
|
|
||||||
(*d)[domain] = realm
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete a domain to realm mapping.
|
|
||||||
func (d *DomainRealm) deleteMapping(domain, realm string) {
|
|
||||||
delete(*d, domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveRealm resolves the kerberos realm for the specified domain name from the domain to realm mapping.
|
|
||||||
// The most specific mapping is returned.
|
|
||||||
func (c *Config) ResolveRealm(domainName string) string {
|
|
||||||
domainName = strings.TrimSuffix(domainName, ".")
|
|
||||||
|
|
||||||
// Try to match the entire hostname first
|
|
||||||
if r, ok := c.DomainRealm[domainName]; ok {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to match all DNS domain parts
|
|
||||||
periods := strings.Count(domainName, ".") + 1
|
|
||||||
for i := 2; i <= periods; i++ {
|
|
||||||
z := strings.SplitN(domainName, ".", i)
|
|
||||||
if r, ok := c.DomainRealm["."+z[len(z)-1]]; ok {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c.LibDefaults.DefaultRealm
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the KRB5 configuration from the specified file path.
|
|
||||||
func Load(cfgPath string) (*Config, error) {
|
|
||||||
fh, err := os.Open(cfgPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("configuration file could not be opened: " + cfgPath + " " + err.Error())
|
|
||||||
}
|
|
||||||
defer fh.Close()
|
|
||||||
scanner := bufio.NewScanner(fh)
|
|
||||||
return NewFromScanner(scanner)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFromString creates a new Config struct from a string.
|
|
||||||
func NewFromString(s string) (*Config, error) {
|
|
||||||
reader := strings.NewReader(s)
|
|
||||||
return NewFromReader(reader)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFromReader creates a new Config struct from an io.Reader.
|
|
||||||
func NewFromReader(r io.Reader) (*Config, error) {
|
|
||||||
scanner := bufio.NewScanner(r)
|
|
||||||
return NewFromScanner(scanner)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFromScanner creates a new Config struct from a bufio.Scanner.
|
|
||||||
func NewFromScanner(scanner *bufio.Scanner) (*Config, error) {
|
|
||||||
c := New()
|
|
||||||
var e error
|
|
||||||
sections := make(map[int]string)
|
|
||||||
var sectionLineNum []int
|
|
||||||
var lines []string
|
|
||||||
for scanner.Scan() {
|
|
||||||
// Skip comments and blank lines
|
|
||||||
if matched, _ := regexp.MatchString(`^\s*(#|;|\n)`, scanner.Text()); matched {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matched, _ := regexp.MatchString(`^\s*\[libdefaults\]\s*`, scanner.Text()); matched {
|
|
||||||
sections[len(lines)] = "libdefaults"
|
|
||||||
sectionLineNum = append(sectionLineNum, len(lines))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matched, _ := regexp.MatchString(`^\s*\[realms\]\s*`, scanner.Text()); matched {
|
|
||||||
sections[len(lines)] = "realms"
|
|
||||||
sectionLineNum = append(sectionLineNum, len(lines))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matched, _ := regexp.MatchString(`^\s*\[domain_realm\]\s*`, scanner.Text()); matched {
|
|
||||||
sections[len(lines)] = "domain_realm"
|
|
||||||
sectionLineNum = append(sectionLineNum, len(lines))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if matched, _ := regexp.MatchString(`^\s*\[.*\]\s*`, scanner.Text()); matched {
|
|
||||||
sections[len(lines)] = "unknown_section"
|
|
||||||
sectionLineNum = append(sectionLineNum, len(lines))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
lines = append(lines, scanner.Text())
|
|
||||||
}
|
|
||||||
for i, start := range sectionLineNum {
|
|
||||||
var end int
|
|
||||||
if i+1 >= len(sectionLineNum) {
|
|
||||||
end = len(lines)
|
|
||||||
} else {
|
|
||||||
end = sectionLineNum[i+1]
|
|
||||||
}
|
|
||||||
switch section := sections[start]; section {
|
|
||||||
case "libdefaults":
|
|
||||||
err := c.LibDefaults.parseLines(lines[start:end])
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(UnsupportedDirective); !ok {
|
|
||||||
return nil, fmt.Errorf("error processing libdefaults section: %v", err)
|
|
||||||
}
|
|
||||||
e = err
|
|
||||||
}
|
|
||||||
case "realms":
|
|
||||||
realms, err := parseRealms(lines[start:end])
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(UnsupportedDirective); !ok {
|
|
||||||
return nil, fmt.Errorf("error processing realms section: %v", err)
|
|
||||||
}
|
|
||||||
e = err
|
|
||||||
}
|
|
||||||
c.Realms = realms
|
|
||||||
case "domain_realm":
|
|
||||||
err := c.DomainRealm.parseLines(lines[start:end])
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(UnsupportedDirective); !ok {
|
|
||||||
return nil, fmt.Errorf("error processing domaain_realm section: %v", err)
|
|
||||||
}
|
|
||||||
e = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c, e
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a space delimited list of ETypes into a list of EType numbers optionally filtering out weak ETypes.
|
|
||||||
func parseETypes(s []string, w bool) []int32 {
|
|
||||||
var eti []int32
|
|
||||||
for _, et := range s {
|
|
||||||
if !w {
|
|
||||||
var weak bool
|
|
||||||
for _, wet := range strings.Fields(WeakETypeList) {
|
|
||||||
if et == wet {
|
|
||||||
weak = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if weak {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i := etypeID.EtypeSupported(et)
|
|
||||||
if i != 0 {
|
|
||||||
eti = append(eti, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return eti
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a time duration string in the configuration to a golang time.Duration.
|
|
||||||
func parseDuration(s string) (time.Duration, error) {
|
|
||||||
s = strings.Replace(strings.TrimSpace(s), " ", "", -1)
|
|
||||||
|
|
||||||
// handle Nd[NmNs]
|
|
||||||
if strings.Contains(s, "d") {
|
|
||||||
ds := strings.SplitN(s, "d", 2)
|
|
||||||
dn, err := strconv.ParseUint(ds[0], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return time.Duration(0), errors.New("invalid time duration")
|
|
||||||
}
|
|
||||||
d := time.Duration(dn*24) * time.Hour
|
|
||||||
if ds[1] != "" {
|
|
||||||
dp, err := time.ParseDuration(ds[1])
|
|
||||||
if err != nil {
|
|
||||||
return time.Duration(0), errors.New("invalid time duration")
|
|
||||||
}
|
|
||||||
d = d + dp
|
|
||||||
}
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle Nm[Ns]
|
|
||||||
d, err := time.ParseDuration(s)
|
|
||||||
if err == nil {
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle N
|
|
||||||
v, err := strconv.ParseUint(s, 10, 32)
|
|
||||||
if err == nil && v > 0 {
|
|
||||||
return time.Duration(v) * time.Second, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle h:m[:s]
|
|
||||||
if strings.Contains(s, ":") {
|
|
||||||
t := strings.Split(s, ":")
|
|
||||||
if 2 > len(t) || len(t) > 3 {
|
|
||||||
return time.Duration(0), errors.New("invalid time duration value")
|
|
||||||
}
|
|
||||||
var i []int
|
|
||||||
for _, n := range t {
|
|
||||||
j, err := strconv.ParseInt(n, 10, 16)
|
|
||||||
if err != nil {
|
|
||||||
return time.Duration(0), errors.New("invalid time duration value")
|
|
||||||
}
|
|
||||||
i = append(i, int(j))
|
|
||||||
}
|
|
||||||
d := time.Duration(i[0])*time.Hour + time.Duration(i[1])*time.Minute
|
|
||||||
if len(i) == 3 {
|
|
||||||
d = d + time.Duration(i[2])*time.Second
|
|
||||||
}
|
|
||||||
return d, nil
|
|
||||||
}
|
|
||||||
return time.Duration(0), errors.New("invalid time duration value")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse possible boolean values to golang bool.
|
|
||||||
func parseBoolean(s string) (bool, error) {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
v, err := strconv.ParseBool(s)
|
|
||||||
if err == nil {
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
switch strings.ToLower(s) {
|
|
||||||
case "yes":
|
|
||||||
return true, nil
|
|
||||||
case "y":
|
|
||||||
return true, nil
|
|
||||||
case "no":
|
|
||||||
return false, nil
|
|
||||||
case "n":
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, errors.New("invalid boolean value")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse array of strings but stop if an asterisk is placed at the end of a line.
|
|
||||||
func appendUntilFinal(s *[]string, value string, final *bool) {
|
|
||||||
if *final {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if last := len(value) - 1; last >= 0 && value[last] == '*' {
|
|
||||||
*final = true
|
|
||||||
value = value[:len(value)-1]
|
|
||||||
}
|
|
||||||
*s = append(*s, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON return details of the config in a JSON format.
|
|
||||||
func (c *Config) JSON() (string, error) {
|
|
||||||
b, err := json.MarshalIndent(c, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(b), nil
|
|
||||||
}
|
|
333
vendor/github.com/jcmturner/gokrb5/v8/credentials/ccache.go
generated
vendored
333
vendor/github.com/jcmturner/gokrb5/v8/credentials/ccache.go
generated
vendored
@ -1,333 +0,0 @@
|
|||||||
package credentials
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gofork/encoding/asn1"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
headerFieldTagKDCOffset = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
// CCache is the file credentials cache as define here: https://web.mit.edu/kerberos/krb5-latest/doc/formats/ccache_file_format.html
|
|
||||||
type CCache struct {
|
|
||||||
Version uint8
|
|
||||||
Header header
|
|
||||||
DefaultPrincipal principal
|
|
||||||
Credentials []*Credential
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|
||||||
type header struct {
|
|
||||||
length uint16
|
|
||||||
fields []headerField
|
|
||||||
}
|
|
||||||
|
|
||||||
type headerField struct {
|
|
||||||
tag uint16
|
|
||||||
length uint16
|
|
||||||
value []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credential cache entry principal struct.
|
|
||||||
type principal struct {
|
|
||||||
Realm string
|
|
||||||
PrincipalName types.PrincipalName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credential holds a Kerberos client's ccache credential information.
|
|
||||||
type Credential struct {
|
|
||||||
Client principal
|
|
||||||
Server principal
|
|
||||||
Key types.EncryptionKey
|
|
||||||
AuthTime time.Time
|
|
||||||
StartTime time.Time
|
|
||||||
EndTime time.Time
|
|
||||||
RenewTill time.Time
|
|
||||||
IsSKey bool
|
|
||||||
TicketFlags asn1.BitString
|
|
||||||
Addresses []types.HostAddress
|
|
||||||
AuthData []types.AuthorizationDataEntry
|
|
||||||
Ticket []byte
|
|
||||||
SecondTicket []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadCCache loads a credential cache file into a CCache type.
|
|
||||||
func LoadCCache(cpath string) (*CCache, error) {
|
|
||||||
c := new(CCache)
|
|
||||||
b, err := ioutil.ReadFile(cpath)
|
|
||||||
if err != nil {
|
|
||||||
return c, err
|
|
||||||
}
|
|
||||||
err = c.Unmarshal(b)
|
|
||||||
return c, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal a byte slice of credential cache data into CCache type.
|
|
||||||
func (c *CCache) Unmarshal(b []byte) error {
|
|
||||||
p := 0
|
|
||||||
//The first byte of the file always has the value 5
|
|
||||||
if int8(b[p]) != 5 {
|
|
||||||
return errors.New("Invalid credential cache data. First byte does not equal 5")
|
|
||||||
}
|
|
||||||
p++
|
|
||||||
//Get credential cache version
|
|
||||||
//The second byte contains the version number (1 to 4)
|
|
||||||
c.Version = b[p]
|
|
||||||
if c.Version < 1 || c.Version > 4 {
|
|
||||||
return errors.New("Invalid credential cache data. Keytab version is not within 1 to 4")
|
|
||||||
}
|
|
||||||
p++
|
|
||||||
//Version 1 or 2 of the file format uses native byte order for integer representations. Versions 3 & 4 always uses big-endian byte order
|
|
||||||
var endian binary.ByteOrder
|
|
||||||
endian = binary.BigEndian
|
|
||||||
if (c.Version == 1 || c.Version == 2) && isNativeEndianLittle() {
|
|
||||||
endian = binary.LittleEndian
|
|
||||||
}
|
|
||||||
if c.Version == 4 {
|
|
||||||
err := parseHeader(b, &p, c, &endian)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.DefaultPrincipal = parsePrincipal(b, &p, c, &endian)
|
|
||||||
for p < len(b) {
|
|
||||||
cred, err := parseCredential(b, &p, c, &endian)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.Credentials = append(c.Credentials, cred)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseHeader(b []byte, p *int, c *CCache, e *binary.ByteOrder) error {
|
|
||||||
if c.Version != 4 {
|
|
||||||
return errors.New("Credentials cache version is not 4 so there is no header to parse.")
|
|
||||||
}
|
|
||||||
h := header{}
|
|
||||||
h.length = uint16(readInt16(b, p, e))
|
|
||||||
for *p <= int(h.length) {
|
|
||||||
f := headerField{}
|
|
||||||
f.tag = uint16(readInt16(b, p, e))
|
|
||||||
f.length = uint16(readInt16(b, p, e))
|
|
||||||
f.value = b[*p : *p+int(f.length)]
|
|
||||||
*p += int(f.length)
|
|
||||||
if !f.valid() {
|
|
||||||
return errors.New("Invalid credential cache header found")
|
|
||||||
}
|
|
||||||
h.fields = append(h.fields, f)
|
|
||||||
}
|
|
||||||
c.Header = h
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the Keytab bytes of a principal into a Keytab entry's principal.
|
|
||||||
func parsePrincipal(b []byte, p *int, c *CCache, e *binary.ByteOrder) (princ principal) {
|
|
||||||
if c.Version != 1 {
|
|
||||||
//Name Type is omitted in version 1
|
|
||||||
princ.PrincipalName.NameType = readInt32(b, p, e)
|
|
||||||
}
|
|
||||||
nc := int(readInt32(b, p, e))
|
|
||||||
if c.Version == 1 {
|
|
||||||
//In version 1 the number of components includes the realm. Minus 1 to make consistent with version 2
|
|
||||||
nc--
|
|
||||||
}
|
|
||||||
lenRealm := readInt32(b, p, e)
|
|
||||||
princ.Realm = string(readBytes(b, p, int(lenRealm), e))
|
|
||||||
for i := 0; i < nc; i++ {
|
|
||||||
l := readInt32(b, p, e)
|
|
||||||
princ.PrincipalName.NameString = append(princ.PrincipalName.NameString, string(readBytes(b, p, int(l), e)))
|
|
||||||
}
|
|
||||||
return princ
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseCredential(b []byte, p *int, c *CCache, e *binary.ByteOrder) (cred *Credential, err error) {
|
|
||||||
cred = new(Credential)
|
|
||||||
cred.Client = parsePrincipal(b, p, c, e)
|
|
||||||
cred.Server = parsePrincipal(b, p, c, e)
|
|
||||||
key := types.EncryptionKey{}
|
|
||||||
key.KeyType = int32(readInt16(b, p, e))
|
|
||||||
if c.Version == 3 {
|
|
||||||
//repeated twice in version 3
|
|
||||||
key.KeyType = int32(readInt16(b, p, e))
|
|
||||||
}
|
|
||||||
key.KeyValue = readData(b, p, e)
|
|
||||||
cred.Key = key
|
|
||||||
cred.AuthTime = readTimestamp(b, p, e)
|
|
||||||
cred.StartTime = readTimestamp(b, p, e)
|
|
||||||
cred.EndTime = readTimestamp(b, p, e)
|
|
||||||
cred.RenewTill = readTimestamp(b, p, e)
|
|
||||||
if ik := readInt8(b, p, e); ik == 0 {
|
|
||||||
cred.IsSKey = false
|
|
||||||
} else {
|
|
||||||
cred.IsSKey = true
|
|
||||||
}
|
|
||||||
cred.TicketFlags = types.NewKrbFlags()
|
|
||||||
cred.TicketFlags.Bytes = readBytes(b, p, 4, e)
|
|
||||||
l := int(readInt32(b, p, e))
|
|
||||||
cred.Addresses = make([]types.HostAddress, l, l)
|
|
||||||
for i := range cred.Addresses {
|
|
||||||
cred.Addresses[i] = readAddress(b, p, e)
|
|
||||||
}
|
|
||||||
l = int(readInt32(b, p, e))
|
|
||||||
cred.AuthData = make([]types.AuthorizationDataEntry, l, l)
|
|
||||||
for i := range cred.AuthData {
|
|
||||||
cred.AuthData[i] = readAuthDataEntry(b, p, e)
|
|
||||||
}
|
|
||||||
cred.Ticket = readData(b, p, e)
|
|
||||||
cred.SecondTicket = readData(b, p, e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetClientPrincipalName returns a PrincipalName type for the client the credentials cache is for.
|
|
||||||
func (c *CCache) GetClientPrincipalName() types.PrincipalName {
|
|
||||||
return c.DefaultPrincipal.PrincipalName
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetClientRealm returns the reals of the client the credentials cache is for.
|
|
||||||
func (c *CCache) GetClientRealm() string {
|
|
||||||
return c.DefaultPrincipal.Realm
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetClientCredentials returns a Credentials object representing the client of the credentials cache.
|
|
||||||
func (c *CCache) GetClientCredentials() *Credentials {
|
|
||||||
return &Credentials{
|
|
||||||
username: c.DefaultPrincipal.PrincipalName.PrincipalNameString(),
|
|
||||||
realm: c.GetClientRealm(),
|
|
||||||
cname: c.DefaultPrincipal.PrincipalName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains tests if the cache contains a credential for the provided server PrincipalName
|
|
||||||
func (c *CCache) Contains(p types.PrincipalName) bool {
|
|
||||||
for _, cred := range c.Credentials {
|
|
||||||
if cred.Server.PrincipalName.Equal(p) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntry returns a specific credential for the PrincipalName provided.
|
|
||||||
func (c *CCache) GetEntry(p types.PrincipalName) (*Credential, bool) {
|
|
||||||
cred := new(Credential)
|
|
||||||
var found bool
|
|
||||||
for i := range c.Credentials {
|
|
||||||
if c.Credentials[i].Server.PrincipalName.Equal(p) {
|
|
||||||
cred = c.Credentials[i]
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return cred, false
|
|
||||||
}
|
|
||||||
return cred, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEntries filters out configuration entries an returns a slice of credentials.
|
|
||||||
func (c *CCache) GetEntries() []*Credential {
|
|
||||||
creds := make([]*Credential, 0)
|
|
||||||
for _, cred := range c.Credentials {
|
|
||||||
// Filter out configuration entries
|
|
||||||
if strings.HasPrefix(cred.Server.Realm, "X-CACHECONF") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
creds = append(creds, cred)
|
|
||||||
}
|
|
||||||
return creds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *headerField) valid() bool {
|
|
||||||
// See https://web.mit.edu/kerberos/krb5-latest/doc/formats/ccache_file_format.html - Header format
|
|
||||||
switch h.tag {
|
|
||||||
case headerFieldTagKDCOffset:
|
|
||||||
if h.length != 8 || len(h.value) != 8 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func readData(b []byte, p *int, e *binary.ByteOrder) []byte {
|
|
||||||
l := readInt32(b, p, e)
|
|
||||||
return readBytes(b, p, int(l), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAddress(b []byte, p *int, e *binary.ByteOrder) types.HostAddress {
|
|
||||||
a := types.HostAddress{}
|
|
||||||
a.AddrType = int32(readInt16(b, p, e))
|
|
||||||
a.Address = readData(b, p, e)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAuthDataEntry(b []byte, p *int, e *binary.ByteOrder) types.AuthorizationDataEntry {
|
|
||||||
a := types.AuthorizationDataEntry{}
|
|
||||||
a.ADType = int32(readInt16(b, p, e))
|
|
||||||
a.ADData = readData(b, p, e)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read bytes representing a timestamp.
|
|
||||||
func readTimestamp(b []byte, p *int, e *binary.ByteOrder) time.Time {
|
|
||||||
return time.Unix(int64(readInt32(b, p, e)), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read bytes representing an eight bit integer.
|
|
||||||
func readInt8(b []byte, p *int, e *binary.ByteOrder) (i int8) {
|
|
||||||
buf := bytes.NewBuffer(b[*p : *p+1])
|
|
||||||
binary.Read(buf, *e, &i)
|
|
||||||
*p++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read bytes representing a sixteen bit integer.
|
|
||||||
func readInt16(b []byte, p *int, e *binary.ByteOrder) (i int16) {
|
|
||||||
buf := bytes.NewBuffer(b[*p : *p+2])
|
|
||||||
binary.Read(buf, *e, &i)
|
|
||||||
*p += 2
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read bytes representing a thirty two bit integer.
|
|
||||||
func readInt32(b []byte, p *int, e *binary.ByteOrder) (i int32) {
|
|
||||||
buf := bytes.NewBuffer(b[*p : *p+4])
|
|
||||||
binary.Read(buf, *e, &i)
|
|
||||||
*p += 4
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func readBytes(b []byte, p *int, s int, e *binary.ByteOrder) []byte {
|
|
||||||
buf := bytes.NewBuffer(b[*p : *p+s])
|
|
||||||
r := make([]byte, s)
|
|
||||||
binary.Read(buf, *e, &r)
|
|
||||||
*p += s
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNativeEndianLittle() bool {
|
|
||||||
var x = 0x012345678
|
|
||||||
var p = unsafe.Pointer(&x)
|
|
||||||
var bp = (*[4]byte)(p)
|
|
||||||
|
|
||||||
var endian bool
|
|
||||||
if 0x01 == bp[0] {
|
|
||||||
endian = false
|
|
||||||
} else if (0x78 & 0xff) == (bp[0] & 0xff) {
|
|
||||||
endian = true
|
|
||||||
} else {
|
|
||||||
// Default to big endian
|
|
||||||
endian = false
|
|
||||||
}
|
|
||||||
return endian
|
|
||||||
}
|
|
405
vendor/github.com/jcmturner/gokrb5/v8/credentials/credentials.go
generated
vendored
405
vendor/github.com/jcmturner/gokrb5/v8/credentials/credentials.go
generated
vendored
@ -1,405 +0,0 @@
|
|||||||
// Package credentials provides credentials management for Kerberos 5 authentication.
|
|
||||||
package credentials
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-uuid"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/nametype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/keytab"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// AttributeKeyADCredentials assigned number for AD credentials.
|
|
||||||
AttributeKeyADCredentials = "gokrb5AttributeKeyADCredentials"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Credentials struct for a user.
|
|
||||||
// Contains either a keytab, password or both.
|
|
||||||
// Keytabs are used over passwords if both are defined.
|
|
||||||
type Credentials struct {
|
|
||||||
username string
|
|
||||||
displayName string
|
|
||||||
realm string
|
|
||||||
cname types.PrincipalName
|
|
||||||
keytab *keytab.Keytab
|
|
||||||
password string
|
|
||||||
attributes map[string]interface{}
|
|
||||||
validUntil time.Time
|
|
||||||
authenticated bool
|
|
||||||
human bool
|
|
||||||
authTime time.Time
|
|
||||||
groupMembership map[string]bool
|
|
||||||
sessionID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// marshalCredentials is used to enable marshaling and unmarshaling of credentials
|
|
||||||
// without having exported fields on the Credentials struct
|
|
||||||
type marshalCredentials struct {
|
|
||||||
Username string
|
|
||||||
DisplayName string
|
|
||||||
Realm string
|
|
||||||
CName types.PrincipalName `json:"-"`
|
|
||||||
Keytab bool
|
|
||||||
Password bool
|
|
||||||
Attributes map[string]interface{} `json:"-"`
|
|
||||||
ValidUntil time.Time
|
|
||||||
Authenticated bool
|
|
||||||
Human bool
|
|
||||||
AuthTime time.Time
|
|
||||||
GroupMembership map[string]bool `json:"-"`
|
|
||||||
SessionID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ADCredentials contains information obtained from the PAC.
|
|
||||||
type ADCredentials struct {
|
|
||||||
EffectiveName string
|
|
||||||
FullName string
|
|
||||||
UserID int
|
|
||||||
PrimaryGroupID int
|
|
||||||
LogOnTime time.Time
|
|
||||||
LogOffTime time.Time
|
|
||||||
PasswordLastSet time.Time
|
|
||||||
GroupMembershipSIDs []string
|
|
||||||
LogonDomainName string
|
|
||||||
LogonDomainID string
|
|
||||||
LogonServer string
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Credentials instance.
|
|
||||||
func New(username string, realm string) *Credentials {
|
|
||||||
uid, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
uid = "00unique-sess-ions-uuid-unavailable0"
|
|
||||||
}
|
|
||||||
return &Credentials{
|
|
||||||
username: username,
|
|
||||||
displayName: username,
|
|
||||||
realm: realm,
|
|
||||||
cname: types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, username),
|
|
||||||
keytab: keytab.New(),
|
|
||||||
attributes: make(map[string]interface{}),
|
|
||||||
groupMembership: make(map[string]bool),
|
|
||||||
sessionID: uid,
|
|
||||||
human: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFromPrincipalName creates a new Credentials instance with the user details provides as a PrincipalName type.
|
|
||||||
func NewFromPrincipalName(cname types.PrincipalName, realm string) *Credentials {
|
|
||||||
c := New(cname.PrincipalNameString(), realm)
|
|
||||||
c.cname = cname
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithKeytab sets the Keytab in the Credentials struct.
|
|
||||||
func (c *Credentials) WithKeytab(kt *keytab.Keytab) *Credentials {
|
|
||||||
c.keytab = kt
|
|
||||||
c.password = ""
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keytab returns the credential's Keytab.
|
|
||||||
func (c *Credentials) Keytab() *keytab.Keytab {
|
|
||||||
return c.keytab
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasKeytab queries if the Credentials has a keytab defined.
|
|
||||||
func (c *Credentials) HasKeytab() bool {
|
|
||||||
if c.keytab != nil && len(c.keytab.Entries) > 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPassword sets the password in the Credentials struct.
|
|
||||||
func (c *Credentials) WithPassword(password string) *Credentials {
|
|
||||||
c.password = password
|
|
||||||
c.keytab = keytab.New() // clear any keytab
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Password returns the credential's password.
|
|
||||||
func (c *Credentials) Password() string {
|
|
||||||
return c.password
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasPassword queries if the Credentials has a password defined.
|
|
||||||
func (c *Credentials) HasPassword() bool {
|
|
||||||
if c.password != "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetValidUntil sets the expiry time of the credentials
|
|
||||||
func (c *Credentials) SetValidUntil(t time.Time) {
|
|
||||||
c.validUntil = t
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetADCredentials adds ADCredentials attributes to the credentials
|
|
||||||
func (c *Credentials) SetADCredentials(a ADCredentials) {
|
|
||||||
c.SetAttribute(AttributeKeyADCredentials, a)
|
|
||||||
if a.FullName != "" {
|
|
||||||
c.SetDisplayName(a.FullName)
|
|
||||||
}
|
|
||||||
if a.EffectiveName != "" {
|
|
||||||
c.SetUserName(a.EffectiveName)
|
|
||||||
}
|
|
||||||
for i := range a.GroupMembershipSIDs {
|
|
||||||
c.AddAuthzAttribute(a.GroupMembershipSIDs[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetADCredentials returns ADCredentials attributes sorted in the credential
|
|
||||||
func (c *Credentials) GetADCredentials() ADCredentials {
|
|
||||||
if a, ok := c.attributes[AttributeKeyADCredentials].(ADCredentials); ok {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return ADCredentials{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods to implement goidentity.Identity interface
|
|
||||||
|
|
||||||
// UserName returns the credential's username.
|
|
||||||
func (c *Credentials) UserName() string {
|
|
||||||
return c.username
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetUserName sets the username value on the credential.
|
|
||||||
func (c *Credentials) SetUserName(s string) {
|
|
||||||
c.username = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// CName returns the credential's client principal name.
|
|
||||||
func (c *Credentials) CName() types.PrincipalName {
|
|
||||||
return c.cname
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetCName sets the client principal name on the credential.
|
|
||||||
func (c *Credentials) SetCName(pn types.PrincipalName) {
|
|
||||||
c.cname = pn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain returns the credential's domain.
|
|
||||||
func (c *Credentials) Domain() string {
|
|
||||||
return c.realm
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDomain sets the domain value on the credential.
|
|
||||||
func (c *Credentials) SetDomain(s string) {
|
|
||||||
c.realm = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Realm returns the credential's realm. Same as the domain.
|
|
||||||
func (c *Credentials) Realm() string {
|
|
||||||
return c.Domain()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRealm sets the realm value on the credential. Same as the domain
|
|
||||||
func (c *Credentials) SetRealm(s string) {
|
|
||||||
c.SetDomain(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisplayName returns the credential's display name.
|
|
||||||
func (c *Credentials) DisplayName() string {
|
|
||||||
return c.displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDisplayName sets the display name value on the credential.
|
|
||||||
func (c *Credentials) SetDisplayName(s string) {
|
|
||||||
c.displayName = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Human returns if the credential represents a human or not.
|
|
||||||
func (c *Credentials) Human() bool {
|
|
||||||
return c.human
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHuman sets the credential as human.
|
|
||||||
func (c *Credentials) SetHuman(b bool) {
|
|
||||||
c.human = b
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthTime returns the time the credential was authenticated.
|
|
||||||
func (c *Credentials) AuthTime() time.Time {
|
|
||||||
return c.authTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthTime sets the time the credential was authenticated.
|
|
||||||
func (c *Credentials) SetAuthTime(t time.Time) {
|
|
||||||
c.authTime = t
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthzAttributes returns the credentials authorizing attributes.
|
|
||||||
func (c *Credentials) AuthzAttributes() []string {
|
|
||||||
s := make([]string, len(c.groupMembership))
|
|
||||||
i := 0
|
|
||||||
for a := range c.groupMembership {
|
|
||||||
s[i] = a
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authenticated indicates if the credential has been successfully authenticated or not.
|
|
||||||
func (c *Credentials) Authenticated() bool {
|
|
||||||
return c.authenticated
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthenticated sets the credential as having been successfully authenticated.
|
|
||||||
func (c *Credentials) SetAuthenticated(b bool) {
|
|
||||||
c.authenticated = b
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAuthzAttribute adds an authorization attribute to the credential.
|
|
||||||
func (c *Credentials) AddAuthzAttribute(a string) {
|
|
||||||
c.groupMembership[a] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveAuthzAttribute removes an authorization attribute from the credential.
|
|
||||||
func (c *Credentials) RemoveAuthzAttribute(a string) {
|
|
||||||
if _, ok := c.groupMembership[a]; !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
delete(c.groupMembership, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableAuthzAttribute toggles an authorization attribute to an enabled state on the credential.
|
|
||||||
func (c *Credentials) EnableAuthzAttribute(a string) {
|
|
||||||
if enabled, ok := c.groupMembership[a]; ok && !enabled {
|
|
||||||
c.groupMembership[a] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableAuthzAttribute toggles an authorization attribute to a disabled state on the credential.
|
|
||||||
func (c *Credentials) DisableAuthzAttribute(a string) {
|
|
||||||
if enabled, ok := c.groupMembership[a]; ok && enabled {
|
|
||||||
c.groupMembership[a] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authorized indicates if the credential has the specified authorizing attribute.
|
|
||||||
func (c *Credentials) Authorized(a string) bool {
|
|
||||||
if enabled, ok := c.groupMembership[a]; ok && enabled {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionID returns the credential's session ID.
|
|
||||||
func (c *Credentials) SessionID() string {
|
|
||||||
return c.sessionID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expired indicates if the credential has expired.
|
|
||||||
func (c *Credentials) Expired() bool {
|
|
||||||
if !c.validUntil.IsZero() && time.Now().UTC().After(c.validUntil) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidUntil returns the credential's valid until date
|
|
||||||
func (c *Credentials) ValidUntil() time.Time {
|
|
||||||
return c.validUntil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attributes returns the Credentials' attributes map.
|
|
||||||
func (c *Credentials) Attributes() map[string]interface{} {
|
|
||||||
return c.attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAttribute sets the value of an attribute.
|
|
||||||
func (c *Credentials) SetAttribute(k string, v interface{}) {
|
|
||||||
c.attributes[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAttributes replaces the attributes map with the one provided.
|
|
||||||
func (c *Credentials) SetAttributes(a map[string]interface{}) {
|
|
||||||
c.attributes = a
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveAttribute deletes an attribute from the attribute map that has the key provided.
|
|
||||||
func (c *Credentials) RemoveAttribute(k string) {
|
|
||||||
delete(c.attributes, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal the Credentials into a byte slice
|
|
||||||
func (c *Credentials) Marshal() ([]byte, error) {
|
|
||||||
gob.Register(map[string]interface{}{})
|
|
||||||
gob.Register(ADCredentials{})
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
enc := gob.NewEncoder(buf)
|
|
||||||
mc := marshalCredentials{
|
|
||||||
Username: c.username,
|
|
||||||
DisplayName: c.displayName,
|
|
||||||
Realm: c.realm,
|
|
||||||
CName: c.cname,
|
|
||||||
Keytab: c.HasKeytab(),
|
|
||||||
Password: c.HasPassword(),
|
|
||||||
Attributes: c.attributes,
|
|
||||||
ValidUntil: c.validUntil,
|
|
||||||
Authenticated: c.authenticated,
|
|
||||||
Human: c.human,
|
|
||||||
AuthTime: c.authTime,
|
|
||||||
GroupMembership: c.groupMembership,
|
|
||||||
SessionID: c.sessionID,
|
|
||||||
}
|
|
||||||
err := enc.Encode(&mc)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal a byte slice into Credentials
|
|
||||||
func (c *Credentials) Unmarshal(b []byte) error {
|
|
||||||
gob.Register(map[string]interface{}{})
|
|
||||||
gob.Register(ADCredentials{})
|
|
||||||
mc := new(marshalCredentials)
|
|
||||||
buf := bytes.NewBuffer(b)
|
|
||||||
dec := gob.NewDecoder(buf)
|
|
||||||
err := dec.Decode(mc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.username = mc.Username
|
|
||||||
c.displayName = mc.DisplayName
|
|
||||||
c.realm = mc.Realm
|
|
||||||
c.cname = mc.CName
|
|
||||||
c.attributes = mc.Attributes
|
|
||||||
c.validUntil = mc.ValidUntil
|
|
||||||
c.authenticated = mc.Authenticated
|
|
||||||
c.human = mc.Human
|
|
||||||
c.authTime = mc.AuthTime
|
|
||||||
c.groupMembership = mc.GroupMembership
|
|
||||||
c.sessionID = mc.SessionID
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON return details of the Credentials in a JSON format.
|
|
||||||
func (c *Credentials) JSON() (string, error) {
|
|
||||||
mc := marshalCredentials{
|
|
||||||
Username: c.username,
|
|
||||||
DisplayName: c.displayName,
|
|
||||||
Realm: c.realm,
|
|
||||||
CName: c.cname,
|
|
||||||
Keytab: c.HasKeytab(),
|
|
||||||
Password: c.HasPassword(),
|
|
||||||
ValidUntil: c.validUntil,
|
|
||||||
Authenticated: c.authenticated,
|
|
||||||
Human: c.human,
|
|
||||||
AuthTime: c.authTime,
|
|
||||||
SessionID: c.sessionID,
|
|
||||||
}
|
|
||||||
b, err := json.MarshalIndent(mc, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(b), nil
|
|
||||||
}
|
|
129
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes128-cts-hmac-sha1-96.go
generated
vendored
129
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes128-cts-hmac-sha1-96.go
generated
vendored
@ -1,129 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3961"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3962"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RFC 3962
|
|
||||||
|
|
||||||
// Aes128CtsHmacSha96 implements Kerberos encryption type aes128-cts-hmac-sha1-96
|
|
||||||
type Aes128CtsHmacSha96 struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e Aes128CtsHmacSha96) GetETypeID() int32 {
|
|
||||||
return etypeID.AES128_CTS_HMAC_SHA1_96
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e Aes128CtsHmacSha96) GetHashID() int32 {
|
|
||||||
return chksumtype.HMAC_SHA1_96_AES128
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e Aes128CtsHmacSha96) GetKeyByteSize() int {
|
|
||||||
return 128 / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e Aes128CtsHmacSha96) GetKeySeedBitLength() int {
|
|
||||||
return e.GetKeyByteSize() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e Aes128CtsHmacSha96) GetHashFunc() func() hash.Hash {
|
|
||||||
return sha1.New
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e Aes128CtsHmacSha96) GetMessageBlockByteSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e Aes128CtsHmacSha96) GetDefaultStringToKeyParams() string {
|
|
||||||
return "00001000"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e Aes128CtsHmacSha96) GetConfounderByteSize() int {
|
|
||||||
return aes.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e Aes128CtsHmacSha96) GetHMACBitLength() int {
|
|
||||||
return 96
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e Aes128CtsHmacSha96) GetCypherBlockBitLength() int {
|
|
||||||
return aes.BlockSize * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e Aes128CtsHmacSha96) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
return rfc3962.StringToKey(secret, salt, s2kparams, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e Aes128CtsHmacSha96) RandomToKey(b []byte) []byte {
|
|
||||||
return rfc3961.RandomToKey(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e Aes128CtsHmacSha96) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
return rfc3962.EncryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e Aes128CtsHmacSha96) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
return rfc3962.EncryptMessage(key, message, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e Aes128CtsHmacSha96) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc3962.DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e Aes128CtsHmacSha96) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc3962.DecryptMessage(key, ciphertext, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e Aes128CtsHmacSha96) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DeriveKey(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e Aes128CtsHmacSha96) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DeriveRandom(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the plaintext message.
|
|
||||||
func (e Aes128CtsHmacSha96) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
return rfc3961.VerifyIntegrity(protocolKey, ct, pt, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e Aes128CtsHmacSha96) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return common.GetHash(data, protocolKey, common.GetUsageKc(usage), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e Aes128CtsHmacSha96) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
c, err := e.GetChecksumHash(protocolKey, data, usage)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(chksum, c)
|
|
||||||
}
|
|
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes128-cts-hmac-sha256-128.go
generated
vendored
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes128-cts-hmac-sha256-128.go
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
"hash"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc8009"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RFC https://tools.ietf.org/html/rfc8009
|
|
||||||
|
|
||||||
// Aes128CtsHmacSha256128 implements Kerberos encryption type aes128-cts-hmac-sha256-128
|
|
||||||
type Aes128CtsHmacSha256128 struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetETypeID() int32 {
|
|
||||||
return etypeID.AES128_CTS_HMAC_SHA256_128
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetHashID() int32 {
|
|
||||||
return chksumtype.HMAC_SHA256_128_AES128
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetKeyByteSize() int {
|
|
||||||
return 128 / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetKeySeedBitLength() int {
|
|
||||||
return e.GetKeyByteSize() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetHashFunc() func() hash.Hash {
|
|
||||||
return sha256.New
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetMessageBlockByteSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetDefaultStringToKeyParams() string {
|
|
||||||
return "00008000"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetConfounderByteSize() int {
|
|
||||||
return aes.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetHMACBitLength() int {
|
|
||||||
return 128
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetCypherBlockBitLength() int {
|
|
||||||
return aes.BlockSize * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
saltp := rfc8009.GetSaltP(salt, "aes128-cts-hmac-sha256-128")
|
|
||||||
return rfc8009.StringToKey(secret, saltp, s2kparams, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) RandomToKey(b []byte) []byte {
|
|
||||||
return rfc8009.RandomToKey(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
return rfc8009.EncryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e Aes128CtsHmacSha256128) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
return rfc8009.EncryptMessage(key, message, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e Aes128CtsHmacSha256128) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc8009.DecryptMessage(key, ciphertext, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e Aes128CtsHmacSha256128) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DeriveKey(protocolKey, usage, e), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e Aes128CtsHmacSha256128) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DeriveRandom(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the ciphertext message.
|
|
||||||
// As the hash is calculated over the iv concatenated with the AES cipher output not the plaintext the pt value to this
|
|
||||||
// interface method is not use. Pass any []byte.
|
|
||||||
func (e Aes128CtsHmacSha256128) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
// We don't need ib just there for the interface
|
|
||||||
return rfc8009.VerifyIntegrity(protocolKey, ct, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return common.GetHash(data, protocolKey, common.GetUsageKc(usage), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e Aes128CtsHmacSha256128) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
c, err := e.GetChecksumHash(protocolKey, data, usage)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(chksum, c)
|
|
||||||
}
|
|
129
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes256-cts-hmac-sha1-96.go
generated
vendored
129
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes256-cts-hmac-sha1-96.go
generated
vendored
@ -1,129 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3961"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3962"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RFC 3962
|
|
||||||
|
|
||||||
// Aes256CtsHmacSha96 implements Kerberos encryption type aes256-cts-hmac-sha1-96
|
|
||||||
type Aes256CtsHmacSha96 struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e Aes256CtsHmacSha96) GetETypeID() int32 {
|
|
||||||
return etypeID.AES256_CTS_HMAC_SHA1_96
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e Aes256CtsHmacSha96) GetHashID() int32 {
|
|
||||||
return chksumtype.HMAC_SHA1_96_AES256
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e Aes256CtsHmacSha96) GetKeyByteSize() int {
|
|
||||||
return 256 / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e Aes256CtsHmacSha96) GetKeySeedBitLength() int {
|
|
||||||
return e.GetKeyByteSize() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e Aes256CtsHmacSha96) GetHashFunc() func() hash.Hash {
|
|
||||||
return sha1.New
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e Aes256CtsHmacSha96) GetMessageBlockByteSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e Aes256CtsHmacSha96) GetDefaultStringToKeyParams() string {
|
|
||||||
return "00001000"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e Aes256CtsHmacSha96) GetConfounderByteSize() int {
|
|
||||||
return aes.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e Aes256CtsHmacSha96) GetHMACBitLength() int {
|
|
||||||
return 96
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e Aes256CtsHmacSha96) GetCypherBlockBitLength() int {
|
|
||||||
return aes.BlockSize * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e Aes256CtsHmacSha96) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
return rfc3962.StringToKey(secret, salt, s2kparams, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e Aes256CtsHmacSha96) RandomToKey(b []byte) []byte {
|
|
||||||
return rfc3961.RandomToKey(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e Aes256CtsHmacSha96) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
return rfc3962.EncryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e Aes256CtsHmacSha96) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
return rfc3962.EncryptMessage(key, message, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e Aes256CtsHmacSha96) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc3962.DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e Aes256CtsHmacSha96) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc3962.DecryptMessage(key, ciphertext, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e Aes256CtsHmacSha96) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DeriveKey(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e Aes256CtsHmacSha96) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DeriveRandom(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the plaintext message.
|
|
||||||
func (e Aes256CtsHmacSha96) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
return rfc3961.VerifyIntegrity(protocolKey, ct, pt, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e Aes256CtsHmacSha96) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return common.GetHash(data, protocolKey, common.GetUsageKc(usage), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e Aes256CtsHmacSha96) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
c, err := e.GetChecksumHash(protocolKey, data, usage)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(chksum, c)
|
|
||||||
}
|
|
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes256-cts-hmac-sha384-192.go
generated
vendored
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/aes256-cts-hmac-sha384-192.go
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha512"
|
|
||||||
"hash"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc8009"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RFC https://tools.ietf.org/html/rfc8009
|
|
||||||
|
|
||||||
// Aes256CtsHmacSha384192 implements Kerberos encryption type aes256-cts-hmac-sha384-192
|
|
||||||
type Aes256CtsHmacSha384192 struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetETypeID() int32 {
|
|
||||||
return etypeID.AES256_CTS_HMAC_SHA384_192
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetHashID() int32 {
|
|
||||||
return chksumtype.HMAC_SHA384_192_AES256
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetKeyByteSize() int {
|
|
||||||
return 192 / 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetKeySeedBitLength() int {
|
|
||||||
return e.GetKeyByteSize() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetHashFunc() func() hash.Hash {
|
|
||||||
return sha512.New384
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetMessageBlockByteSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetDefaultStringToKeyParams() string {
|
|
||||||
return "00008000"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetConfounderByteSize() int {
|
|
||||||
return aes.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetHMACBitLength() int {
|
|
||||||
return 192
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetCypherBlockBitLength() int {
|
|
||||||
return aes.BlockSize * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
saltp := rfc8009.GetSaltP(salt, "aes256-cts-hmac-sha384-192")
|
|
||||||
return rfc8009.StringToKey(secret, saltp, s2kparams, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) RandomToKey(b []byte) []byte {
|
|
||||||
return rfc8009.RandomToKey(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
return rfc8009.EncryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e Aes256CtsHmacSha384192) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
return rfc8009.EncryptMessage(key, message, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e Aes256CtsHmacSha384192) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc8009.DecryptMessage(key, ciphertext, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e Aes256CtsHmacSha384192) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DeriveKey(protocolKey, usage, e), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e Aes256CtsHmacSha384192) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc8009.DeriveRandom(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the ciphertext message.
|
|
||||||
// As the hash is calculated over the iv concatenated with the AES cipher output not the plaintext the pt value to this
|
|
||||||
// interface method is not use. Pass any []byte.
|
|
||||||
func (e Aes256CtsHmacSha384192) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
// We don't need ib just there for the interface
|
|
||||||
return rfc8009.VerifyIntegrity(protocolKey, ct, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return common.GetHash(data, protocolKey, common.GetUsageKc(usage), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e Aes256CtsHmacSha384192) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
c, err := e.GetChecksumHash(protocolKey, data, usage)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(chksum, c)
|
|
||||||
}
|
|
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/common/common.go
generated
vendored
132
vendor/github.com/jcmturner/gokrb5/v8/crypto/common/common.go
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
// Package common provides encryption methods common across encryption types
|
|
||||||
package common
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ZeroPad pads bytes with zeros to nearest multiple of message size m.
|
|
||||||
func ZeroPad(b []byte, m int) ([]byte, error) {
|
|
||||||
if m <= 0 {
|
|
||||||
return nil, errors.New("Invalid message block size when padding")
|
|
||||||
}
|
|
||||||
if b == nil || len(b) == 0 {
|
|
||||||
return nil, errors.New("Data not valid to pad: Zero size")
|
|
||||||
}
|
|
||||||
if l := len(b) % m; l != 0 {
|
|
||||||
n := m - l
|
|
||||||
z := make([]byte, n)
|
|
||||||
b = append(b, z...)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PKCS7Pad pads bytes according to RFC 2315 to nearest multiple of message size m.
|
|
||||||
func PKCS7Pad(b []byte, m int) ([]byte, error) {
|
|
||||||
if m <= 0 {
|
|
||||||
return nil, errors.New("Invalid message block size when padding")
|
|
||||||
}
|
|
||||||
if b == nil || len(b) == 0 {
|
|
||||||
return nil, errors.New("Data not valid to pad: Zero size")
|
|
||||||
}
|
|
||||||
n := m - (len(b) % m)
|
|
||||||
pb := make([]byte, len(b)+n)
|
|
||||||
copy(pb, b)
|
|
||||||
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
|
|
||||||
return pb, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PKCS7Unpad removes RFC 2315 padding from byes where message size is m.
|
|
||||||
func PKCS7Unpad(b []byte, m int) ([]byte, error) {
|
|
||||||
if m <= 0 {
|
|
||||||
return nil, errors.New("invalid message block size when unpadding")
|
|
||||||
}
|
|
||||||
if b == nil || len(b) == 0 {
|
|
||||||
return nil, errors.New("padded data not valid: Zero size")
|
|
||||||
}
|
|
||||||
if len(b)%m != 0 {
|
|
||||||
return nil, errors.New("padded data not valid: Not multiple of message block size")
|
|
||||||
}
|
|
||||||
c := b[len(b)-1]
|
|
||||||
n := int(c)
|
|
||||||
if n == 0 || n > len(b) {
|
|
||||||
return nil, errors.New("padded data not valid: Data may not have been padded")
|
|
||||||
}
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
if b[len(b)-n+i] != c {
|
|
||||||
return nil, errors.New("padded data not valid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b[:len(b)-n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHash generates the keyed hash value according to the etype's hash function.
|
|
||||||
func GetHash(pt, key []byte, usage []byte, etype etype.EType) ([]byte, error) {
|
|
||||||
k, err := etype.DeriveKey(key, usage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to derive key for checksum: %v", err)
|
|
||||||
}
|
|
||||||
mac := hmac.New(etype.GetHashFunc(), k)
|
|
||||||
p := make([]byte, len(pt))
|
|
||||||
copy(p, pt)
|
|
||||||
mac.Write(p)
|
|
||||||
return mac.Sum(nil)[:etype.GetHMACBitLength()/8], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func GetChecksumHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
|
|
||||||
return GetHash(b, key, GetUsageKc(usage), etype)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIntegrityHash returns a keyed integrity hash of the bytes provided.
|
|
||||||
func GetIntegrityHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
|
|
||||||
return GetHash(b, key, GetUsageKi(usage), etype)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the msg bytes is the same as the checksum provided.
|
|
||||||
func VerifyChecksum(key, chksum, msg []byte, usage uint32, etype etype.EType) bool {
|
|
||||||
//The encrypted message is a concatenation of the encrypted output and the hash HMAC.
|
|
||||||
expectedMAC, _ := GetChecksumHash(msg, key, usage, etype)
|
|
||||||
return hmac.Equal(chksum, expectedMAC)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsageKc returns the checksum key usage value for the usage number un.
|
|
||||||
//
|
|
||||||
// See RFC 3961 5.3 key-derivation function definition.
|
|
||||||
func GetUsageKc(un uint32) []byte {
|
|
||||||
return getUsage(un, 0x99)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsageKe returns the encryption key usage value for the usage number un
|
|
||||||
//
|
|
||||||
// See RFC 3961 5.3 key-derivation function definition.
|
|
||||||
func GetUsageKe(un uint32) []byte {
|
|
||||||
return getUsage(un, 0xAA)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsageKi returns the integrity key usage value for the usage number un
|
|
||||||
//
|
|
||||||
// See RFC 3961 5.3 key-derivation function definition.
|
|
||||||
func GetUsageKi(un uint32) []byte {
|
|
||||||
return getUsage(un, 0x55)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUsage(un uint32, o byte) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
binary.Write(&buf, binary.BigEndian, un)
|
|
||||||
return append(buf.Bytes(), o)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IterationsToS2Kparams converts the number of iterations as an integer to a string representation.
|
|
||||||
func IterationsToS2Kparams(i uint32) string {
|
|
||||||
b := make([]byte, 4, 4)
|
|
||||||
binary.BigEndian.PutUint32(b, i)
|
|
||||||
return hex.EncodeToString(b)
|
|
||||||
}
|
|
175
vendor/github.com/jcmturner/gokrb5/v8/crypto/crypto.go
generated
vendored
175
vendor/github.com/jcmturner/gokrb5/v8/crypto/crypto.go
generated
vendored
@ -1,175 +0,0 @@
|
|||||||
// Package crypto implements cryptographic functions for Kerberos 5 implementation.
|
|
||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/patype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetEtype returns an instances of the required etype struct for the etype ID.
|
|
||||||
func GetEtype(id int32) (etype.EType, error) {
|
|
||||||
switch id {
|
|
||||||
case etypeID.AES128_CTS_HMAC_SHA1_96:
|
|
||||||
var et Aes128CtsHmacSha96
|
|
||||||
return et, nil
|
|
||||||
case etypeID.AES256_CTS_HMAC_SHA1_96:
|
|
||||||
var et Aes256CtsHmacSha96
|
|
||||||
return et, nil
|
|
||||||
case etypeID.AES128_CTS_HMAC_SHA256_128:
|
|
||||||
var et Aes128CtsHmacSha256128
|
|
||||||
return et, nil
|
|
||||||
case etypeID.AES256_CTS_HMAC_SHA384_192:
|
|
||||||
var et Aes256CtsHmacSha384192
|
|
||||||
return et, nil
|
|
||||||
case etypeID.DES3_CBC_SHA1_KD:
|
|
||||||
var et Des3CbcSha1Kd
|
|
||||||
return et, nil
|
|
||||||
case etypeID.RC4_HMAC:
|
|
||||||
var et RC4HMAC
|
|
||||||
return et, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown or unsupported EType: %d", id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChksumEtype returns an instances of the required etype struct for the checksum ID.
|
|
||||||
func GetChksumEtype(id int32) (etype.EType, error) {
|
|
||||||
switch id {
|
|
||||||
case chksumtype.HMAC_SHA1_96_AES128:
|
|
||||||
var et Aes128CtsHmacSha96
|
|
||||||
return et, nil
|
|
||||||
case chksumtype.HMAC_SHA1_96_AES256:
|
|
||||||
var et Aes256CtsHmacSha96
|
|
||||||
return et, nil
|
|
||||||
case chksumtype.HMAC_SHA256_128_AES128:
|
|
||||||
var et Aes128CtsHmacSha256128
|
|
||||||
return et, nil
|
|
||||||
case chksumtype.HMAC_SHA384_192_AES256:
|
|
||||||
var et Aes256CtsHmacSha384192
|
|
||||||
return et, nil
|
|
||||||
case chksumtype.HMAC_SHA1_DES3_KD:
|
|
||||||
var et Des3CbcSha1Kd
|
|
||||||
return et, nil
|
|
||||||
case chksumtype.KERB_CHECKSUM_HMAC_MD5:
|
|
||||||
var et RC4HMAC
|
|
||||||
return et, nil
|
|
||||||
//case chksumtype.KERB_CHECKSUM_HMAC_MD5_UNSIGNED:
|
|
||||||
// var et RC4HMAC
|
|
||||||
// return et, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown or unsupported checksum type: %d", id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyFromPassword generates an encryption key from the principal's password.
|
|
||||||
func GetKeyFromPassword(passwd string, cname types.PrincipalName, realm string, etypeID int32, pas types.PADataSequence) (types.EncryptionKey, etype.EType, error) {
|
|
||||||
var key types.EncryptionKey
|
|
||||||
et, err := GetEtype(etypeID)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error getting encryption type: %v", err)
|
|
||||||
}
|
|
||||||
sk2p := et.GetDefaultStringToKeyParams()
|
|
||||||
var salt string
|
|
||||||
var paID int32
|
|
||||||
for _, pa := range pas {
|
|
||||||
switch pa.PADataType {
|
|
||||||
case patype.PA_PW_SALT:
|
|
||||||
if paID > pa.PADataType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
salt = string(pa.PADataValue)
|
|
||||||
case patype.PA_ETYPE_INFO:
|
|
||||||
if paID > pa.PADataType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var eti types.ETypeInfo
|
|
||||||
err := eti.Unmarshal(pa.PADataValue)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error unmashaling PA Data to PA-ETYPE-INFO2: %v", err)
|
|
||||||
}
|
|
||||||
if etypeID != eti[0].EType {
|
|
||||||
et, err = GetEtype(eti[0].EType)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error getting encryption type: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
salt = string(eti[0].Salt)
|
|
||||||
case patype.PA_ETYPE_INFO2:
|
|
||||||
if paID > pa.PADataType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var et2 types.ETypeInfo2
|
|
||||||
err := et2.Unmarshal(pa.PADataValue)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error unmashalling PA Data to PA-ETYPE-INFO2: %v", err)
|
|
||||||
}
|
|
||||||
if etypeID != et2[0].EType {
|
|
||||||
et, err = GetEtype(et2[0].EType)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error getting encryption type: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(et2[0].S2KParams) == 4 {
|
|
||||||
sk2p = hex.EncodeToString(et2[0].S2KParams)
|
|
||||||
}
|
|
||||||
salt = et2[0].Salt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if salt == "" {
|
|
||||||
salt = cname.GetSalt(realm)
|
|
||||||
}
|
|
||||||
k, err := et.StringToKey(passwd, salt, sk2p)
|
|
||||||
if err != nil {
|
|
||||||
return key, et, fmt.Errorf("error deriving key from string: %+v", err)
|
|
||||||
}
|
|
||||||
key = types.EncryptionKey{
|
|
||||||
KeyType: etypeID,
|
|
||||||
KeyValue: k,
|
|
||||||
}
|
|
||||||
return key, et, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEncryptedData encrypts the data provided and returns and EncryptedData type.
|
|
||||||
// Pass a usage value of zero to use the key provided directly rather than deriving one.
|
|
||||||
func GetEncryptedData(plainBytes []byte, key types.EncryptionKey, usage uint32, kvno int) (types.EncryptedData, error) {
|
|
||||||
var ed types.EncryptedData
|
|
||||||
et, err := GetEtype(key.KeyType)
|
|
||||||
if err != nil {
|
|
||||||
return ed, fmt.Errorf("error getting etype: %v", err)
|
|
||||||
}
|
|
||||||
_, b, err := et.EncryptMessage(key.KeyValue, plainBytes, usage)
|
|
||||||
if err != nil {
|
|
||||||
return ed, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ed = types.EncryptedData{
|
|
||||||
EType: key.KeyType,
|
|
||||||
Cipher: b,
|
|
||||||
KVNO: kvno,
|
|
||||||
}
|
|
||||||
return ed, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptEncPart decrypts the EncryptedData.
|
|
||||||
func DecryptEncPart(ed types.EncryptedData, key types.EncryptionKey, usage uint32) ([]byte, error) {
|
|
||||||
return DecryptMessage(ed.Cipher, key, usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the ciphertext and verifies the integrity.
|
|
||||||
func DecryptMessage(ciphertext []byte, key types.EncryptionKey, usage uint32) ([]byte, error) {
|
|
||||||
et, err := GetEtype(key.KeyType)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, fmt.Errorf("error decrypting: %v", err)
|
|
||||||
}
|
|
||||||
b, err := et.DecryptMessage(key.KeyValue, ciphertext, usage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decrypting: %v", err)
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
139
vendor/github.com/jcmturner/gokrb5/v8/crypto/des3-cbc-sha1-kd.go
generated
vendored
139
vendor/github.com/jcmturner/gokrb5/v8/crypto/des3-cbc-sha1-kd.go
generated
vendored
@ -1,139 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/des"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha1"
|
|
||||||
"errors"
|
|
||||||
"hash"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3961"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
)
|
|
||||||
|
|
||||||
//RFC: 3961 Section 6.3
|
|
||||||
|
|
||||||
// Des3CbcSha1Kd implements Kerberos encryption type des3-cbc-hmac-sha1-kd
|
|
||||||
type Des3CbcSha1Kd struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e Des3CbcSha1Kd) GetETypeID() int32 {
|
|
||||||
return etypeID.DES3_CBC_SHA1_KD
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e Des3CbcSha1Kd) GetHashID() int32 {
|
|
||||||
return chksumtype.HMAC_SHA1_DES3_KD
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e Des3CbcSha1Kd) GetKeyByteSize() int {
|
|
||||||
return 24
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e Des3CbcSha1Kd) GetKeySeedBitLength() int {
|
|
||||||
return 21 * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e Des3CbcSha1Kd) GetHashFunc() func() hash.Hash {
|
|
||||||
return sha1.New
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e Des3CbcSha1Kd) GetMessageBlockByteSize() int {
|
|
||||||
//For traditional CBC mode with padding, it would be the underlying cipher's block size
|
|
||||||
return des.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e Des3CbcSha1Kd) GetDefaultStringToKeyParams() string {
|
|
||||||
var s string
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e Des3CbcSha1Kd) GetConfounderByteSize() int {
|
|
||||||
return des.BlockSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e Des3CbcSha1Kd) GetHMACBitLength() int {
|
|
||||||
return e.GetHashFunc()().Size() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e Des3CbcSha1Kd) GetCypherBlockBitLength() int {
|
|
||||||
return des.BlockSize * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e Des3CbcSha1Kd) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
if s2kparams != "" {
|
|
||||||
return []byte{}, errors.New("s2kparams must be an empty string")
|
|
||||||
}
|
|
||||||
return rfc3961.DES3StringToKey(secret, salt, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e Des3CbcSha1Kd) RandomToKey(b []byte) []byte {
|
|
||||||
return rfc3961.DES3RandomToKey(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e Des3CbcSha1Kd) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
r, err := rfc3961.DeriveRandom(protocolKey, usage, e)
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e Des3CbcSha1Kd) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
r, err := e.DeriveRandom(protocolKey, usage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return e.RandomToKey(r), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e Des3CbcSha1Kd) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
return rfc3961.DES3EncryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e Des3CbcSha1Kd) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
return rfc3961.DES3EncryptMessage(key, message, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e Des3CbcSha1Kd) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DES3DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e Des3CbcSha1Kd) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc3961.DES3DecryptMessage(key, ciphertext, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the plaintext message.
|
|
||||||
func (e Des3CbcSha1Kd) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
return rfc3961.VerifyIntegrity(protocolKey, ct, pt, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e Des3CbcSha1Kd) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return common.GetHash(data, protocolKey, common.GetUsageKc(usage), e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e Des3CbcSha1Kd) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
c, err := e.GetChecksumHash(protocolKey, data, usage)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(chksum, c)
|
|
||||||
}
|
|
29
vendor/github.com/jcmturner/gokrb5/v8/crypto/etype/etype.go
generated
vendored
29
vendor/github.com/jcmturner/gokrb5/v8/crypto/etype/etype.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// Package etype provides the Kerberos Encryption Type interface
|
|
||||||
package etype
|
|
||||||
|
|
||||||
import "hash"
|
|
||||||
|
|
||||||
// EType is the interface defining the Encryption Type.
|
|
||||||
type EType interface {
|
|
||||||
GetETypeID() int32
|
|
||||||
GetHashID() int32
|
|
||||||
GetKeyByteSize() int
|
|
||||||
GetKeySeedBitLength() int
|
|
||||||
GetDefaultStringToKeyParams() string
|
|
||||||
StringToKey(string, salt, s2kparams string) ([]byte, error)
|
|
||||||
RandomToKey(b []byte) []byte
|
|
||||||
GetHMACBitLength() int
|
|
||||||
GetMessageBlockByteSize() int
|
|
||||||
EncryptData(key, data []byte) ([]byte, []byte, error)
|
|
||||||
EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error)
|
|
||||||
DecryptData(key, data []byte) ([]byte, error)
|
|
||||||
DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error)
|
|
||||||
GetCypherBlockBitLength() int
|
|
||||||
GetConfounderByteSize() int
|
|
||||||
DeriveKey(protocolKey, usage []byte) ([]byte, error)
|
|
||||||
DeriveRandom(protocolKey, usage []byte) ([]byte, error)
|
|
||||||
VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool
|
|
||||||
GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error)
|
|
||||||
VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool
|
|
||||||
GetHashFunc() func() hash.Hash
|
|
||||||
}
|
|
133
vendor/github.com/jcmturner/gokrb5/v8/crypto/rc4-hmac.go
generated
vendored
133
vendor/github.com/jcmturner/gokrb5/v8/crypto/rc4-hmac.go
generated
vendored
@ -1,133 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/md5"
|
|
||||||
"hash"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc3961"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/rfc4757"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/chksumtype"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
|
|
||||||
"golang.org/x/crypto/md4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RC4HMAC implements Kerberos encryption type rc4-hmac
|
|
||||||
type RC4HMAC struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetETypeID returns the EType ID number.
|
|
||||||
func (e RC4HMAC) GetETypeID() int32 {
|
|
||||||
return etypeID.RC4_HMAC
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashID returns the checksum type ID number.
|
|
||||||
func (e RC4HMAC) GetHashID() int32 {
|
|
||||||
return chksumtype.KERB_CHECKSUM_HMAC_MD5
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyByteSize returns the number of bytes for key of this etype.
|
|
||||||
func (e RC4HMAC) GetKeyByteSize() int {
|
|
||||||
return 16
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeySeedBitLength returns the number of bits for the seed for key generation.
|
|
||||||
func (e RC4HMAC) GetKeySeedBitLength() int {
|
|
||||||
return e.GetKeyByteSize() * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHashFunc returns the hash function for this etype.
|
|
||||||
func (e RC4HMAC) GetHashFunc() func() hash.Hash {
|
|
||||||
return md5.New
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMessageBlockByteSize returns the block size for the etype's messages.
|
|
||||||
func (e RC4HMAC) GetMessageBlockByteSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultStringToKeyParams returns the default key derivation parameters in string form.
|
|
||||||
func (e RC4HMAC) GetDefaultStringToKeyParams() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfounderByteSize returns the byte count for confounder to be used during cryptographic operations.
|
|
||||||
func (e RC4HMAC) GetConfounderByteSize() int {
|
|
||||||
return 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHMACBitLength returns the bit count size of the integrity hash.
|
|
||||||
func (e RC4HMAC) GetHMACBitLength() int {
|
|
||||||
return md5.Size * 8
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCypherBlockBitLength returns the bit count size of the cypher block.
|
|
||||||
func (e RC4HMAC) GetCypherBlockBitLength() int {
|
|
||||||
return 8 // doesn't really apply
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided.
|
|
||||||
func (e RC4HMAC) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
|
|
||||||
return rfc4757.StringToKey(secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided.
|
|
||||||
func (e RC4HMAC) RandomToKey(b []byte) []byte {
|
|
||||||
r := bytes.NewReader(b)
|
|
||||||
h := md4.New()
|
|
||||||
io.Copy(h, r)
|
|
||||||
return h.Sum(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided.
|
|
||||||
func (e RC4HMAC) EncryptData(key, data []byte) ([]byte, []byte, error) {
|
|
||||||
b, err := rfc4757.EncryptData(key, data, e)
|
|
||||||
return []byte{}, b, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided and concatenates it with the integrity hash to create an encrypted message.
|
|
||||||
func (e RC4HMAC) EncryptMessage(key, message []byte, usage uint32) ([]byte, []byte, error) {
|
|
||||||
b, err := rfc4757.EncryptMessage(key, message, usage, false, e)
|
|
||||||
return []byte{}, b, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided.
|
|
||||||
func (e RC4HMAC) DecryptData(key, data []byte) ([]byte, error) {
|
|
||||||
return rfc4757.DecryptData(key, data, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided and verifies the integrity of the message.
|
|
||||||
func (e RC4HMAC) DecryptMessage(key, ciphertext []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc4757.DecryptMessage(key, ciphertext, usage, false, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage value.
|
|
||||||
func (e RC4HMAC) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc4757.HMAC(protocolKey, usage), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveRandom generates data needed for key generation.
|
|
||||||
func (e RC4HMAC) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
|
|
||||||
return rfc3961.DeriveRandom(protocolKey, usage, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity checks the integrity of the plaintext message.
|
|
||||||
func (e RC4HMAC) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
|
|
||||||
return rfc4757.VerifyIntegrity(protocolKey, pt, ct, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChecksumHash returns a keyed checksum hash of the bytes provided.
|
|
||||||
func (e RC4HMAC) GetChecksumHash(protocolKey, data []byte, usage uint32) ([]byte, error) {
|
|
||||||
return rfc4757.Checksum(protocolKey, usage, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyChecksum compares the checksum of the message bytes is the same as the checksum provided.
|
|
||||||
func (e RC4HMAC) VerifyChecksum(protocolKey, data, chksum []byte, usage uint32) bool {
|
|
||||||
checksum, err := rfc4757.Checksum(protocolKey, usage, data)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hmac.Equal(checksum, chksum)
|
|
||||||
}
|
|
119
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/encryption.go
generated
vendored
119
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/encryption.go
generated
vendored
@ -1,119 +0,0 @@
|
|||||||
// Package rfc3961 provides encryption and checksum methods as specified in RFC 3961
|
|
||||||
package rfc3961
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/des"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DES3EncryptData encrypts the data provided using DES3 and methods specific to the etype provided.
|
|
||||||
func DES3EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) {
|
|
||||||
if len(key) != e.GetKeyByteSize() {
|
|
||||||
return nil, nil, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
|
||||||
}
|
|
||||||
data, _ = common.ZeroPad(data, e.GetMessageBlockByteSize())
|
|
||||||
|
|
||||||
block, err := des.NewTripleDESCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("error creating cipher: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//RFC 3961: initial cipher state All bits zero
|
|
||||||
ivz := make([]byte, des.BlockSize)
|
|
||||||
|
|
||||||
ct := make([]byte, len(data))
|
|
||||||
mode := cipher.NewCBCEncrypter(block, ivz)
|
|
||||||
mode.CryptBlocks(ct, data)
|
|
||||||
return ct[len(ct)-e.GetMessageBlockByteSize():], ct, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DES3EncryptMessage encrypts the message provided using DES3 and methods specific to the etype provided.
|
|
||||||
// The encrypted data is concatenated with its integrity hash to create an encrypted message.
|
|
||||||
func DES3EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) {
|
|
||||||
//confounder
|
|
||||||
c := make([]byte, e.GetConfounderByteSize())
|
|
||||||
_, err := rand.Read(c)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err)
|
|
||||||
}
|
|
||||||
plainBytes := append(c, message...)
|
|
||||||
plainBytes, _ = common.ZeroPad(plainBytes, e.GetMessageBlockByteSize())
|
|
||||||
|
|
||||||
// Derive key for encryption from usage
|
|
||||||
var k []byte
|
|
||||||
if usage != 0 {
|
|
||||||
k, err = e.DeriveKey(key, common.GetUsageKe(usage))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iv, b, err := e.EncryptData(k, plainBytes)
|
|
||||||
if err != nil {
|
|
||||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate and append integrity hash
|
|
||||||
ih, err := common.GetIntegrityHash(plainBytes, key, usage, e)
|
|
||||||
if err != nil {
|
|
||||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
|
||||||
}
|
|
||||||
b = append(b, ih...)
|
|
||||||
return iv, b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DES3DecryptData decrypts the data provided using DES3 and methods specific to the etype provided.
|
|
||||||
func DES3DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
|
|
||||||
if len(key) != e.GetKeyByteSize() {
|
|
||||||
return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(data) < des.BlockSize || len(data)%des.BlockSize != 0 {
|
|
||||||
return []byte{}, errors.New("ciphertext is not a multiple of the block size")
|
|
||||||
}
|
|
||||||
block, err := des.NewTripleDESCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, fmt.Errorf("error creating cipher: %v", err)
|
|
||||||
}
|
|
||||||
pt := make([]byte, len(data))
|
|
||||||
ivz := make([]byte, des.BlockSize)
|
|
||||||
mode := cipher.NewCBCDecrypter(block, ivz)
|
|
||||||
mode.CryptBlocks(pt, data)
|
|
||||||
return pt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DES3DecryptMessage decrypts the message provided using DES3 and methods specific to the etype provided.
|
|
||||||
// The integrity of the message is also verified.
|
|
||||||
func DES3DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) {
|
|
||||||
//Derive the key
|
|
||||||
k, err := e.DeriveKey(key, common.GetUsageKe(usage))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error deriving key: %v", err)
|
|
||||||
}
|
|
||||||
// Strip off the checksum from the end
|
|
||||||
b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decrypting: %v", err)
|
|
||||||
}
|
|
||||||
//Verify checksum
|
|
||||||
if !e.VerifyIntegrity(key, ciphertext, b, usage) {
|
|
||||||
return nil, errors.New("error decrypting: integrity verification failed")
|
|
||||||
}
|
|
||||||
//Remove the confounder bytes
|
|
||||||
return b[e.GetConfounderByteSize():], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIntegrity verifies the integrity of cipertext bytes ct.
|
|
||||||
func VerifyIntegrity(key, ct, pt []byte, usage uint32, etype etype.EType) bool {
|
|
||||||
h := make([]byte, etype.GetHMACBitLength()/8)
|
|
||||||
copy(h, ct[len(ct)-etype.GetHMACBitLength()/8:])
|
|
||||||
expectedMAC, _ := common.GetIntegrityHash(pt, key, usage, etype)
|
|
||||||
return hmac.Equal(h, expectedMAC)
|
|
||||||
}
|
|
169
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/keyDerivation.go
generated
vendored
169
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/keyDerivation.go
generated
vendored
@ -1,169 +0,0 @@
|
|||||||
package rfc3961
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
prfconstant = "prf"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeriveRandom implements the RFC 3961 defined function: DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state)).
|
|
||||||
//
|
|
||||||
// key: base key or protocol key. Likely to be a key from a keytab file.
|
|
||||||
//
|
|
||||||
// usage: a constant.
|
|
||||||
//
|
|
||||||
// n: block size in bits (not bytes) - note if you use something like aes.BlockSize this is in bytes.
|
|
||||||
//
|
|
||||||
// k: key length / key seed length in bits. Eg. for AES256 this value is 256.
|
|
||||||
//
|
|
||||||
// e: the encryption etype function to use.
|
|
||||||
func DeriveRandom(key, usage []byte, e etype.EType) ([]byte, error) {
|
|
||||||
n := e.GetCypherBlockBitLength()
|
|
||||||
k := e.GetKeySeedBitLength()
|
|
||||||
//Ensure the usage constant is at least the size of the cypher block size. Pass it through the nfold algorithm that will "stretch" it if needs be.
|
|
||||||
nFoldUsage := Nfold(usage, n)
|
|
||||||
//k-truncate implemented by creating a byte array the size of k (k is in bits hence /8)
|
|
||||||
out := make([]byte, k/8)
|
|
||||||
// Keep feeding the output back into the encryption function until it is no longer short than k.
|
|
||||||
_, K, err := e.EncryptData(key, nFoldUsage)
|
|
||||||
if err != nil {
|
|
||||||
return out, err
|
|
||||||
}
|
|
||||||
for i := copy(out, K); i < len(out); {
|
|
||||||
_, K, _ = e.EncryptData(key, K)
|
|
||||||
i = i + copy(out[i:], K)
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeriveKey derives a key from the protocol key based on the usage and the etype's specific methods.
|
|
||||||
func DeriveKey(protocolKey, usage []byte, e etype.EType) ([]byte, error) {
|
|
||||||
r, err := e.DeriveRandom(protocolKey, usage)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return e.RandomToKey(r), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomToKey returns a key from the bytes provided according to the definition in RFC 3961.
|
|
||||||
func RandomToKey(b []byte) []byte {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// DES3RandomToKey returns a key from the bytes provided according to the definition in RFC 3961 for DES3 etypes.
|
|
||||||
func DES3RandomToKey(b []byte) []byte {
|
|
||||||
r := fixWeakKey(stretch56Bits(b[:7]))
|
|
||||||
r2 := fixWeakKey(stretch56Bits(b[7:14]))
|
|
||||||
r = append(r, r2...)
|
|
||||||
r3 := fixWeakKey(stretch56Bits(b[14:21]))
|
|
||||||
r = append(r, r3...)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// DES3StringToKey returns a key derived from the string provided according to the definition in RFC 3961 for DES3 etypes.
|
|
||||||
func DES3StringToKey(secret, salt string, e etype.EType) ([]byte, error) {
|
|
||||||
s := secret + salt
|
|
||||||
tkey := e.RandomToKey(Nfold([]byte(s), e.GetKeySeedBitLength()))
|
|
||||||
return e.DeriveKey(tkey, []byte("kerberos"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PseudoRandom function as defined in RFC 3961
|
|
||||||
func PseudoRandom(key, b []byte, e etype.EType) ([]byte, error) {
|
|
||||||
h := e.GetHashFunc()()
|
|
||||||
h.Write(b)
|
|
||||||
tmp := h.Sum(nil)[:e.GetMessageBlockByteSize()]
|
|
||||||
k, err := e.DeriveKey(key, []byte(prfconstant))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
_, prf, err := e.EncryptData(k, tmp)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
return prf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func stretch56Bits(b []byte) []byte {
|
|
||||||
d := make([]byte, len(b), len(b))
|
|
||||||
copy(d, b)
|
|
||||||
var lb byte
|
|
||||||
for i, v := range d {
|
|
||||||
bv, nb := calcEvenParity(v)
|
|
||||||
d[i] = nb
|
|
||||||
if bv != 0 {
|
|
||||||
lb = lb | (1 << uint(i+1))
|
|
||||||
} else {
|
|
||||||
lb = lb &^ (1 << uint(i+1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, lb = calcEvenParity(lb)
|
|
||||||
d = append(d, lb)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func calcEvenParity(b byte) (uint8, uint8) {
|
|
||||||
lowestbit := b & 0x01
|
|
||||||
// c counter of 1s in the first 7 bits of the byte
|
|
||||||
var c int
|
|
||||||
// Iterate over the highest 7 bits (hence p starts at 1 not zero) and count the 1s.
|
|
||||||
for p := 1; p < 8; p++ {
|
|
||||||
v := b & (1 << uint(p))
|
|
||||||
if v != 0 {
|
|
||||||
c++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c%2 == 0 {
|
|
||||||
//Even number of 1s so set parity to 1
|
|
||||||
b = b | 1
|
|
||||||
} else {
|
|
||||||
//Odd number of 1s so set parity to 0
|
|
||||||
b = b &^ 1
|
|
||||||
}
|
|
||||||
return lowestbit, b
|
|
||||||
}
|
|
||||||
|
|
||||||
func fixWeakKey(b []byte) []byte {
|
|
||||||
if weak(b) {
|
|
||||||
b[7] ^= 0xF0
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func weak(b []byte) bool {
|
|
||||||
// weak keys from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-67r1.pdf
|
|
||||||
weakKeys := [4][]byte{
|
|
||||||
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
|
||||||
{0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE},
|
|
||||||
{0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1},
|
|
||||||
{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
|
|
||||||
}
|
|
||||||
semiWeakKeys := [12][]byte{
|
|
||||||
{0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E},
|
|
||||||
{0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01},
|
|
||||||
{0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1},
|
|
||||||
{0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01},
|
|
||||||
{0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE},
|
|
||||||
{0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01},
|
|
||||||
{0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1},
|
|
||||||
{0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E},
|
|
||||||
{0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE},
|
|
||||||
{0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E},
|
|
||||||
{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
|
|
||||||
{0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1},
|
|
||||||
}
|
|
||||||
for _, k := range weakKeys {
|
|
||||||
if bytes.Equal(b, k) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, k := range semiWeakKeys {
|
|
||||||
if bytes.Equal(b, k) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
107
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/nfold.go
generated
vendored
107
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3961/nfold.go
generated
vendored
@ -1,107 +0,0 @@
|
|||||||
package rfc3961
|
|
||||||
|
|
||||||
// Implementation of the n-fold algorithm as defined in RFC 3961.
|
|
||||||
|
|
||||||
/* Credits
|
|
||||||
This golang implementation of nfold used the following project for help with implementation detail.
|
|
||||||
Although their source is in java it was helpful as a reference implementation of the RFC.
|
|
||||||
You can find the source code of their open source project along with license information below.
|
|
||||||
We acknowledge and are grateful to these developers for their contributions to open source
|
|
||||||
|
|
||||||
Project: Apache Directory (http://http://directory.apache.org/)
|
|
||||||
https://svn.apache.org/repos/asf/directory/apacheds/tags/1.5.1/kerberos-shared/src/main/java/org/apache/directory/server/kerberos/shared/crypto/encryption/NFold.java
|
|
||||||
License: http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Nfold expands the key to ensure it is not smaller than one cipher block.
|
|
||||||
// Defined in RFC 3961.
|
|
||||||
//
|
|
||||||
// m input bytes that will be "stretched" to the least common multiple of n bits and the bit length of m.
|
|
||||||
func Nfold(m []byte, n int) []byte {
|
|
||||||
k := len(m) * 8
|
|
||||||
|
|
||||||
//Get the lowest common multiple of the two bit sizes
|
|
||||||
lcm := lcm(n, k)
|
|
||||||
relicate := lcm / k
|
|
||||||
var sumBytes []byte
|
|
||||||
|
|
||||||
for i := 0; i < relicate; i++ {
|
|
||||||
rotation := 13 * i
|
|
||||||
sumBytes = append(sumBytes, rotateRight(m, rotation)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
nfold := make([]byte, n/8)
|
|
||||||
sum := make([]byte, n/8)
|
|
||||||
for i := 0; i < lcm/n; i++ {
|
|
||||||
for j := 0; j < n/8; j++ {
|
|
||||||
sum[j] = sumBytes[j+(i*len(sum))]
|
|
||||||
}
|
|
||||||
nfold = onesComplementAddition(nfold, sum)
|
|
||||||
}
|
|
||||||
return nfold
|
|
||||||
}
|
|
||||||
|
|
||||||
func onesComplementAddition(n1, n2 []byte) []byte {
|
|
||||||
numBits := len(n1) * 8
|
|
||||||
out := make([]byte, numBits/8)
|
|
||||||
carry := 0
|
|
||||||
for i := numBits - 1; i > -1; i-- {
|
|
||||||
n1b := getBit(&n1, i)
|
|
||||||
n2b := getBit(&n2, i)
|
|
||||||
s := n1b + n2b + carry
|
|
||||||
|
|
||||||
if s == 0 || s == 1 {
|
|
||||||
setBit(&out, i, s)
|
|
||||||
carry = 0
|
|
||||||
} else if s == 2 {
|
|
||||||
carry = 1
|
|
||||||
} else if s == 3 {
|
|
||||||
setBit(&out, i, 1)
|
|
||||||
carry = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if carry == 1 {
|
|
||||||
carryArray := make([]byte, len(n1))
|
|
||||||
carryArray[len(carryArray)-1] = 1
|
|
||||||
out = onesComplementAddition(out, carryArray)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func rotateRight(b []byte, step int) []byte {
|
|
||||||
out := make([]byte, len(b))
|
|
||||||
bitLen := len(b) * 8
|
|
||||||
for i := 0; i < bitLen; i++ {
|
|
||||||
v := getBit(&b, i)
|
|
||||||
setBit(&out, (i+step)%bitLen, v)
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func lcm(x, y int) int {
|
|
||||||
return (x * y) / gcd(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func gcd(x, y int) int {
|
|
||||||
for y != 0 {
|
|
||||||
x, y = y, x%y
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBit(b *[]byte, p int) int {
|
|
||||||
pByte := p / 8
|
|
||||||
pBit := uint(p % 8)
|
|
||||||
vByte := (*b)[pByte]
|
|
||||||
vInt := int(vByte >> (8 - (pBit + 1)) & 0x0001)
|
|
||||||
return vInt
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBit(b *[]byte, p, v int) {
|
|
||||||
pByte := p / 8
|
|
||||||
pBit := uint(p % 8)
|
|
||||||
oldByte := (*b)[pByte]
|
|
||||||
var newByte byte
|
|
||||||
newByte = byte(v<<(8-(pBit+1))) | oldByte
|
|
||||||
(*b)[pByte] = newByte
|
|
||||||
}
|
|
89
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3962/encryption.go
generated
vendored
89
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3962/encryption.go
generated
vendored
@ -1,89 +0,0 @@
|
|||||||
// Package rfc3962 provides encryption and checksum methods as specified in RFC 3962
|
|
||||||
package rfc3962
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jcmturner/aescts/v2"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/common"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 3962.
|
|
||||||
func EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) {
|
|
||||||
if len(key) != e.GetKeyByteSize() {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
|
||||||
}
|
|
||||||
ivz := make([]byte, e.GetCypherBlockBitLength()/8)
|
|
||||||
return aescts.Encrypt(key, ivz, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 3962.
|
|
||||||
// The encrypted data is concatenated with its integrity hash to create an encrypted message.
|
|
||||||
func EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) {
|
|
||||||
if len(key) != e.GetKeyByteSize() {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
|
||||||
}
|
|
||||||
//confounder
|
|
||||||
c := make([]byte, e.GetConfounderByteSize())
|
|
||||||
_, err := rand.Read(c)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err)
|
|
||||||
}
|
|
||||||
plainBytes := append(c, message...)
|
|
||||||
|
|
||||||
// Derive key for encryption from usage
|
|
||||||
var k []byte
|
|
||||||
if usage != 0 {
|
|
||||||
k, err = e.DeriveKey(key, common.GetUsageKe(usage))
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt the data
|
|
||||||
iv, b, err := e.EncryptData(k, plainBytes)
|
|
||||||
if err != nil {
|
|
||||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate and append integrity hash
|
|
||||||
ih, err := common.GetIntegrityHash(plainBytes, key, usage, e)
|
|
||||||
if err != nil {
|
|
||||||
return iv, b, fmt.Errorf("error encrypting data: %v", err)
|
|
||||||
}
|
|
||||||
b = append(b, ih...)
|
|
||||||
return iv, b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 3962.
|
|
||||||
func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
|
|
||||||
if len(key) != e.GetKeyByteSize() {
|
|
||||||
return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
|
|
||||||
}
|
|
||||||
ivz := make([]byte, e.GetCypherBlockBitLength()/8)
|
|
||||||
return aescts.Decrypt(key, ivz, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 3962.
|
|
||||||
// The integrity of the message is also verified.
|
|
||||||
func DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) {
|
|
||||||
//Derive the key
|
|
||||||
k, err := e.DeriveKey(key, common.GetUsageKe(usage))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error deriving key: %v", err)
|
|
||||||
}
|
|
||||||
// Strip off the checksum from the end
|
|
||||||
b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
//Verify checksum
|
|
||||||
if !e.VerifyIntegrity(key, ciphertext, b, usage) {
|
|
||||||
return nil, errors.New("integrity verification failed")
|
|
||||||
}
|
|
||||||
//Remove the confounder bytes
|
|
||||||
return b[e.GetConfounderByteSize():], nil
|
|
||||||
}
|
|
51
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3962/keyDerivation.go
generated
vendored
51
vendor/github.com/jcmturner/gokrb5/v8/crypto/rfc3962/keyDerivation.go
generated
vendored
@ -1,51 +0,0 @@
|
|||||||
package rfc3962
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/jcmturner/gofork/x/crypto/pbkdf2"
|
|
||||||
"github.com/jcmturner/gokrb5/v8/crypto/etype"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
s2kParamsZero = 4294967296
|
|
||||||
)
|
|
||||||
|
|
||||||
// StringToKey returns a key derived from the string provided according to the definition in RFC 3961.
|
|
||||||
func StringToKey(secret, salt, s2kparams string, e etype.EType) ([]byte, error) {
|
|
||||||
i, err := S2KparamsToItertions(s2kparams)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return StringToKeyIter(secret, salt, i, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToPBKDF2 generates an encryption key from a pass phrase and salt string using the PBKDF2 function from PKCS #5 v2.0
|
|
||||||
func StringToPBKDF2(secret, salt string, iterations int64, e etype.EType) []byte {
|
|
||||||
return pbkdf2.Key64([]byte(secret), []byte(salt), iterations, int64(e.GetKeyByteSize()), e.GetHashFunc())
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringToKeyIter returns a key derived from the string provided according to the definition in RFC 3961.
|
|
||||||
func StringToKeyIter(secret, salt string, iterations int64, e etype.EType) ([]byte, error) {
|
|
||||||
tkey := e.RandomToKey(StringToPBKDF2(secret, salt, iterations, e))
|
|
||||||
return e.DeriveKey(tkey, []byte("kerberos"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// S2KparamsToItertions converts the string representation of iterations to an integer
|
|
||||||
func S2KparamsToItertions(s2kparams string) (int64, error) {
|
|
||||||
//The s2kparams string should be hex string representing 4 bytes
|
|
||||||
//The 4 bytes represent a number in big endian order
|
|
||||||
//If the value is zero then the number of iterations should be 4,294,967,296 (2^32)
|
|
||||||
var i uint32
|
|
||||||
if len(s2kparams) != 8 {
|
|
||||||
return int64(s2kParamsZero), errors.New("invalid s2kparams length")
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(s2kparams)
|
|
||||||
if err != nil {
|
|
||||||
return int64(s2kParamsZero), errors.New("invalid s2kparams, cannot decode string to bytes")
|
|
||||||
}
|
|
||||||
i = binary.BigEndian.Uint32(b)
|
|
||||||
return int64(i), nil
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user