mirror of
https://github.com/documize/community.git
synced 2025-07-19 05:09:42 +02:00
Prep 5.11.3
This commit is contained in:
parent
69940cb7f1
commit
f2ba294be8
47 changed files with 169 additions and 3090 deletions
|
@ -41,8 +41,8 @@ func main() {
|
||||||
rt.Product = domain.Product{}
|
rt.Product = domain.Product{}
|
||||||
rt.Product.Major = "5"
|
rt.Product.Major = "5"
|
||||||
rt.Product.Minor = "11"
|
rt.Product.Minor = "11"
|
||||||
rt.Product.Patch = "2"
|
rt.Product.Patch = "3"
|
||||||
rt.Product.Revision = "1705427184"
|
rt.Product.Revision = "1708098744"
|
||||||
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
||||||
rt.Product.Edition = domain.CommunityEdition
|
rt.Product.Edition = domain.CommunityEdition
|
||||||
rt.Product.Title = "Community"
|
rt.Product.Title = "Community"
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -11,7 +11,7 @@ require (
|
||||||
github.com/documize/glick v0.0.0-20160503134043-a8ccbef88237
|
github.com/documize/glick v0.0.0-20160503134043-a8ccbef88237
|
||||||
github.com/documize/html-diff v0.0.0-20160503140253-f61c192c7796
|
github.com/documize/html-diff v0.0.0-20160503140253-f61c192c7796
|
||||||
github.com/documize/slug v1.1.1
|
github.com/documize/slug v1.1.1
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.1
|
||||||
github.com/go-sql-driver/mysql v1.7.1
|
github.com/go-sql-driver/mysql v1.7.1
|
||||||
github.com/golang/glog v1.2.0 // indirect
|
github.com/golang/glog v1.2.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
|
@ -36,7 +36,7 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||||
|
@ -44,7 +44,6 @@ require (
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/google/uuid v1.3.1 // indirect
|
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/trivago/tgo v1.0.7 // indirect
|
github.com/trivago/tgo v1.0.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
20
go.sum
20
go.sum
|
@ -1,13 +1,11 @@
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
|
||||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
|
||||||
github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ=
|
github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ=
|
||||||
github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU=
|
github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU=
|
||||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
|
@ -34,10 +32,11 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
@ -59,8 +58,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
|
||||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||||
|
@ -127,15 +124,16 @@ github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM=
|
||||||
github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
|
github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
|
||||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
@ -150,6 +148,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -159,21 +158,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "documize",
|
"name": "documize",
|
||||||
"version": "5.11.2",
|
"version": "5.11.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Documize Community",
|
"description": "Documize Community",
|
||||||
"repository": "",
|
"repository": "",
|
||||||
|
|
41
vendor/github.com/Azure/go-ntlmssp/SECURITY.md
generated
vendored
41
vendor/github.com/Azure/go-ntlmssp/SECURITY.md
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->
|
|
||||||
|
|
||||||
## Security
|
|
||||||
|
|
||||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
|
||||||
|
|
||||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
|
||||||
|
|
||||||
## Reporting Security Issues
|
|
||||||
|
|
||||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
|
||||||
|
|
||||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
|
||||||
|
|
||||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
|
||||||
|
|
||||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
|
||||||
|
|
||||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
|
||||||
|
|
||||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
|
||||||
* Full paths of source file(s) related to the manifestation of the issue
|
|
||||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
|
||||||
* Any special configuration required to reproduce the issue
|
|
||||||
* Step-by-step instructions to reproduce the issue
|
|
||||||
* Proof-of-concept or exploit code (if possible)
|
|
||||||
* Impact of the issue, including how an attacker might exploit the issue
|
|
||||||
|
|
||||||
This information will help us triage your report more quickly.
|
|
||||||
|
|
||||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
|
||||||
|
|
||||||
## Preferred Languages
|
|
||||||
|
|
||||||
We prefer all communications to be in English.
|
|
||||||
|
|
||||||
## Policy
|
|
||||||
|
|
||||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
|
||||||
|
|
||||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
|
8
vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
generated
vendored
8
vendor/github.com/Azure/go-ntlmssp/authenticate_message.go
generated
vendored
|
@ -42,7 +42,7 @@ func (m authenicateMessage) MarshalBinary() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
target, user := toUnicode(m.TargetName), toUnicode(m.UserName)
|
target, user := toUnicode(m.TargetName), toUnicode(m.UserName)
|
||||||
workstation := toUnicode("")
|
workstation := toUnicode("go-ntlmssp")
|
||||||
|
|
||||||
ptr := binary.Size(&authenticateMessageFields{})
|
ptr := binary.Size(&authenticateMessageFields{})
|
||||||
f := authenticateMessageFields{
|
f := authenticateMessageFields{
|
||||||
|
@ -82,7 +82,7 @@ func (m authenicateMessage) MarshalBinary() ([]byte, error) {
|
||||||
|
|
||||||
//ProcessChallenge crafts an AUTHENTICATE message in response to the CHALLENGE message
|
//ProcessChallenge crafts an AUTHENTICATE message in response to the CHALLENGE message
|
||||||
//that was received from the server
|
//that was received from the server
|
||||||
func ProcessChallenge(challengeMessageData []byte, user, password string, domainNeeded bool) ([]byte, error) {
|
func ProcessChallenge(challengeMessageData []byte, user, password string) ([]byte, error) {
|
||||||
if user == "" && password == "" {
|
if user == "" && password == "" {
|
||||||
return nil, errors.New("Anonymous authentication not supported")
|
return nil, errors.New("Anonymous authentication not supported")
|
||||||
}
|
}
|
||||||
|
@ -99,10 +99,6 @@ func ProcessChallenge(challengeMessageData []byte, user, password string, domain
|
||||||
return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
|
return nil, errors.New("Key exchange requested but not supported (NTLMSSP_NEGOTIATE_KEY_EXCH)")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !domainNeeded {
|
|
||||||
cm.TargetName = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
am := authenicateMessage{
|
am := authenicateMessage{
|
||||||
UserName: user,
|
UserName: user,
|
||||||
TargetName: cm.TargetName,
|
TargetName: cm.TargetName,
|
||||||
|
|
45
vendor/github.com/Azure/go-ntlmssp/authheader.go
generated
vendored
45
vendor/github.com/Azure/go-ntlmssp/authheader.go
generated
vendored
|
@ -5,55 +5,26 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type authheader []string
|
type authheader string
|
||||||
|
|
||||||
func (h authheader) IsBasic() bool {
|
func (h authheader) IsBasic() bool {
|
||||||
for _, s := range h {
|
return strings.HasPrefix(string(h), "Basic ")
|
||||||
if strings.HasPrefix(string(s), "Basic ") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h authheader) Basic() string {
|
|
||||||
for _, s := range h {
|
|
||||||
if strings.HasPrefix(string(s), "Basic ") {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authheader) IsNegotiate() bool {
|
func (h authheader) IsNegotiate() bool {
|
||||||
for _, s := range h {
|
return strings.HasPrefix(string(h), "Negotiate")
|
||||||
if strings.HasPrefix(string(s), "Negotiate") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authheader) IsNTLM() bool {
|
func (h authheader) IsNTLM() bool {
|
||||||
for _, s := range h {
|
return strings.HasPrefix(string(h), "NTLM")
|
||||||
if strings.HasPrefix(string(s), "NTLM") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authheader) GetData() ([]byte, error) {
|
func (h authheader) GetData() ([]byte, error) {
|
||||||
for _, s := range h {
|
p := strings.Split(string(h), " ")
|
||||||
if strings.HasPrefix(string(s), "NTLM") || strings.HasPrefix(string(s), "Negotiate") || strings.HasPrefix(string(s), "Basic ") {
|
if len(p) < 2 {
|
||||||
p := strings.Split(string(s), " ")
|
return nil, nil
|
||||||
if len(p) < 2 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return base64.StdEncoding.DecodeString(string(p[1]))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
return base64.StdEncoding.DecodeString(string(p[1]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authheader) GetBasicCreds() (username, password string, err error) {
|
func (h authheader) GetBasicCreds() (username, password string, err error) {
|
||||||
|
|
27
vendor/github.com/Azure/go-ntlmssp/negotiator.go
generated
vendored
27
vendor/github.com/Azure/go-ntlmssp/negotiator.go
generated
vendored
|
@ -10,22 +10,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetDomain : parse domain name from based on slashes in the input
|
// GetDomain : parse domain name from based on slashes in the input
|
||||||
// Need to check for upn as well
|
func GetDomain(user string) (string, string) {
|
||||||
func GetDomain(user string) (string, string, bool) {
|
|
||||||
domain := ""
|
domain := ""
|
||||||
domainNeeded := false
|
|
||||||
|
|
||||||
if strings.Contains(user, "\\") {
|
if strings.Contains(user, "\\") {
|
||||||
ucomponents := strings.SplitN(user, "\\", 2)
|
ucomponents := strings.SplitN(user, "\\", 2)
|
||||||
domain = ucomponents[0]
|
domain = ucomponents[0]
|
||||||
user = ucomponents[1]
|
user = ucomponents[1]
|
||||||
domainNeeded = true
|
|
||||||
} else if strings.Contains(user, "@") {
|
|
||||||
domainNeeded = false
|
|
||||||
} else {
|
|
||||||
domainNeeded = true
|
|
||||||
}
|
}
|
||||||
return user, domain, domainNeeded
|
return user, domain
|
||||||
}
|
}
|
||||||
|
|
||||||
//Negotiator is a http.Roundtripper decorator that automatically
|
//Negotiator is a http.Roundtripper decorator that automatically
|
||||||
|
@ -41,11 +34,10 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
rt = http.DefaultTransport
|
rt = http.DefaultTransport
|
||||||
}
|
}
|
||||||
// If it is not basic auth, just round trip the request as usual
|
// If it is not basic auth, just round trip the request as usual
|
||||||
reqauth := authheader(req.Header.Values("Authorization"))
|
reqauth := authheader(req.Header.Get("Authorization"))
|
||||||
if !reqauth.IsBasic() {
|
if !reqauth.IsBasic() {
|
||||||
return rt.RoundTrip(req)
|
return rt.RoundTrip(req)
|
||||||
}
|
}
|
||||||
reqauthBasic := reqauth.Basic()
|
|
||||||
// Save request body
|
// Save request body
|
||||||
body := bytes.Buffer{}
|
body := bytes.Buffer{}
|
||||||
if req.Body != nil {
|
if req.Body != nil {
|
||||||
|
@ -67,10 +59,11 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
if res.StatusCode != http.StatusUnauthorized {
|
if res.StatusCode != http.StatusUnauthorized {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
resauth := authheader(res.Header.Values("Www-Authenticate"))
|
|
||||||
|
resauth := authheader(res.Header.Get("Www-Authenticate"))
|
||||||
if !resauth.IsNegotiate() && !resauth.IsNTLM() {
|
if !resauth.IsNegotiate() && !resauth.IsNTLM() {
|
||||||
// Unauthorized, Negotiate not requested, let's try with basic auth
|
// Unauthorized, Negotiate not requested, let's try with basic auth
|
||||||
req.Header.Set("Authorization", string(reqauthBasic))
|
req.Header.Set("Authorization", string(reqauth))
|
||||||
io.Copy(ioutil.Discard, res.Body)
|
io.Copy(ioutil.Discard, res.Body)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||||
|
@ -82,7 +75,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
if res.StatusCode != http.StatusUnauthorized {
|
if res.StatusCode != http.StatusUnauthorized {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
resauth = authheader(res.Header.Values("Www-Authenticate"))
|
resauth = authheader(res.Header.Get("Www-Authenticate"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if resauth.IsNegotiate() || resauth.IsNTLM() {
|
if resauth.IsNegotiate() || resauth.IsNTLM() {
|
||||||
|
@ -98,7 +91,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
|
|
||||||
// get domain from username
|
// get domain from username
|
||||||
domain := ""
|
domain := ""
|
||||||
u, domain, domainNeeded := GetDomain(u)
|
u, domain = GetDomain(u)
|
||||||
|
|
||||||
// send negotiate
|
// send negotiate
|
||||||
negotiateMessage, err := NewNegotiateMessage(domain, "")
|
negotiateMessage, err := NewNegotiateMessage(domain, "")
|
||||||
|
@ -119,7 +112,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive challenge?
|
// receive challenge?
|
||||||
resauth = authheader(res.Header.Values("Www-Authenticate"))
|
resauth = authheader(res.Header.Get("Www-Authenticate"))
|
||||||
challengeMessage, err := resauth.GetData()
|
challengeMessage, err := resauth.GetData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -132,7 +125,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
|
|
||||||
// send authenticate
|
// send authenticate
|
||||||
authenticateMessage, err := ProcessChallenge(challengeMessage, u, p, domainNeeded)
|
authenticateMessage, err := ProcessChallenge(challengeMessage, u, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
6
vendor/github.com/go-ldap/ldap/v3/add.go
generated
vendored
6
vendor/github.com/go-ldap/ldap/v3/add.go
generated
vendored
|
@ -1,7 +1,8 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"log"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ func NewAddRequest(dn string, controls []Control) *AddRequest {
|
||||||
DN: dn,
|
DN: dn,
|
||||||
Controls: controls,
|
Controls: controls,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add performs the given AddRequest
|
// Add performs the given AddRequest
|
||||||
|
@ -83,7 +85,7 @@ func (l *Conn) Add(addRequest *AddRequest) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("ldap: unexpected response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
209
vendor/github.com/go-ldap/ldap/v3/bind.go
generated
vendored
209
vendor/github.com/go-ldap/ldap/v3/bind.go
generated
vendored
|
@ -261,7 +261,7 @@ func parseParams(str string) (map[string]string, error) {
|
||||||
var state int
|
var state int
|
||||||
for i := 0; i <= len(str); i++ {
|
for i := 0; i <= len(str); i++ {
|
||||||
switch state {
|
switch state {
|
||||||
case 0: // reading key
|
case 0: //reading key
|
||||||
if i == len(str) {
|
if i == len(str) {
|
||||||
return nil, fmt.Errorf("syntax error on %d", i)
|
return nil, fmt.Errorf("syntax error on %d", i)
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ func parseParams(str string) (map[string]string, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
state = 1
|
state = 1
|
||||||
case 1: // reading value
|
case 1: //reading value
|
||||||
if i == len(str) {
|
if i == len(str) {
|
||||||
m[key] = value
|
m[key] = value
|
||||||
break
|
break
|
||||||
|
@ -289,7 +289,7 @@ func parseParams(str string) (map[string]string, error) {
|
||||||
default:
|
default:
|
||||||
value += string(str[i])
|
value += string(str[i])
|
||||||
}
|
}
|
||||||
case 2: // inside quotes
|
case 2: //inside quotes
|
||||||
if i == len(str) {
|
if i == len(str) {
|
||||||
return nil, fmt.Errorf("syntax error on %d", i)
|
return nil, fmt.Errorf("syntax error on %d", i)
|
||||||
}
|
}
|
||||||
|
@ -399,9 +399,6 @@ type NTLMBindRequest struct {
|
||||||
Username string
|
Username string
|
||||||
// Password is the credentials to bind with
|
// Password is the credentials to bind with
|
||||||
Password string
|
Password string
|
||||||
// AllowEmptyPassword sets whether the client allows binding with an empty password
|
|
||||||
// (normally used for unauthenticated bind).
|
|
||||||
AllowEmptyPassword bool
|
|
||||||
// Hash is the hex NTLM hash to bind with. Password or hash must be provided
|
// Hash is the hex NTLM hash to bind with. Password or hash must be provided
|
||||||
Hash string
|
Hash string
|
||||||
// Controls are optional controls to send with the bind request
|
// Controls are optional controls to send with the bind request
|
||||||
|
@ -445,22 +442,6 @@ func (l *Conn) NTLMBind(domain, username, password string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NTLMUnauthenticatedBind performs an bind with an empty password.
|
|
||||||
//
|
|
||||||
// A username is required. The anonymous bind is not (yet) supported by the go-ntlmssp library (https://github.com/Azure/go-ntlmssp/blob/819c794454d067543bc61d29f61fef4b3c3df62c/authenticate_message.go#L87)
|
|
||||||
//
|
|
||||||
// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b38c36ed-2804-4868-a9ff-8dd3182128e4 part 3.2.5.1.2
|
|
||||||
func (l *Conn) NTLMUnauthenticatedBind(domain, username string) error {
|
|
||||||
req := &NTLMBindRequest{
|
|
||||||
Domain: domain,
|
|
||||||
Username: username,
|
|
||||||
Password: "",
|
|
||||||
AllowEmptyPassword: true,
|
|
||||||
}
|
|
||||||
_, err := l.NTLMChallengeBind(req)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NTLMBindWithHash performs an NTLM Bind with an NTLM hash instead of plaintext password (pass-the-hash)
|
// NTLMBindWithHash performs an NTLM Bind with an NTLM hash instead of plaintext password (pass-the-hash)
|
||||||
func (l *Conn) NTLMBindWithHash(domain, username, hash string) error {
|
func (l *Conn) NTLMBindWithHash(domain, username, hash string) error {
|
||||||
req := &NTLMBindRequest{
|
req := &NTLMBindRequest{
|
||||||
|
@ -474,7 +455,7 @@ func (l *Conn) NTLMBindWithHash(domain, username, hash string) error {
|
||||||
|
|
||||||
// NTLMChallengeBind performs the NTLMSSP bind operation defined in the given request
|
// NTLMChallengeBind performs the NTLMSSP bind operation defined in the given request
|
||||||
func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindResult, error) {
|
func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindResult, error) {
|
||||||
if !ntlmBindRequest.AllowEmptyPassword && ntlmBindRequest.Password == "" && ntlmBindRequest.Hash == "" {
|
if ntlmBindRequest.Password == "" && ntlmBindRequest.Hash == "" {
|
||||||
return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
|
return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,11 +496,10 @@ func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindRes
|
||||||
var err error
|
var err error
|
||||||
var responseMessage []byte
|
var responseMessage []byte
|
||||||
// generate a response message to the challenge with the given Username/Password if password is provided
|
// generate a response message to the challenge with the given Username/Password if password is provided
|
||||||
if ntlmBindRequest.Hash != "" {
|
if ntlmBindRequest.Password != "" {
|
||||||
|
responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password)
|
||||||
|
} else if ntlmBindRequest.Hash != "" {
|
||||||
responseMessage, err = ntlmssp.ProcessChallengeWithHash(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash)
|
responseMessage, err = ntlmssp.ProcessChallengeWithHash(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Hash)
|
||||||
} else if ntlmBindRequest.Password != "" || ntlmBindRequest.AllowEmptyPassword {
|
|
||||||
_, _, domainNeeded := ntlmssp.GetDomain(ntlmBindRequest.Username)
|
|
||||||
responseMessage, err = ntlmssp.ProcessChallenge(ntlmsspChallenge, ntlmBindRequest.Username, ntlmBindRequest.Password, domainNeeded)
|
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("need a password or hash to generate reply")
|
err = fmt.Errorf("need a password or hash to generate reply")
|
||||||
}
|
}
|
||||||
|
@ -558,178 +538,3 @@ func (l *Conn) NTLMChallengeBind(ntlmBindRequest *NTLMBindRequest) (*NTLMBindRes
|
||||||
err = GetLDAPError(packet)
|
err = GetLDAPError(packet)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GSSAPIClient interface is used as the client-side implementation for the
|
|
||||||
// GSSAPI SASL mechanism.
|
|
||||||
// Interface inspired by GSSAPIClient from golang.org/x/crypto/ssh
|
|
||||||
type GSSAPIClient interface {
|
|
||||||
// InitSecContext initiates the establishment of a security context for
|
|
||||||
// GSS-API between the client and server.
|
|
||||||
// Initially the token parameter should be specified as nil.
|
|
||||||
// The routine may return a outputToken which should be transferred to
|
|
||||||
// the server, where the server will present it to AcceptSecContext.
|
|
||||||
// If no token need be sent, InitSecContext will indicate this by setting
|
|
||||||
// needContinue to false. To complete the context
|
|
||||||
// establishment, one or more reply tokens may be required from the server;
|
|
||||||
// if so, InitSecContext will return a needContinue which is true.
|
|
||||||
// In this case, InitSecContext should be called again when the
|
|
||||||
// reply token is received from the server, passing the reply token
|
|
||||||
// to InitSecContext via the token parameters.
|
|
||||||
// See RFC 4752 section 3.1.
|
|
||||||
InitSecContext(target string, token []byte) (outputToken []byte, needContinue bool, err error)
|
|
||||||
// NegotiateSaslAuth performs the last step of the Sasl handshake.
|
|
||||||
// It takes a token, which, when unwrapped, describes the servers supported
|
|
||||||
// security layers (first octet) and maximum receive buffer (remaining
|
|
||||||
// three octets).
|
|
||||||
// If the received token is unacceptable an error must be returned to abort
|
|
||||||
// the handshake.
|
|
||||||
// Outputs a signed token describing the client's selected security layer
|
|
||||||
// and receive buffer size and optionally an authorization identity.
|
|
||||||
// The returned token will be sent to the server and the handshake considered
|
|
||||||
// completed successfully and the server authenticated.
|
|
||||||
// See RFC 4752 section 3.1.
|
|
||||||
NegotiateSaslAuth(token []byte, authzid string) ([]byte, error)
|
|
||||||
// DeleteSecContext destroys any established secure context.
|
|
||||||
DeleteSecContext() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// GSSAPIBindRequest represents a GSSAPI SASL mechanism bind request.
|
|
||||||
// See rfc4752 and rfc4513 section 5.2.1.2.
|
|
||||||
type GSSAPIBindRequest struct {
|
|
||||||
// Service Principal Name user for the service ticket. Eg. "ldap/<host>"
|
|
||||||
ServicePrincipalName string
|
|
||||||
// (Optional) Authorization entity
|
|
||||||
AuthZID string
|
|
||||||
// (Optional) Controls to send with the bind request
|
|
||||||
Controls []Control
|
|
||||||
}
|
|
||||||
|
|
||||||
// GSSAPIBind performs the GSSAPI SASL bind using the provided GSSAPI client.
|
|
||||||
func (l *Conn) GSSAPIBind(client GSSAPIClient, servicePrincipal, authzid string) error {
|
|
||||||
return l.GSSAPIBindRequest(client, &GSSAPIBindRequest{
|
|
||||||
ServicePrincipalName: servicePrincipal,
|
|
||||||
AuthZID: authzid,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// GSSAPIBindRequest performs the GSSAPI SASL bind using the provided GSSAPI client.
|
|
||||||
func (l *Conn) GSSAPIBindRequest(client GSSAPIClient, req *GSSAPIBindRequest) error {
|
|
||||||
//nolint:errcheck
|
|
||||||
defer client.DeleteSecContext()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
var reqToken []byte
|
|
||||||
var recvToken []byte
|
|
||||||
needInit := true
|
|
||||||
for {
|
|
||||||
if needInit {
|
|
||||||
// Establish secure context between client and server.
|
|
||||||
reqToken, needInit, err = client.InitSecContext(req.ServicePrincipalName, recvToken)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Secure context is set up, perform the last step of SASL handshake.
|
|
||||||
reqToken, err = client.NegotiateSaslAuth(recvToken, req.AuthZID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send Bind request containing the current token and extract the
|
|
||||||
// token sent by server.
|
|
||||||
recvToken, err = l.saslBindTokenExchange(req.Controls, reqToken)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !needInit && len(recvToken) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Conn) saslBindTokenExchange(reqControls []Control, reqToken []byte) ([]byte, error) {
|
|
||||||
// Construct LDAP Bind request with GSSAPI SASL mechanism.
|
|
||||||
envelope := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
|
||||||
envelope.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
|
||||||
|
|
||||||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
|
|
||||||
request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
|
|
||||||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "User Name"))
|
|
||||||
|
|
||||||
auth := ber.Encode(ber.ClassContext, ber.TypeConstructed, 3, "", "authentication")
|
|
||||||
auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "GSSAPI", "SASL Mech"))
|
|
||||||
if len(reqToken) > 0 {
|
|
||||||
auth.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(reqToken), "Credentials"))
|
|
||||||
}
|
|
||||||
request.AppendChild(auth)
|
|
||||||
envelope.AppendChild(request)
|
|
||||||
if len(reqControls) > 0 {
|
|
||||||
envelope.AppendChild(encodeControls(reqControls))
|
|
||||||
}
|
|
||||||
|
|
||||||
msgCtx, err := l.sendMessage(envelope)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer l.finishMessage(msgCtx)
|
|
||||||
|
|
||||||
packet, err := l.readPacket(msgCtx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
|
|
||||||
if l.Debug {
|
|
||||||
if err = addLDAPDescriptions(packet); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ber.PrintPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://www.rfc-editor.org/rfc/rfc4511#section-4.1.1
|
|
||||||
// packet is an envelope
|
|
||||||
// child 0 is message id
|
|
||||||
// child 1 is protocolOp
|
|
||||||
if len(packet.Children) != 2 {
|
|
||||||
return nil, fmt.Errorf("bad bind response")
|
|
||||||
}
|
|
||||||
|
|
||||||
protocolOp := packet.Children[1]
|
|
||||||
RESP:
|
|
||||||
switch protocolOp.Description {
|
|
||||||
case "Bind Response": // Bind Response
|
|
||||||
// Bind Reponse is an LDAP Response (https://www.rfc-editor.org/rfc/rfc4511#section-4.1.9)
|
|
||||||
// with an additional optional serverSaslCreds string (https://www.rfc-editor.org/rfc/rfc4511#section-4.2.2)
|
|
||||||
// child 0 is resultCode
|
|
||||||
resultCode := protocolOp.Children[0]
|
|
||||||
if resultCode.Tag != ber.TagEnumerated {
|
|
||||||
break RESP
|
|
||||||
}
|
|
||||||
switch resultCode.Value.(int64) {
|
|
||||||
case 14: // Sasl bind in progress
|
|
||||||
if len(protocolOp.Children) < 3 {
|
|
||||||
break RESP
|
|
||||||
}
|
|
||||||
referral := protocolOp.Children[3]
|
|
||||||
switch referral.Description {
|
|
||||||
case "Referral":
|
|
||||||
if referral.ClassType != ber.ClassContext || referral.Tag != ber.TagObjectDescriptor {
|
|
||||||
break RESP
|
|
||||||
}
|
|
||||||
return ioutil.ReadAll(referral.Data)
|
|
||||||
}
|
|
||||||
// Optional:
|
|
||||||
//if len(protocolOp.Children) == 4 {
|
|
||||||
// serverSaslCreds := protocolOp.Children[4]
|
|
||||||
//}
|
|
||||||
case 0: // Success - Bind OK.
|
|
||||||
// SASL layer in effect (if any) (See https://www.rfc-editor.org/rfc/rfc4513#section-5.2.1.4)
|
|
||||||
// NOTE: SASL security layers are not supported currently.
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, GetLDAPError(packet)
|
|
||||||
}
|
|
||||||
|
|
11
vendor/github.com/go-ldap/ldap/v3/client.go
generated
vendored
11
vendor/github.com/go-ldap/ldap/v3/client.go
generated
vendored
|
@ -1,7 +1,6 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -10,18 +9,14 @@ import (
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Start()
|
Start()
|
||||||
StartTLS(*tls.Config) error
|
StartTLS(*tls.Config) error
|
||||||
Close() error
|
Close()
|
||||||
GetLastError() error
|
|
||||||
IsClosing() bool
|
IsClosing() bool
|
||||||
SetTimeout(time.Duration)
|
SetTimeout(time.Duration)
|
||||||
TLSConnectionState() (tls.ConnectionState, bool)
|
|
||||||
|
|
||||||
Bind(username, password string) error
|
Bind(username, password string) error
|
||||||
UnauthenticatedBind(username string) error
|
UnauthenticatedBind(username string) error
|
||||||
SimpleBind(*SimpleBindRequest) (*SimpleBindResult, error)
|
SimpleBind(*SimpleBindRequest) (*SimpleBindResult, error)
|
||||||
ExternalBind() error
|
ExternalBind() error
|
||||||
NTLMUnauthenticatedBind(domain, username string) error
|
|
||||||
Unbind() error
|
|
||||||
|
|
||||||
Add(*AddRequest) error
|
Add(*AddRequest) error
|
||||||
Del(*DelRequest) error
|
Del(*DelRequest) error
|
||||||
|
@ -33,9 +28,5 @@ type Client interface {
|
||||||
PasswordModify(*PasswordModifyRequest) (*PasswordModifyResult, error)
|
PasswordModify(*PasswordModifyRequest) (*PasswordModifyResult, error)
|
||||||
|
|
||||||
Search(*SearchRequest) (*SearchResult, error)
|
Search(*SearchRequest) (*SearchResult, error)
|
||||||
SearchAsync(ctx context.Context, searchRequest *SearchRequest, bufferSize int) Response
|
|
||||||
SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
|
SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
|
||||||
DirSync(searchRequest *SearchRequest, flags, maxAttrCount int64, cookie []byte) (*SearchResult, error)
|
|
||||||
DirSyncAsync(ctx context.Context, searchRequest *SearchRequest, bufferSize int, flags, maxAttrCount int64, cookie []byte) Response
|
|
||||||
Syncrepl(ctx context.Context, searchRequest *SearchRequest, bufferSize int, mode ControlSyncRequestMode, cookie []byte, reloadHint bool) Response
|
|
||||||
}
|
}
|
||||||
|
|
3
vendor/github.com/go-ldap/ldap/v3/compare.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/compare.go
generated
vendored
|
@ -34,8 +34,7 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
|
||||||
msgCtx, err := l.doRequest(&CompareRequest{
|
msgCtx, err := l.doRequest(&CompareRequest{
|
||||||
DN: dn,
|
DN: dn,
|
||||||
Attribute: attribute,
|
Attribute: attribute,
|
||||||
Value: value,
|
Value: value})
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
126
vendor/github.com/go-ldap/ldap/v3/conn.go
generated
vendored
126
vendor/github.com/go-ldap/ldap/v3/conn.go
generated
vendored
|
@ -2,10 +2,10 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -61,21 +61,13 @@ type messageContext struct {
|
||||||
|
|
||||||
// sendResponse should only be called within the processMessages() loop which
|
// sendResponse should only be called within the processMessages() loop which
|
||||||
// is also responsible for closing the responses channel.
|
// is also responsible for closing the responses channel.
|
||||||
func (msgCtx *messageContext) sendResponse(packet *PacketResponse, timeout time.Duration) {
|
func (msgCtx *messageContext) sendResponse(packet *PacketResponse) {
|
||||||
timeoutCtx := context.Background()
|
|
||||||
if timeout > 0 {
|
|
||||||
var cancelFunc context.CancelFunc
|
|
||||||
timeoutCtx, cancelFunc = context.WithTimeout(context.Background(), timeout)
|
|
||||||
defer cancelFunc()
|
|
||||||
}
|
|
||||||
select {
|
select {
|
||||||
case msgCtx.responses <- packet:
|
case msgCtx.responses <- packet:
|
||||||
// Successfully sent packet to message handler.
|
// Successfully sent packet to message handler.
|
||||||
case <-msgCtx.done:
|
case <-msgCtx.done:
|
||||||
// The request handler is done and will not receive more
|
// The request handler is done and will not receive more
|
||||||
// packets.
|
// packets.
|
||||||
case <-timeoutCtx.Done():
|
|
||||||
// The timeout was reached before the packet was sent.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +88,6 @@ const (
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
// requestTimeout is loaded atomically
|
// requestTimeout is loaded atomically
|
||||||
// so we need to ensure 64-bit alignment on 32-bit platforms.
|
// so we need to ensure 64-bit alignment on 32-bit platforms.
|
||||||
// https://github.com/go-ldap/ldap/pull/199
|
|
||||||
requestTimeout int64
|
requestTimeout int64
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
isTLS bool
|
isTLS bool
|
||||||
|
@ -111,8 +102,6 @@ type Conn struct {
|
||||||
wgClose sync.WaitGroup
|
wgClose sync.WaitGroup
|
||||||
outstandingRequests uint
|
outstandingRequests uint
|
||||||
messageMutex sync.Mutex
|
messageMutex sync.Mutex
|
||||||
|
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Client = &Conn{}
|
var _ Client = &Conn{}
|
||||||
|
@ -130,31 +119,30 @@ type DialOpt func(*DialContext)
|
||||||
// DialWithDialer updates net.Dialer in DialContext.
|
// DialWithDialer updates net.Dialer in DialContext.
|
||||||
func DialWithDialer(d *net.Dialer) DialOpt {
|
func DialWithDialer(d *net.Dialer) DialOpt {
|
||||||
return func(dc *DialContext) {
|
return func(dc *DialContext) {
|
||||||
dc.dialer = d
|
dc.d = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialWithTLSConfig updates tls.Config in DialContext.
|
// DialWithTLSConfig updates tls.Config in DialContext.
|
||||||
func DialWithTLSConfig(tc *tls.Config) DialOpt {
|
func DialWithTLSConfig(tc *tls.Config) DialOpt {
|
||||||
return func(dc *DialContext) {
|
return func(dc *DialContext) {
|
||||||
dc.tlsConfig = tc
|
dc.tc = tc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialWithTLSDialer is a wrapper for DialWithTLSConfig with the option to
|
// DialWithTLSDialer is a wrapper for DialWithTLSConfig with the option to
|
||||||
// specify a net.Dialer to for example define a timeout or a custom resolver.
|
// specify a net.Dialer to for example define a timeout or a custom resolver.
|
||||||
// @deprecated Use DialWithDialer and DialWithTLSConfig instead
|
|
||||||
func DialWithTLSDialer(tlsConfig *tls.Config, dialer *net.Dialer) DialOpt {
|
func DialWithTLSDialer(tlsConfig *tls.Config, dialer *net.Dialer) DialOpt {
|
||||||
return func(dc *DialContext) {
|
return func(dc *DialContext) {
|
||||||
dc.tlsConfig = tlsConfig
|
dc.tc = tlsConfig
|
||||||
dc.dialer = dialer
|
dc.d = dialer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext contains necessary parameters to dial the given ldap URL.
|
// DialContext contains necessary parameters to dial the given ldap URL.
|
||||||
type DialContext struct {
|
type DialContext struct {
|
||||||
dialer *net.Dialer
|
d *net.Dialer
|
||||||
tlsConfig *tls.Config
|
tc *tls.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
|
func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
|
||||||
|
@ -162,7 +150,7 @@ func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
|
||||||
if u.Path == "" || u.Path == "/" {
|
if u.Path == "" || u.Path == "/" {
|
||||||
u.Path = "/var/run/slapd/ldapi"
|
u.Path = "/var/run/slapd/ldapi"
|
||||||
}
|
}
|
||||||
return dc.dialer.Dial("unix", u.Path)
|
return dc.d.Dial("unix", u.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(u.Host)
|
host, port, err := net.SplitHostPort(u.Host)
|
||||||
|
@ -173,21 +161,16 @@ func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
case "cldap":
|
|
||||||
if port == "" {
|
|
||||||
port = DefaultLdapPort
|
|
||||||
}
|
|
||||||
return dc.dialer.Dial("udp", net.JoinHostPort(host, port))
|
|
||||||
case "ldap":
|
case "ldap":
|
||||||
if port == "" {
|
if port == "" {
|
||||||
port = DefaultLdapPort
|
port = DefaultLdapPort
|
||||||
}
|
}
|
||||||
return dc.dialer.Dial("tcp", net.JoinHostPort(host, port))
|
return dc.d.Dial("tcp", net.JoinHostPort(host, port))
|
||||||
case "ldaps":
|
case "ldaps":
|
||||||
if port == "" {
|
if port == "" {
|
||||||
port = DefaultLdapsPort
|
port = DefaultLdapsPort
|
||||||
}
|
}
|
||||||
return tls.DialWithDialer(dc.dialer, "tcp", net.JoinHostPort(host, port), dc.tlsConfig)
|
return tls.DialWithDialer(dc.d, "tcp", net.JoinHostPort(host, port), dc.tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("Unknown scheme '%s'", u.Scheme)
|
return nil, fmt.Errorf("Unknown scheme '%s'", u.Scheme)
|
||||||
|
@ -220,8 +203,7 @@ func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialURL connects to the given ldap URL.
|
// DialURL connects to the given ldap URL.
|
||||||
// The following schemas are supported: ldap://, ldaps://, ldapi://,
|
// The following schemas are supported: ldap://, ldaps://, ldapi://.
|
||||||
// and cldap:// (RFC1798, deprecated but used by Active Directory).
|
|
||||||
// On success a new Conn for the connection is returned.
|
// On success a new Conn for the connection is returned.
|
||||||
func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
|
func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
|
||||||
u, err := url.Parse(addr)
|
u, err := url.Parse(addr)
|
||||||
|
@ -233,8 +215,8 @@ func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(&dc)
|
opt(&dc)
|
||||||
}
|
}
|
||||||
if dc.dialer == nil {
|
if dc.d == nil {
|
||||||
dc.dialer = &net.Dialer{Timeout: DefaultTimeout}
|
dc.d = &net.Dialer{Timeout: DefaultTimeout}
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dc.dial(u)
|
c, err := dc.dial(u)
|
||||||
|
@ -249,7 +231,7 @@ func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
|
||||||
|
|
||||||
// NewConn returns a new Conn using conn for network I/O.
|
// NewConn returns a new Conn using conn for network I/O.
|
||||||
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
||||||
l := &Conn{
|
return &Conn{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
chanConfirm: make(chan struct{}),
|
chanConfirm: make(chan struct{}),
|
||||||
chanMessageID: make(chan int64),
|
chanMessageID: make(chan int64),
|
||||||
|
@ -258,12 +240,11 @@ func NewConn(conn net.Conn, isTLS bool) *Conn {
|
||||||
requestTimeout: 0,
|
requestTimeout: 0,
|
||||||
isTLS: isTLS,
|
isTLS: isTLS,
|
||||||
}
|
}
|
||||||
l.wgClose.Add(1)
|
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start initializes goroutines to read responses and process messages
|
// Start initializes goroutines to read responses and process messages
|
||||||
func (l *Conn) Start() {
|
func (l *Conn) Start() {
|
||||||
|
l.wgClose.Add(1)
|
||||||
go l.reader()
|
go l.reader()
|
||||||
go l.processMessages()
|
go l.processMessages()
|
||||||
}
|
}
|
||||||
|
@ -279,45 +260,31 @@ func (l *Conn) setClosing() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the connection.
|
// Close closes the connection.
|
||||||
func (l *Conn) Close() (err error) {
|
func (l *Conn) Close() {
|
||||||
l.messageMutex.Lock()
|
l.messageMutex.Lock()
|
||||||
defer l.messageMutex.Unlock()
|
defer l.messageMutex.Unlock()
|
||||||
|
|
||||||
if l.setClosing() {
|
if l.setClosing() {
|
||||||
l.Debug.Printf("Sending quit message and waiting for confirmation")
|
l.Debug.Printf("Sending quit message and waiting for confirmation")
|
||||||
l.chanMessage <- &messagePacket{Op: MessageQuit}
|
l.chanMessage <- &messagePacket{Op: MessageQuit}
|
||||||
|
<-l.chanConfirm
|
||||||
timeoutCtx := context.Background()
|
|
||||||
if l.getTimeout() > 0 {
|
|
||||||
var cancelFunc context.CancelFunc
|
|
||||||
timeoutCtx, cancelFunc = context.WithTimeout(timeoutCtx, time.Duration(l.getTimeout()))
|
|
||||||
defer cancelFunc()
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-l.chanConfirm:
|
|
||||||
// Confirmation was received.
|
|
||||||
case <-timeoutCtx.Done():
|
|
||||||
// The timeout was reached before confirmation was received.
|
|
||||||
}
|
|
||||||
|
|
||||||
close(l.chanMessage)
|
close(l.chanMessage)
|
||||||
|
|
||||||
l.Debug.Printf("Closing network connection")
|
l.Debug.Printf("Closing network connection")
|
||||||
err = l.conn.Close()
|
if err := l.conn.Close(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
l.wgClose.Done()
|
l.wgClose.Done()
|
||||||
}
|
}
|
||||||
l.wgClose.Wait()
|
l.wgClose.Wait()
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTimeout sets the time after a request is sent that a MessageTimeout triggers
|
// SetTimeout sets the time after a request is sent that a MessageTimeout triggers
|
||||||
func (l *Conn) SetTimeout(timeout time.Duration) {
|
func (l *Conn) SetTimeout(timeout time.Duration) {
|
||||||
atomic.StoreInt64(&l.requestTimeout, int64(timeout))
|
if timeout > 0 {
|
||||||
}
|
atomic.StoreInt64(&l.requestTimeout, int64(timeout))
|
||||||
|
}
|
||||||
func (l *Conn) getTimeout() int64 {
|
|
||||||
return atomic.LoadInt64(&l.requestTimeout)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the next available messageID
|
// Returns the next available messageID
|
||||||
|
@ -328,14 +295,6 @@ func (l *Conn) nextMessageID() int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLastError returns the last recorded error from goroutines like processMessages and reader.
|
|
||||||
// Only the last recorded error will be returned.
|
|
||||||
func (l *Conn) GetLastError() error {
|
|
||||||
l.messageMutex.Lock()
|
|
||||||
defer l.messageMutex.Unlock()
|
|
||||||
return l.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
|
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
|
||||||
func (l *Conn) StartTLS(config *tls.Config) error {
|
func (l *Conn) StartTLS(config *tls.Config) error {
|
||||||
if l.isTLS {
|
if l.isTLS {
|
||||||
|
@ -484,13 +443,13 @@ func (l *Conn) sendProcessMessage(message *messagePacket) bool {
|
||||||
func (l *Conn) processMessages() {
|
func (l *Conn) processMessages() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
l.err = fmt.Errorf("ldap: recovered panic in processMessages: %v", err)
|
log.Printf("ldap: recovered panic in processMessages: %v", err)
|
||||||
}
|
}
|
||||||
for messageID, msgCtx := range l.messageContexts {
|
for messageID, msgCtx := range l.messageContexts {
|
||||||
// If we are closing due to an error, inform anyone who
|
// If we are closing due to an error, inform anyone who
|
||||||
// is waiting about the error.
|
// is waiting about the error.
|
||||||
if l.IsClosing() && l.closeErr.Load() != nil {
|
if l.IsClosing() && l.closeErr.Load() != nil {
|
||||||
msgCtx.sendResponse(&PacketResponse{Error: l.closeErr.Load().(error)}, time.Duration(l.getTimeout()))
|
msgCtx.sendResponse(&PacketResponse{Error: l.closeErr.Load().(error)})
|
||||||
}
|
}
|
||||||
l.Debug.Printf("Closing channel for MessageID %d", messageID)
|
l.Debug.Printf("Closing channel for MessageID %d", messageID)
|
||||||
close(msgCtx.responses)
|
close(msgCtx.responses)
|
||||||
|
@ -518,7 +477,7 @@ func (l *Conn) processMessages() {
|
||||||
_, err := l.conn.Write(buf)
|
_, err := l.conn.Write(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debug.Printf("Error Sending Message: %s", err.Error())
|
l.Debug.Printf("Error Sending Message: %s", err.Error())
|
||||||
message.Context.sendResponse(&PacketResponse{Error: fmt.Errorf("unable to send request: %s", err)}, time.Duration(l.getTimeout()))
|
message.Context.sendResponse(&PacketResponse{Error: fmt.Errorf("unable to send request: %s", err)})
|
||||||
close(message.Context.responses)
|
close(message.Context.responses)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -528,35 +487,28 @@ func (l *Conn) processMessages() {
|
||||||
l.messageContexts[message.MessageID] = message.Context
|
l.messageContexts[message.MessageID] = message.Context
|
||||||
|
|
||||||
// Add timeout if defined
|
// Add timeout if defined
|
||||||
requestTimeout := l.getTimeout()
|
requestTimeout := time.Duration(atomic.LoadInt64(&l.requestTimeout))
|
||||||
if requestTimeout > 0 {
|
if requestTimeout > 0 {
|
||||||
go func() {
|
go func() {
|
||||||
timer := time.NewTimer(time.Duration(requestTimeout))
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
l.err = fmt.Errorf("ldap: recovered panic in RequestTimeout: %v", err)
|
log.Printf("ldap: recovered panic in RequestTimeout: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.Stop()
|
|
||||||
}()
|
}()
|
||||||
|
time.Sleep(requestTimeout)
|
||||||
select {
|
timeoutMessage := &messagePacket{
|
||||||
case <-timer.C:
|
Op: MessageTimeout,
|
||||||
timeoutMessage := &messagePacket{
|
MessageID: message.MessageID,
|
||||||
Op: MessageTimeout,
|
|
||||||
MessageID: message.MessageID,
|
|
||||||
}
|
|
||||||
l.sendProcessMessage(timeoutMessage)
|
|
||||||
case <-message.Context.done:
|
|
||||||
}
|
}
|
||||||
|
l.sendProcessMessage(timeoutMessage)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
case MessageResponse:
|
case MessageResponse:
|
||||||
l.Debug.Printf("Receiving message %d", message.MessageID)
|
l.Debug.Printf("Receiving message %d", message.MessageID)
|
||||||
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||||
msgCtx.sendResponse(&PacketResponse{message.Packet, nil}, time.Duration(l.getTimeout()))
|
msgCtx.sendResponse(&PacketResponse{message.Packet, nil})
|
||||||
} else {
|
} else {
|
||||||
l.err = fmt.Errorf("ldap: received unexpected message %d, %v", message.MessageID, l.IsClosing())
|
log.Printf("Received unexpected message %d, %v", message.MessageID, l.IsClosing())
|
||||||
l.Debug.PrintPacket(message.Packet)
|
l.Debug.PrintPacket(message.Packet)
|
||||||
}
|
}
|
||||||
case MessageTimeout:
|
case MessageTimeout:
|
||||||
|
@ -564,7 +516,7 @@ func (l *Conn) processMessages() {
|
||||||
// All reads will return immediately
|
// All reads will return immediately
|
||||||
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||||
l.Debug.Printf("Receiving message timeout for %d", message.MessageID)
|
l.Debug.Printf("Receiving message timeout for %d", message.MessageID)
|
||||||
msgCtx.sendResponse(&PacketResponse{message.Packet, NewError(ErrorNetwork, errors.New("ldap: connection timed out"))}, time.Duration(l.getTimeout()))
|
msgCtx.sendResponse(&PacketResponse{message.Packet, NewError(ErrorNetwork, errors.New("ldap: connection timed out"))})
|
||||||
delete(l.messageContexts, message.MessageID)
|
delete(l.messageContexts, message.MessageID)
|
||||||
close(msgCtx.responses)
|
close(msgCtx.responses)
|
||||||
}
|
}
|
||||||
|
@ -583,7 +535,7 @@ func (l *Conn) reader() {
|
||||||
cleanstop := false
|
cleanstop := false
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
l.err = fmt.Errorf("ldap: recovered panic in reader: %v", err)
|
log.Printf("ldap: recovered panic in reader: %v", err)
|
||||||
}
|
}
|
||||||
if !cleanstop {
|
if !cleanstop {
|
||||||
l.Close()
|
l.Close()
|
||||||
|
|
788
vendor/github.com/go-ldap/ldap/v3/control.go
generated
vendored
788
vendor/github.com/go-ldap/ldap/v3/control.go
generated
vendored
|
@ -5,7 +5,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -21,13 +20,6 @@ const (
|
||||||
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
||||||
// ControlTypeWhoAmI - https://tools.ietf.org/html/rfc4532
|
// ControlTypeWhoAmI - https://tools.ietf.org/html/rfc4532
|
||||||
ControlTypeWhoAmI = "1.3.6.1.4.1.4203.1.11.3"
|
ControlTypeWhoAmI = "1.3.6.1.4.1.4203.1.11.3"
|
||||||
// ControlTypeSubtreeDelete - https://datatracker.ietf.org/doc/html/draft-armijo-ldap-treedelete-02
|
|
||||||
ControlTypeSubtreeDelete = "1.2.840.113556.1.4.805"
|
|
||||||
|
|
||||||
// ControlTypeServerSideSorting - https://www.ietf.org/rfc/rfc2891.txt
|
|
||||||
ControlTypeServerSideSorting = "1.2.840.113556.1.4.473"
|
|
||||||
// ControlTypeServerSideSorting - https://www.ietf.org/rfc/rfc2891.txt
|
|
||||||
ControlTypeServerSideSortingResult = "1.2.840.113556.1.4.474"
|
|
||||||
|
|
||||||
// ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
|
// ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
|
||||||
ControlTypeMicrosoftNotification = "1.2.840.113556.1.4.528"
|
ControlTypeMicrosoftNotification = "1.2.840.113556.1.4.528"
|
||||||
|
@ -35,43 +27,16 @@ const (
|
||||||
ControlTypeMicrosoftShowDeleted = "1.2.840.113556.1.4.417"
|
ControlTypeMicrosoftShowDeleted = "1.2.840.113556.1.4.417"
|
||||||
// ControlTypeMicrosoftServerLinkTTL - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/f4f523a8-abc0-4b3a-a471-6b2fef135481?redirectedfrom=MSDN
|
// ControlTypeMicrosoftServerLinkTTL - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/f4f523a8-abc0-4b3a-a471-6b2fef135481?redirectedfrom=MSDN
|
||||||
ControlTypeMicrosoftServerLinkTTL = "1.2.840.113556.1.4.2309"
|
ControlTypeMicrosoftServerLinkTTL = "1.2.840.113556.1.4.2309"
|
||||||
// ControlTypeDirSync - Active Directory DirSync - https://msdn.microsoft.com/en-us/library/aa366978(v=vs.85).aspx
|
|
||||||
ControlTypeDirSync = "1.2.840.113556.1.4.841"
|
|
||||||
|
|
||||||
// ControlTypeSyncRequest - https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
ControlTypeSyncRequest = "1.3.6.1.4.1.4203.1.9.1.1"
|
|
||||||
// ControlTypeSyncState - https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
ControlTypeSyncState = "1.3.6.1.4.1.4203.1.9.1.2"
|
|
||||||
// ControlTypeSyncDone - https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
ControlTypeSyncDone = "1.3.6.1.4.1.4203.1.9.1.3"
|
|
||||||
// ControlTypeSyncInfo - https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
ControlTypeSyncInfo = "1.3.6.1.4.1.4203.1.9.1.4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Flags for DirSync control
|
|
||||||
const (
|
|
||||||
DirSyncIncrementalValues int64 = 2147483648
|
|
||||||
DirSyncPublicDataOnly int64 = 8192
|
|
||||||
DirSyncAncestorsFirstOrder int64 = 2048
|
|
||||||
DirSyncObjectSecurity int64 = 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControlTypeMap maps controls to text descriptions
|
// ControlTypeMap maps controls to text descriptions
|
||||||
var ControlTypeMap = map[string]string{
|
var ControlTypeMap = map[string]string{
|
||||||
ControlTypePaging: "Paging",
|
ControlTypePaging: "Paging",
|
||||||
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
||||||
ControlTypeManageDsaIT: "Manage DSA IT",
|
ControlTypeManageDsaIT: "Manage DSA IT",
|
||||||
ControlTypeSubtreeDelete: "Subtree Delete Control",
|
ControlTypeMicrosoftNotification: "Change Notification - Microsoft",
|
||||||
ControlTypeMicrosoftNotification: "Change Notification - Microsoft",
|
ControlTypeMicrosoftShowDeleted: "Show Deleted Objects - Microsoft",
|
||||||
ControlTypeMicrosoftShowDeleted: "Show Deleted Objects - Microsoft",
|
ControlTypeMicrosoftServerLinkTTL: "Return TTL-DNs for link values with associated expiry times - Microsoft",
|
||||||
ControlTypeMicrosoftServerLinkTTL: "Return TTL-DNs for link values with associated expiry times - Microsoft",
|
|
||||||
ControlTypeServerSideSorting: "Server Side Sorting Request - LDAP Control Extension for Server Side Sorting of Search Results (RFC2891)",
|
|
||||||
ControlTypeServerSideSortingResult: "Server Side Sorting Results - LDAP Control Extension for Server Side Sorting of Search Results (RFC2891)",
|
|
||||||
ControlTypeDirSync: "DirSync",
|
|
||||||
ControlTypeSyncRequest: "Sync Request",
|
|
||||||
ControlTypeSyncState: "Sync State",
|
|
||||||
ControlTypeSyncDone: "Sync Done",
|
|
||||||
ControlTypeSyncInfo: "Sync Info",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control defines an interface controls provide to encode and describe themselves
|
// Control defines an interface controls provide to encode and describe themselves
|
||||||
|
@ -264,7 +229,7 @@ func (c *ControlManageDsaIT) GetControlType() string {
|
||||||
|
|
||||||
// Encode returns the ber packet representation
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
||||||
// FIXME
|
//FIXME
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeManageDsaIT, "Control Type ("+ControlTypeMap[ControlTypeManageDsaIT]+")"))
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeManageDsaIT, "Control Type ("+ControlTypeMap[ControlTypeManageDsaIT]+")"))
|
||||||
if c.Criticality {
|
if c.Criticality {
|
||||||
|
@ -404,13 +369,7 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
||||||
if packet.Children[0].Value != nil {
|
ControlType = packet.Children[0].Value.(string)
|
||||||
ControlType = packet.Children[0].Value.(string)
|
|
||||||
} else if packet.Children[0].Data != nil {
|
|
||||||
ControlType = packet.Children[0].Data.String()
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("not found where to get the control type")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Children[1] could be criticality or value (both are optional)
|
// Children[1] could be criticality or value (both are optional)
|
||||||
// duck-type on whether this is a boolean
|
// duck-type on whether this is a boolean
|
||||||
|
@ -477,18 +436,18 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||||
|
|
||||||
for _, child := range sequence.Children {
|
for _, child := range sequence.Children {
|
||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
// Warning
|
//Warning
|
||||||
warningPacket := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
val, err := ber.ParseInt64(warningPacket.Data.Bytes())
|
val, err := ber.ParseInt64(warningPacket.Data.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
}
|
}
|
||||||
if warningPacket.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
// timeBeforeExpiration
|
//timeBeforeExpiration
|
||||||
c.Expire = val
|
c.Expire = val
|
||||||
warningPacket.Value = c.Expire
|
warningPacket.Value = c.Expire
|
||||||
} else if warningPacket.Tag == 1 {
|
} else if warningPacket.Tag == 1 {
|
||||||
// graceAuthNsRemaining
|
//graceAuthNsRemaining
|
||||||
c.Grace = val
|
c.Grace = val
|
||||||
warningPacket.Value = c.Grace
|
warningPacket.Value = c.Grace
|
||||||
}
|
}
|
||||||
|
@ -526,36 +485,6 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||||
return NewControlMicrosoftShowDeleted(), nil
|
return NewControlMicrosoftShowDeleted(), nil
|
||||||
case ControlTypeMicrosoftServerLinkTTL:
|
case ControlTypeMicrosoftServerLinkTTL:
|
||||||
return NewControlMicrosoftServerLinkTTL(), nil
|
return NewControlMicrosoftServerLinkTTL(), nil
|
||||||
case ControlTypeSubtreeDelete:
|
|
||||||
return NewControlSubtreeDelete(), nil
|
|
||||||
case ControlTypeServerSideSorting:
|
|
||||||
return NewControlServerSideSorting(value)
|
|
||||||
case ControlTypeServerSideSortingResult:
|
|
||||||
return NewControlServerSideSortingResult(value)
|
|
||||||
case ControlTypeDirSync:
|
|
||||||
value.Description += " (DirSync)"
|
|
||||||
return NewResponseControlDirSync(value)
|
|
||||||
case ControlTypeSyncState:
|
|
||||||
value.Description += " (Sync State)"
|
|
||||||
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
|
||||||
}
|
|
||||||
return NewControlSyncState(valueChildren)
|
|
||||||
case ControlTypeSyncDone:
|
|
||||||
value.Description += " (Sync Done)"
|
|
||||||
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
|
||||||
}
|
|
||||||
return NewControlSyncDone(valueChildren)
|
|
||||||
case ControlTypeSyncInfo:
|
|
||||||
value.Description += " (Sync Info)"
|
|
||||||
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
|
||||||
}
|
|
||||||
return NewControlSyncInfo(valueChildren)
|
|
||||||
default:
|
default:
|
||||||
c := new(ControlString)
|
c := new(ControlString)
|
||||||
c.ControlType = ControlType
|
c.ControlType = ControlType
|
||||||
|
@ -590,35 +519,6 @@ func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControlSubtreeDelete implements the subtree delete control described in
|
|
||||||
// https://datatracker.ietf.org/doc/html/draft-armijo-ldap-treedelete-02
|
|
||||||
type ControlSubtreeDelete struct{}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlSubtreeDelete) GetControlType() string {
|
|
||||||
return ControlTypeSubtreeDelete
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewControlSubtreeDelete returns a ControlSubtreeDelete control.
|
|
||||||
func NewControlSubtreeDelete() *ControlSubtreeDelete {
|
|
||||||
return &ControlSubtreeDelete{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode returns the ber packet representation
|
|
||||||
func (c *ControlSubtreeDelete) Encode() *ber.Packet {
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeSubtreeDelete, "Control Type ("+ControlTypeMap[ControlTypeSubtreeDelete]+")"))
|
|
||||||
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlSubtreeDelete) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q)",
|
|
||||||
ControlTypeMap[ControlTypeSubtreeDelete],
|
|
||||||
ControlTypeSubtreeDelete)
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeControls(controls []Control) *ber.Packet {
|
func encodeControls(controls []Control) *ber.Packet {
|
||||||
packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls")
|
packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls")
|
||||||
for _, control := range controls {
|
for _, control := range controls {
|
||||||
|
@ -626,669 +526,3 @@ func encodeControls(controls []Control) *ber.Packet {
|
||||||
}
|
}
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControlDirSync implements the control described in https://msdn.microsoft.com/en-us/library/aa366978(v=vs.85).aspx
|
|
||||||
type ControlDirSync struct {
|
|
||||||
Criticality bool
|
|
||||||
Flags int64
|
|
||||||
MaxAttrCount int64
|
|
||||||
Cookie []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// @deprecated Use NewRequestControlDirSync instead
|
|
||||||
func NewControlDirSync(flags int64, maxAttrCount int64, cookie []byte) *ControlDirSync {
|
|
||||||
return NewRequestControlDirSync(flags, maxAttrCount, cookie)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRequestControlDirSync returns a dir sync control
|
|
||||||
func NewRequestControlDirSync(
|
|
||||||
flags int64, maxAttrCount int64, cookie []byte,
|
|
||||||
) *ControlDirSync {
|
|
||||||
return &ControlDirSync{
|
|
||||||
Criticality: true,
|
|
||||||
Flags: flags,
|
|
||||||
MaxAttrCount: maxAttrCount,
|
|
||||||
Cookie: cookie,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResponseControlDirSync returns a dir sync control
|
|
||||||
func NewResponseControlDirSync(value *ber.Packet) (*ControlDirSync, error) {
|
|
||||||
if value.Value != nil {
|
|
||||||
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
|
||||||
}
|
|
||||||
value.Data.Truncate(0)
|
|
||||||
value.Value = nil
|
|
||||||
value.AppendChild(valueChildren)
|
|
||||||
}
|
|
||||||
child := value.Children[0]
|
|
||||||
if len(child.Children) != 3 { // also on initial creation, Cookie is an empty string
|
|
||||||
return nil, fmt.Errorf("invalid number of children in dirSync control")
|
|
||||||
}
|
|
||||||
child.Description = "DirSync Control Value"
|
|
||||||
child.Children[0].Description = "Flags"
|
|
||||||
child.Children[1].Description = "MaxAttrCount"
|
|
||||||
child.Children[2].Description = "Cookie"
|
|
||||||
|
|
||||||
cookie := child.Children[2].Data.Bytes()
|
|
||||||
child.Children[2].Value = cookie
|
|
||||||
return &ControlDirSync{
|
|
||||||
Criticality: true,
|
|
||||||
Flags: child.Children[0].Value.(int64),
|
|
||||||
MaxAttrCount: child.Children[1].Value.(int64),
|
|
||||||
Cookie: cookie,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlDirSync) GetControlType() string {
|
|
||||||
return ControlTypeDirSync
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlDirSync) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"ControlType: %s (%q) Criticality: %t ControlValue: Flags: %d MaxAttrCount: %d",
|
|
||||||
ControlTypeMap[ControlTypeDirSync],
|
|
||||||
ControlTypeDirSync,
|
|
||||||
c.Criticality,
|
|
||||||
c.Flags,
|
|
||||||
c.MaxAttrCount,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode returns the ber packet representation
|
|
||||||
func (c *ControlDirSync) Encode() *ber.Packet {
|
|
||||||
cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "Cookie")
|
|
||||||
if len(c.Cookie) != 0 {
|
|
||||||
cookie.Value = c.Cookie
|
|
||||||
cookie.Data.Write(c.Cookie)
|
|
||||||
}
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeDirSync, "Control Type ("+ControlTypeMap[ControlTypeDirSync]+")"))
|
|
||||||
packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality")) // must be true always
|
|
||||||
|
|
||||||
val := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (DirSync)")
|
|
||||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "DirSync Control Value")
|
|
||||||
seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, int64(c.Flags), "Flags"))
|
|
||||||
seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, int64(c.MaxAttrCount), "MaxAttrCount"))
|
|
||||||
seq.AppendChild(cookie)
|
|
||||||
val.AppendChild(seq)
|
|
||||||
|
|
||||||
packet.AppendChild(val)
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetCookie stores the given cookie in the dirSync control
|
|
||||||
func (c *ControlDirSync) SetCookie(cookie []byte) {
|
|
||||||
c.Cookie = cookie
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlServerSideSorting
|
|
||||||
|
|
||||||
type SortKey struct {
|
|
||||||
Reverse bool
|
|
||||||
AttributeType string
|
|
||||||
MatchingRule string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlServerSideSorting struct {
|
|
||||||
SortKeys []*SortKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlServerSideSorting) GetControlType() string {
|
|
||||||
return ControlTypeServerSideSorting
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlServerSideSorting(value *ber.Packet) (*ControlServerSideSorting, error) {
|
|
||||||
sortKeys := []*SortKey{}
|
|
||||||
|
|
||||||
val := value.Children[1].Children
|
|
||||||
|
|
||||||
if len(val) != 1 {
|
|
||||||
return nil, fmt.Errorf("no sequence value in packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
sequences := val[0].Children
|
|
||||||
|
|
||||||
for i, sequence := range sequences {
|
|
||||||
sortKey := &SortKey{}
|
|
||||||
|
|
||||||
if len(sequence.Children) < 2 {
|
|
||||||
return nil, fmt.Errorf("attributeType or matchingRule is missing from sequence %d", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
sortKey.AttributeType = sequence.Children[0].Value.(string)
|
|
||||||
sortKey.MatchingRule = sequence.Children[1].Value.(string)
|
|
||||||
|
|
||||||
if len(sequence.Children) == 3 {
|
|
||||||
sortKey.Reverse = sequence.Children[2].Value.(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
sortKeys = append(sortKeys, sortKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ControlServerSideSorting{SortKeys: sortKeys}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlServerSideSortingWithSortKeys(sortKeys []*SortKey) *ControlServerSideSorting {
|
|
||||||
return &ControlServerSideSorting{SortKeys: sortKeys}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlServerSideSorting) Encode() *ber.Packet {
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
|
||||||
control := ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.GetControlType(), "Control Type")
|
|
||||||
|
|
||||||
value := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value")
|
|
||||||
seqs := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "SortKeyList")
|
|
||||||
|
|
||||||
for _, f := range c.SortKeys {
|
|
||||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "")
|
|
||||||
|
|
||||||
seq.AppendChild(
|
|
||||||
ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, f.AttributeType, "attributeType"),
|
|
||||||
)
|
|
||||||
seq.AppendChild(
|
|
||||||
ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, f.MatchingRule, "orderingRule"),
|
|
||||||
)
|
|
||||||
if f.Reverse {
|
|
||||||
seq.AppendChild(
|
|
||||||
ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, 1, f.Reverse, "reverseOrder"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
seqs.AppendChild(seq)
|
|
||||||
}
|
|
||||||
|
|
||||||
value.AppendChild(seqs)
|
|
||||||
|
|
||||||
packet.AppendChild(control)
|
|
||||||
packet.AppendChild(value)
|
|
||||||
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlServerSideSorting) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality:%t %+v",
|
|
||||||
"Server Side Sorting",
|
|
||||||
c.GetControlType(),
|
|
||||||
false,
|
|
||||||
c.SortKeys,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlServerSideSortingResponse
|
|
||||||
|
|
||||||
const (
|
|
||||||
ControlServerSideSortingCodeSuccess ControlServerSideSortingCode = 0
|
|
||||||
ControlServerSideSortingCodeOperationsError ControlServerSideSortingCode = 1
|
|
||||||
ControlServerSideSortingCodeTimeLimitExceeded ControlServerSideSortingCode = 2
|
|
||||||
ControlServerSideSortingCodeStrongAuthRequired ControlServerSideSortingCode = 8
|
|
||||||
ControlServerSideSortingCodeAdminLimitExceeded ControlServerSideSortingCode = 11
|
|
||||||
ControlServerSideSortingCodeNoSuchAttribute ControlServerSideSortingCode = 16
|
|
||||||
ControlServerSideSortingCodeInappropriateMatching ControlServerSideSortingCode = 18
|
|
||||||
ControlServerSideSortingCodeInsufficientAccessRights ControlServerSideSortingCode = 50
|
|
||||||
ControlServerSideSortingCodeBusy ControlServerSideSortingCode = 51
|
|
||||||
ControlServerSideSortingCodeUnwillingToPerform ControlServerSideSortingCode = 53
|
|
||||||
ControlServerSideSortingCodeOther ControlServerSideSortingCode = 80
|
|
||||||
)
|
|
||||||
|
|
||||||
var ControlServerSideSortingCodes = []ControlServerSideSortingCode{
|
|
||||||
ControlServerSideSortingCodeSuccess,
|
|
||||||
ControlServerSideSortingCodeOperationsError,
|
|
||||||
ControlServerSideSortingCodeTimeLimitExceeded,
|
|
||||||
ControlServerSideSortingCodeStrongAuthRequired,
|
|
||||||
ControlServerSideSortingCodeAdminLimitExceeded,
|
|
||||||
ControlServerSideSortingCodeNoSuchAttribute,
|
|
||||||
ControlServerSideSortingCodeInappropriateMatching,
|
|
||||||
ControlServerSideSortingCodeInsufficientAccessRights,
|
|
||||||
ControlServerSideSortingCodeBusy,
|
|
||||||
ControlServerSideSortingCodeUnwillingToPerform,
|
|
||||||
ControlServerSideSortingCodeOther,
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlServerSideSortingCode int64
|
|
||||||
|
|
||||||
// Valid test the code contained in the control against the ControlServerSideSortingCodes slice and return an error if the code is unknown.
|
|
||||||
func (c ControlServerSideSortingCode) Valid() error {
|
|
||||||
for _, validRet := range ControlServerSideSortingCodes {
|
|
||||||
if c == validRet {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("unknown return code : %d", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlServerSideSortingResult(pkt *ber.Packet) (*ControlServerSideSortingResult, error) {
|
|
||||||
control := &ControlServerSideSortingResult{}
|
|
||||||
|
|
||||||
if pkt == nil || len(pkt.Children) == 0 {
|
|
||||||
return nil, fmt.Errorf("bad packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
codeInt, err := ber.ParseInt64(pkt.Children[0].Data.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
code := ControlServerSideSortingCode(codeInt)
|
|
||||||
if err := code.Valid(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return control, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControlServerSideSortingResult struct {
|
|
||||||
Criticality bool
|
|
||||||
|
|
||||||
Result ControlServerSideSortingCode
|
|
||||||
|
|
||||||
// Not populated for now. I can't get openldap to send me this value, so I think this is specific to other directory server
|
|
||||||
// AttributeType string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (control *ControlServerSideSortingResult) GetControlType() string {
|
|
||||||
return ControlTypeServerSideSortingResult
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlServerSideSortingResult) Encode() *ber.Packet {
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "SortResult sequence")
|
|
||||||
sortResult := ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, int64(c.Result), "SortResult")
|
|
||||||
packet.AppendChild(sortResult)
|
|
||||||
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlServerSideSortingResult) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality:%t ResultCode:%+v",
|
|
||||||
"Server Side Sorting Result",
|
|
||||||
c.GetControlType(),
|
|
||||||
c.Criticality,
|
|
||||||
c.Result,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode for ControlTypeSyncRequest
|
|
||||||
type ControlSyncRequestMode int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
SyncRequestModeRefreshOnly ControlSyncRequestMode = 1
|
|
||||||
SyncRequestModeRefreshAndPersist ControlSyncRequestMode = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// ControlSyncRequest implements the Sync Request Control described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncRequest struct {
|
|
||||||
Criticality bool
|
|
||||||
Mode ControlSyncRequestMode
|
|
||||||
Cookie []byte
|
|
||||||
ReloadHint bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlSyncRequest(
|
|
||||||
mode ControlSyncRequestMode, cookie []byte, reloadHint bool,
|
|
||||||
) *ControlSyncRequest {
|
|
||||||
return &ControlSyncRequest{
|
|
||||||
Criticality: true,
|
|
||||||
Mode: mode,
|
|
||||||
Cookie: cookie,
|
|
||||||
ReloadHint: reloadHint,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlSyncRequest) GetControlType() string {
|
|
||||||
return ControlTypeSyncRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes the control
|
|
||||||
func (c *ControlSyncRequest) Encode() *ber.Packet {
|
|
||||||
_mode := int64(c.Mode)
|
|
||||||
mode := ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, _mode, "Mode")
|
|
||||||
var cookie *ber.Packet
|
|
||||||
if len(c.Cookie) > 0 {
|
|
||||||
cookie = ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
|
|
||||||
cookie.Value = c.Cookie
|
|
||||||
cookie.Data.Write(c.Cookie)
|
|
||||||
}
|
|
||||||
reloadHint := ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.ReloadHint, "Reload Hint")
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeSyncRequest, "Control Type ("+ControlTypeMap[ControlTypeSyncRequest]+")"))
|
|
||||||
packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
|
|
||||||
|
|
||||||
val := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Sync Request)")
|
|
||||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Sync Request Value")
|
|
||||||
seq.AppendChild(mode)
|
|
||||||
if cookie != nil {
|
|
||||||
seq.AppendChild(cookie)
|
|
||||||
}
|
|
||||||
seq.AppendChild(reloadHint)
|
|
||||||
val.AppendChild(seq)
|
|
||||||
|
|
||||||
packet.AppendChild(val)
|
|
||||||
return packet
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncRequest) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality: %t Mode: %d Cookie: %s ReloadHint: %t",
|
|
||||||
ControlTypeMap[ControlTypeSyncRequest],
|
|
||||||
ControlTypeSyncRequest,
|
|
||||||
c.Criticality,
|
|
||||||
c.Mode,
|
|
||||||
string(c.Cookie),
|
|
||||||
c.ReloadHint,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// State for ControlSyncState
|
|
||||||
type ControlSyncStateState int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
SyncStatePresent ControlSyncStateState = 0
|
|
||||||
SyncStateAdd ControlSyncStateState = 1
|
|
||||||
SyncStateModify ControlSyncStateState = 2
|
|
||||||
SyncStateDelete ControlSyncStateState = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// ControlSyncState implements the Sync State Control described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncState struct {
|
|
||||||
Criticality bool
|
|
||||||
State ControlSyncStateState
|
|
||||||
EntryUUID uuid.UUID
|
|
||||||
Cookie []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlSyncState(pkt *ber.Packet) (*ControlSyncState, error) {
|
|
||||||
var (
|
|
||||||
state ControlSyncStateState
|
|
||||||
entryUUID uuid.UUID
|
|
||||||
cookie []byte
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
switch len(pkt.Children) {
|
|
||||||
case 0, 1:
|
|
||||||
return nil, fmt.Errorf("at least two children are required: %d", len(pkt.Children))
|
|
||||||
case 2:
|
|
||||||
state = ControlSyncStateState(pkt.Children[0].Value.(int64))
|
|
||||||
entryUUID, err = uuid.FromBytes(pkt.Children[1].ByteValue)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode uuid: %w", err)
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
state = ControlSyncStateState(pkt.Children[0].Value.(int64))
|
|
||||||
entryUUID, err = uuid.FromBytes(pkt.Children[1].ByteValue)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode uuid: %w", err)
|
|
||||||
}
|
|
||||||
cookie = pkt.Children[2].ByteValue
|
|
||||||
}
|
|
||||||
return &ControlSyncState{
|
|
||||||
Criticality: false,
|
|
||||||
State: state,
|
|
||||||
EntryUUID: entryUUID,
|
|
||||||
Cookie: cookie,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlSyncState) GetControlType() string {
|
|
||||||
return ControlTypeSyncState
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes the control
|
|
||||||
func (c *ControlSyncState) Encode() *ber.Packet {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncState) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality: %t State: %d EntryUUID: %s Cookie: %s",
|
|
||||||
ControlTypeMap[ControlTypeSyncState],
|
|
||||||
ControlTypeSyncState,
|
|
||||||
c.Criticality,
|
|
||||||
c.State,
|
|
||||||
c.EntryUUID.String(),
|
|
||||||
string(c.Cookie),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlSyncDone implements the Sync Done Control described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncDone struct {
|
|
||||||
Criticality bool
|
|
||||||
Cookie []byte
|
|
||||||
RefreshDeletes bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlSyncDone(pkt *ber.Packet) (*ControlSyncDone, error) {
|
|
||||||
var (
|
|
||||||
cookie []byte
|
|
||||||
refreshDeletes bool
|
|
||||||
)
|
|
||||||
switch len(pkt.Children) {
|
|
||||||
case 0:
|
|
||||||
// have nothing to do
|
|
||||||
case 1:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
case 2:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
refreshDeletes = pkt.Children[1].Value.(bool)
|
|
||||||
}
|
|
||||||
return &ControlSyncDone{
|
|
||||||
Criticality: false,
|
|
||||||
Cookie: cookie,
|
|
||||||
RefreshDeletes: refreshDeletes,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlSyncDone) GetControlType() string {
|
|
||||||
return ControlTypeSyncDone
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes the control
|
|
||||||
func (c *ControlSyncDone) Encode() *ber.Packet {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncDone) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality: %t Cookie: %s RefreshDeletes: %t",
|
|
||||||
ControlTypeMap[ControlTypeSyncDone],
|
|
||||||
ControlTypeSyncDone,
|
|
||||||
c.Criticality,
|
|
||||||
string(c.Cookie),
|
|
||||||
c.RefreshDeletes,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag For ControlSyncInfo
|
|
||||||
type ControlSyncInfoValue uint64
|
|
||||||
|
|
||||||
const (
|
|
||||||
SyncInfoNewcookie ControlSyncInfoValue = 0
|
|
||||||
SyncInfoRefreshDelete ControlSyncInfoValue = 1
|
|
||||||
SyncInfoRefreshPresent ControlSyncInfoValue = 2
|
|
||||||
SyncInfoSyncIdSet ControlSyncInfoValue = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// ControlSyncInfoNewCookie implements a part of syncInfoValue described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncInfoNewCookie struct {
|
|
||||||
Cookie []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncInfoNewCookie) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"NewCookie[Cookie: %s]",
|
|
||||||
string(c.Cookie),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlSyncInfoRefreshDelete implements a part of syncInfoValue described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncInfoRefreshDelete struct {
|
|
||||||
Cookie []byte
|
|
||||||
RefreshDone bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncInfoRefreshDelete) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"RefreshDelete[Cookie: %s RefreshDone: %t]",
|
|
||||||
string(c.Cookie),
|
|
||||||
c.RefreshDone,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlSyncInfoRefreshPresent implements a part of syncInfoValue described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncInfoRefreshPresent struct {
|
|
||||||
Cookie []byte
|
|
||||||
RefreshDone bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncInfoRefreshPresent) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"RefreshPresent[Cookie: %s RefreshDone: %t]",
|
|
||||||
string(c.Cookie),
|
|
||||||
c.RefreshDone,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlSyncInfoSyncIdSet implements a part of syncInfoValue described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncInfoSyncIdSet struct {
|
|
||||||
Cookie []byte
|
|
||||||
RefreshDeletes bool
|
|
||||||
SyncUUIDs []uuid.UUID
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncInfoSyncIdSet) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"SyncIdSet[Cookie: %s RefreshDeletes: %t SyncUUIDs: %v]",
|
|
||||||
string(c.Cookie),
|
|
||||||
c.RefreshDeletes,
|
|
||||||
c.SyncUUIDs,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ControlSyncInfo implements the Sync Info Control described in https://www.ietf.org/rfc/rfc4533.txt
|
|
||||||
type ControlSyncInfo struct {
|
|
||||||
Criticality bool
|
|
||||||
Value ControlSyncInfoValue
|
|
||||||
NewCookie *ControlSyncInfoNewCookie
|
|
||||||
RefreshDelete *ControlSyncInfoRefreshDelete
|
|
||||||
RefreshPresent *ControlSyncInfoRefreshPresent
|
|
||||||
SyncIdSet *ControlSyncInfoSyncIdSet
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewControlSyncInfo(pkt *ber.Packet) (*ControlSyncInfo, error) {
|
|
||||||
var (
|
|
||||||
cookie []byte
|
|
||||||
refreshDone = true
|
|
||||||
refreshDeletes bool
|
|
||||||
syncUUIDs []uuid.UUID
|
|
||||||
)
|
|
||||||
c := &ControlSyncInfo{Criticality: false}
|
|
||||||
switch ControlSyncInfoValue(pkt.Identifier.Tag) {
|
|
||||||
case SyncInfoNewcookie:
|
|
||||||
c.Value = SyncInfoNewcookie
|
|
||||||
c.NewCookie = &ControlSyncInfoNewCookie{
|
|
||||||
Cookie: pkt.ByteValue,
|
|
||||||
}
|
|
||||||
case SyncInfoRefreshDelete:
|
|
||||||
c.Value = SyncInfoRefreshDelete
|
|
||||||
switch len(pkt.Children) {
|
|
||||||
case 0:
|
|
||||||
// have nothing to do
|
|
||||||
case 1:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
case 2:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
refreshDone = pkt.Children[1].Value.(bool)
|
|
||||||
}
|
|
||||||
c.RefreshDelete = &ControlSyncInfoRefreshDelete{
|
|
||||||
Cookie: cookie,
|
|
||||||
RefreshDone: refreshDone,
|
|
||||||
}
|
|
||||||
case SyncInfoRefreshPresent:
|
|
||||||
c.Value = SyncInfoRefreshPresent
|
|
||||||
switch len(pkt.Children) {
|
|
||||||
case 0:
|
|
||||||
// have nothing to do
|
|
||||||
case 1:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
case 2:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
refreshDone = pkt.Children[1].Value.(bool)
|
|
||||||
}
|
|
||||||
c.RefreshPresent = &ControlSyncInfoRefreshPresent{
|
|
||||||
Cookie: cookie,
|
|
||||||
RefreshDone: refreshDone,
|
|
||||||
}
|
|
||||||
case SyncInfoSyncIdSet:
|
|
||||||
c.Value = SyncInfoSyncIdSet
|
|
||||||
switch len(pkt.Children) {
|
|
||||||
case 0:
|
|
||||||
// have nothing to do
|
|
||||||
case 1:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
case 2:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
refreshDeletes = pkt.Children[1].Value.(bool)
|
|
||||||
case 3:
|
|
||||||
cookie = pkt.Children[0].ByteValue
|
|
||||||
refreshDeletes = pkt.Children[1].Value.(bool)
|
|
||||||
syncUUIDs = make([]uuid.UUID, 0, len(pkt.Children[2].Children))
|
|
||||||
for _, child := range pkt.Children[2].Children {
|
|
||||||
u, err := uuid.FromBytes(child.ByteValue)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode uuid: %w", err)
|
|
||||||
}
|
|
||||||
syncUUIDs = append(syncUUIDs, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.SyncIdSet = &ControlSyncInfoSyncIdSet{
|
|
||||||
Cookie: cookie,
|
|
||||||
RefreshDeletes: refreshDeletes,
|
|
||||||
SyncUUIDs: syncUUIDs,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown sync info value: %d", pkt.Identifier.Tag)
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetControlType returns the OID
|
|
||||||
func (c *ControlSyncInfo) GetControlType() string {
|
|
||||||
return ControlTypeSyncInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes the control
|
|
||||||
func (c *ControlSyncInfo) Encode() *ber.Packet {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a human-readable description
|
|
||||||
func (c *ControlSyncInfo) String() string {
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"Control Type: %s (%q) Criticality: %t Value: %d %s %s %s %s",
|
|
||||||
ControlTypeMap[ControlTypeSyncInfo],
|
|
||||||
ControlTypeSyncInfo,
|
|
||||||
c.Criticality,
|
|
||||||
c.Value,
|
|
||||||
c.NewCookie,
|
|
||||||
c.RefreshDelete,
|
|
||||||
c.RefreshPresent,
|
|
||||||
c.SyncIdSet,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
8
vendor/github.com/go-ldap/ldap/v3/debug.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/debug.go
generated
vendored
|
@ -1,11 +1,13 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
|
||||||
// debugging type
|
// debugging type
|
||||||
// - has a Printf method to write the debug output
|
// - has a Printf method to write the debug output
|
||||||
type debugging bool
|
type debugging bool
|
||||||
|
|
||||||
// Enable controls debugging mode.
|
// Enable controls debugging mode.
|
||||||
|
@ -16,13 +18,13 @@ func (debug *debugging) Enable(b bool) {
|
||||||
// Printf writes debug output.
|
// Printf writes debug output.
|
||||||
func (debug debugging) Printf(format string, args ...interface{}) {
|
func (debug debugging) Printf(format string, args ...interface{}) {
|
||||||
if debug {
|
if debug {
|
||||||
logger.Printf(format, args...)
|
log.Printf(format, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintPacket dumps a packet.
|
// PrintPacket dumps a packet.
|
||||||
func (debug debugging) PrintPacket(packet *ber.Packet) {
|
func (debug debugging) PrintPacket(packet *ber.Packet) {
|
||||||
if debug {
|
if debug {
|
||||||
ber.WritePacket(logger.Writer(), packet)
|
ber.WritePacket(log.Writer(), packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
vendor/github.com/go-ldap/ldap/v3/del.go
generated
vendored
6
vendor/github.com/go-ldap/ldap/v3/del.go
generated
vendored
|
@ -1,7 +1,8 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"log"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,8 +53,7 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("ldap: unexpected response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
92
vendor/github.com/go-ldap/ldap/v3/dn.go
generated
vendored
92
vendor/github.com/go-ldap/ldap/v3/dn.go
generated
vendored
|
@ -5,7 +5,6 @@ import (
|
||||||
enchex "encoding/hex"
|
enchex "encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
|
@ -19,95 +18,16 @@ type AttributeTypeAndValue struct {
|
||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a normalized string representation of this attribute type and
|
|
||||||
// value pair which is the a lowercased join of the Type and Value with a "=".
|
|
||||||
func (a *AttributeTypeAndValue) String() string {
|
|
||||||
return strings.ToLower(a.Type) + "=" + a.encodeValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AttributeTypeAndValue) encodeValue() string {
|
|
||||||
// Normalize the value first.
|
|
||||||
// value := strings.ToLower(a.Value)
|
|
||||||
value := a.Value
|
|
||||||
|
|
||||||
encodedBuf := bytes.Buffer{}
|
|
||||||
|
|
||||||
escapeChar := func(c byte) {
|
|
||||||
encodedBuf.WriteByte('\\')
|
|
||||||
encodedBuf.WriteByte(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
escapeHex := func(c byte) {
|
|
||||||
encodedBuf.WriteByte('\\')
|
|
||||||
encodedBuf.WriteString(enchex.EncodeToString([]byte{c}))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(value); i++ {
|
|
||||||
char := value[i]
|
|
||||||
if i == 0 && char == ' ' || char == '#' {
|
|
||||||
// Special case leading space or number sign.
|
|
||||||
escapeChar(char)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i == len(value)-1 && char == ' ' {
|
|
||||||
// Special case trailing space.
|
|
||||||
escapeChar(char)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch char {
|
|
||||||
case '"', '+', ',', ';', '<', '>', '\\':
|
|
||||||
// Each of these special characters must be escaped.
|
|
||||||
escapeChar(char)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if char < ' ' || char > '~' {
|
|
||||||
// All special character escapes are handled first
|
|
||||||
// above. All bytes less than ASCII SPACE and all bytes
|
|
||||||
// greater than ASCII TILDE must be hex-escaped.
|
|
||||||
escapeHex(char)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any other character does not require escaping.
|
|
||||||
encodedBuf.WriteByte(char)
|
|
||||||
}
|
|
||||||
|
|
||||||
return encodedBuf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RelativeDN represents a relativeDistinguishedName from https://tools.ietf.org/html/rfc4514
|
// RelativeDN represents a relativeDistinguishedName from https://tools.ietf.org/html/rfc4514
|
||||||
type RelativeDN struct {
|
type RelativeDN struct {
|
||||||
Attributes []*AttributeTypeAndValue
|
Attributes []*AttributeTypeAndValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a normalized string representation of this relative DN which
|
|
||||||
// is the a join of all attributes (sorted in increasing order) with a "+".
|
|
||||||
func (r *RelativeDN) String() string {
|
|
||||||
attrs := make([]string, len(r.Attributes))
|
|
||||||
for i := range r.Attributes {
|
|
||||||
attrs[i] = r.Attributes[i].String()
|
|
||||||
}
|
|
||||||
sort.Strings(attrs)
|
|
||||||
return strings.Join(attrs, "+")
|
|
||||||
}
|
|
||||||
|
|
||||||
// DN represents a distinguishedName from https://tools.ietf.org/html/rfc4514
|
// DN represents a distinguishedName from https://tools.ietf.org/html/rfc4514
|
||||||
type DN struct {
|
type DN struct {
|
||||||
RDNs []*RelativeDN
|
RDNs []*RelativeDN
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a normalized string representation of this DN which is the
|
|
||||||
// join of all relative DNs with a ",".
|
|
||||||
func (d *DN) String() string {
|
|
||||||
rdns := make([]string, len(d.RDNs))
|
|
||||||
for i := range d.RDNs {
|
|
||||||
rdns[i] = d.RDNs[i].String()
|
|
||||||
}
|
|
||||||
return strings.Join(rdns, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDN returns a distinguishedName or an error.
|
// ParseDN returns a distinguishedName or an error.
|
||||||
// The function respects https://tools.ietf.org/html/rfc4514
|
// The function respects https://tools.ietf.org/html/rfc4514
|
||||||
func ParseDN(str string) (*DN, error) {
|
func ParseDN(str string) (*DN, error) {
|
||||||
|
@ -156,7 +76,7 @@ func ParseDN(str string) (*DN, error) {
|
||||||
case char == '\\':
|
case char == '\\':
|
||||||
unescapedTrailingSpaces = 0
|
unescapedTrailingSpaces = 0
|
||||||
escaping = true
|
escaping = true
|
||||||
case char == '=' && attribute.Type == "":
|
case char == '=':
|
||||||
attribute.Type = stringFromBuffer()
|
attribute.Type = stringFromBuffer()
|
||||||
// Special case: If the first character in the value is # the
|
// Special case: If the first character in the value is # the
|
||||||
// following data is BER encoded so we can just fast forward
|
// following data is BER encoded so we can just fast forward
|
||||||
|
@ -164,7 +84,7 @@ func ParseDN(str string) (*DN, error) {
|
||||||
if len(str) > i+1 && str[i+1] == '#' {
|
if len(str) > i+1 && str[i+1] == '#' {
|
||||||
i += 2
|
i += 2
|
||||||
index := strings.IndexAny(str[i:], ",+")
|
index := strings.IndexAny(str[i:], ",+")
|
||||||
var data string
|
data := str
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
data = str[i : i+index]
|
data = str[i : i+index]
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,7 +101,7 @@ func ParseDN(str string) (*DN, error) {
|
||||||
buffer.WriteString(packet.Data.String())
|
buffer.WriteString(packet.Data.String())
|
||||||
i += len(data) - 1
|
i += len(data) - 1
|
||||||
}
|
}
|
||||||
case char == ',' || char == '+' || char == ';':
|
case char == ',' || char == '+':
|
||||||
// We're done with this RDN or value, push it
|
// We're done with this RDN or value, push it
|
||||||
if len(attribute.Type) == 0 {
|
if len(attribute.Type) == 0 {
|
||||||
return nil, errors.New("incomplete type, value pair")
|
return nil, errors.New("incomplete type, value pair")
|
||||||
|
@ -189,7 +109,7 @@ func ParseDN(str string) (*DN, error) {
|
||||||
attribute.Value = stringFromBuffer()
|
attribute.Value = stringFromBuffer()
|
||||||
rdn.Attributes = append(rdn.Attributes, attribute)
|
rdn.Attributes = append(rdn.Attributes, attribute)
|
||||||
attribute = new(AttributeTypeAndValue)
|
attribute = new(AttributeTypeAndValue)
|
||||||
if char == ',' || char == ';' {
|
if char == ',' {
|
||||||
dn.RDNs = append(dn.RDNs, rdn)
|
dn.RDNs = append(dn.RDNs, rdn)
|
||||||
rdn = new(RelativeDN)
|
rdn = new(RelativeDN)
|
||||||
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
||||||
|
@ -286,7 +206,7 @@ func (a *AttributeTypeAndValue) Equal(other *AttributeTypeAndValue) bool {
|
||||||
return strings.EqualFold(a.Type, other.Type) && a.Value == other.Value
|
return strings.EqualFold(a.Type, other.Type) && a.Value == other.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualFold returns true if the DNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
// Equal returns true if the DNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
||||||
// Returns true if they have the same number of relative distinguished names
|
// Returns true if they have the same number of relative distinguished names
|
||||||
// and corresponding relative distinguished names (by position) are the same.
|
// and corresponding relative distinguished names (by position) are the same.
|
||||||
// Case of the attribute type and value is not significant
|
// Case of the attribute type and value is not significant
|
||||||
|
@ -318,7 +238,7 @@ func (d *DN) AncestorOfFold(other *DN) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualFold returns true if the RelativeDNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
// Equal returns true if the RelativeDNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
||||||
// Case of the attribute type is not significant
|
// Case of the attribute type is not significant
|
||||||
func (r *RelativeDN) EqualFold(other *RelativeDN) bool {
|
func (r *RelativeDN) EqualFold(other *RelativeDN) bool {
|
||||||
if len(r.Attributes) != len(other.Attributes) {
|
if len(r.Attributes) != len(other.Attributes) {
|
||||||
|
|
26
vendor/github.com/go-ldap/ldap/v3/error.go
generated
vendored
26
vendor/github.com/go-ldap/ldap/v3/error.go
generated
vendored
|
@ -192,8 +192,6 @@ func (e *Error) Error() string {
|
||||||
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Error) Unwrap() error { return e.Err }
|
|
||||||
|
|
||||||
// GetLDAPError creates an Error out of a BER packet representing a LDAPResult
|
// GetLDAPError creates an Error out of a BER packet representing a LDAPResult
|
||||||
// The return is an error object. It can be casted to a Error structure.
|
// The return is an error object. It can be casted to a Error structure.
|
||||||
// This function returns nil if resultCode in the LDAPResult sequence is success(0).
|
// This function returns nil if resultCode in the LDAPResult sequence is success(0).
|
||||||
|
@ -208,21 +206,15 @@ func GetLDAPError(packet *ber.Packet) error {
|
||||||
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet}
|
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet}
|
||||||
}
|
}
|
||||||
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
||||||
if ber.Type(response.Children[0].Tag) == ber.Type(ber.TagInteger) || ber.Type(response.Children[0].Tag) == ber.Type(ber.TagEnumerated) {
|
resultCode := uint16(response.Children[0].Value.(int64))
|
||||||
resultCode := uint16(response.Children[0].Value.(int64))
|
if resultCode == 0 { // No error
|
||||||
if resultCode == 0 { // No error
|
return nil
|
||||||
return nil
|
}
|
||||||
}
|
return &Error{
|
||||||
|
ResultCode: resultCode,
|
||||||
if ber.Type(response.Children[1].Tag) == ber.Type(ber.TagOctetString) &&
|
MatchedDN: response.Children[1].Value.(string),
|
||||||
ber.Type(response.Children[2].Tag) == ber.Type(ber.TagOctetString) {
|
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
|
||||||
return &Error{
|
Packet: packet,
|
||||||
ResultCode: resultCode,
|
|
||||||
MatchedDN: response.Children[1].Value.(string),
|
|
||||||
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
|
|
||||||
Packet: packet,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
vendor/github.com/go-ldap/ldap/v3/filter.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/filter.go
generated
vendored
|
@ -396,7 +396,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
|
|
||||||
case packet.Tag == FilterEqualityMatch && bytes.Equal(condition.Bytes(), _SymbolAny):
|
case packet.Tag == FilterEqualityMatch && bytes.Equal(condition.Bytes(), _SymbolAny):
|
||||||
packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute.String(), FilterMap[FilterPresent])
|
packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute.String(), FilterMap[FilterPresent])
|
||||||
case packet.Tag == FilterEqualityMatch && bytes.Contains(condition.Bytes(), _SymbolAny):
|
case packet.Tag == FilterEqualityMatch && bytes.Index(condition.Bytes(), _SymbolAny) > -1:
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute.String(), "Attribute"))
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute.String(), "Attribute"))
|
||||||
packet.Tag = FilterSubstrings
|
packet.Tag = FilterSubstrings
|
||||||
packet.Description = FilterMap[uint64(packet.Tag)]
|
packet.Description = FilterMap[uint64(packet.Tag)]
|
||||||
|
@ -438,6 +438,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
|
|
||||||
// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
|
// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
|
||||||
func decodeEscapedSymbols(src []byte) (string, error) {
|
func decodeEscapedSymbols(src []byte) (string, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
offset int
|
offset int
|
||||||
|
|
57
vendor/github.com/go-ldap/ldap/v3/ldap.go
generated
vendored
57
vendor/github.com/go-ldap/ldap/v3/ldap.go
generated
vendored
|
@ -3,9 +3,7 @@ package ldap
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
@ -32,7 +30,6 @@ const (
|
||||||
ApplicationSearchResultReference = 19
|
ApplicationSearchResultReference = 19
|
||||||
ApplicationExtendedRequest = 23
|
ApplicationExtendedRequest = 23
|
||||||
ApplicationExtendedResponse = 24
|
ApplicationExtendedResponse = 24
|
||||||
ApplicationIntermediateResponse = 25
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApplicationMap contains human readable descriptions of LDAP Application Codes
|
// ApplicationMap contains human readable descriptions of LDAP Application Codes
|
||||||
|
@ -57,7 +54,6 @@ var ApplicationMap = map[uint8]string{
|
||||||
ApplicationSearchResultReference: "Search Result Reference",
|
ApplicationSearchResultReference: "Search Result Reference",
|
||||||
ApplicationExtendedRequest: "Extended Request",
|
ApplicationExtendedRequest: "Extended Request",
|
||||||
ApplicationExtendedResponse: "Extended Response",
|
ApplicationExtendedResponse: "Extended Response",
|
||||||
ApplicationIntermediateResponse: "Intermediate Response",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10)
|
// Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10)
|
||||||
|
@ -86,13 +82,6 @@ var BeheraPasswordPolicyErrorMap = map[int8]string{
|
||||||
BeheraPasswordInHistory: "New password is in list of old passwords",
|
BeheraPasswordInHistory: "New password is in list of old passwords",
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = log.New(os.Stderr, "", log.LstdFlags)
|
|
||||||
|
|
||||||
// Logger allows clients to override the default logger
|
|
||||||
func Logger(l *log.Logger) {
|
|
||||||
logger = l
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds descriptions to an LDAP Response packet for debugging
|
// Adds descriptions to an LDAP Response packet for debugging
|
||||||
func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -232,18 +221,18 @@ func addControlDescriptions(packet *ber.Packet) error {
|
||||||
sequence := value.Children[0]
|
sequence := value.Children[0]
|
||||||
for _, child := range sequence.Children {
|
for _, child := range sequence.Children {
|
||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
// Warning
|
//Warning
|
||||||
warningPacket := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
val, err := ber.ParseInt64(warningPacket.Data.Bytes())
|
val, err := ber.ParseInt64(warningPacket.Data.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to decode data bytes: %s", err)
|
return fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
}
|
}
|
||||||
if warningPacket.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
// timeBeforeExpiration
|
//timeBeforeExpiration
|
||||||
value.Description += " (TimeBeforeExpiration)"
|
value.Description += " (TimeBeforeExpiration)"
|
||||||
warningPacket.Value = val
|
warningPacket.Value = val
|
||||||
} else if warningPacket.Tag == 1 {
|
} else if warningPacket.Tag == 1 {
|
||||||
// graceAuthNsRemaining
|
//graceAuthNsRemaining
|
||||||
value.Description += " (GraceAuthNsRemaining)"
|
value.Description += " (GraceAuthNsRemaining)"
|
||||||
warningPacket.Value = val
|
warningPacket.Value = val
|
||||||
}
|
}
|
||||||
|
@ -348,43 +337,3 @@ func EscapeFilter(filter string) string {
|
||||||
}
|
}
|
||||||
return string(buf)
|
return string(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeDN escapes distinguished names as described in RFC4514. Characters in the
|
|
||||||
// set `"+,;<>\` are escaped by prepending a backslash, which is also done for trailing
|
|
||||||
// spaces or a leading `#`. Null bytes are replaced with `\00`.
|
|
||||||
func EscapeDN(dn string) string {
|
|
||||||
if dn == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
builder := strings.Builder{}
|
|
||||||
|
|
||||||
for i, r := range dn {
|
|
||||||
// Escape leading and trailing spaces
|
|
||||||
if (i == 0 || i == len(dn)-1) && r == ' ' {
|
|
||||||
builder.WriteRune('\\')
|
|
||||||
builder.WriteRune(r)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape leading '#'
|
|
||||||
if i == 0 && r == '#' {
|
|
||||||
builder.WriteRune('\\')
|
|
||||||
builder.WriteRune(r)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape characters as defined in RFC4514
|
|
||||||
switch r {
|
|
||||||
case '"', '+', ',', ';', '<', '>', '\\':
|
|
||||||
builder.WriteRune('\\')
|
|
||||||
builder.WriteRune(r)
|
|
||||||
case '\x00': // Null byte may not be escaped by a leading backslash
|
|
||||||
builder.WriteString("\\00")
|
|
||||||
default:
|
|
||||||
builder.WriteRune(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.String()
|
|
||||||
}
|
|
||||||
|
|
10
vendor/github.com/go-ldap/ldap/v3/moddn.go
generated
vendored
10
vendor/github.com/go-ldap/ldap/v3/moddn.go
generated
vendored
|
@ -1,7 +1,8 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"log"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,9 +25,7 @@ type ModifyDNRequest struct {
|
||||||
// RDN of the given DN.
|
// RDN of the given DN.
|
||||||
//
|
//
|
||||||
// A call like
|
// A call like
|
||||||
//
|
// mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
|
||||||
// mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
|
|
||||||
//
|
|
||||||
// will setup the request to just rename uid=someone,dc=example,dc=org to
|
// will setup the request to just rename uid=someone,dc=example,dc=org to
|
||||||
// uid=newname,dc=example,dc=org.
|
// uid=newname,dc=example,dc=org.
|
||||||
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
|
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
|
||||||
|
@ -95,8 +94,7 @@ func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("ldap: unexpected response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
14
vendor/github.com/go-ldap/ldap/v3/modify.go
generated
vendored
14
vendor/github.com/go-ldap/ldap/v3/modify.go
generated
vendored
|
@ -2,7 +2,7 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"log"
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
@ -127,9 +127,8 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("ldap: unexpected response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +136,6 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
||||||
type ModifyResult struct {
|
type ModifyResult struct {
|
||||||
// Controls are the returned controls
|
// Controls are the returned controls
|
||||||
Controls []Control
|
Controls []Control
|
||||||
// Referral is the returned referral
|
|
||||||
Referral string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModifyWithResult performs the ModifyRequest and returns the result
|
// ModifyWithResult performs the ModifyRequest and returns the result
|
||||||
|
@ -161,10 +158,9 @@ func (l *Conn) ModifyWithResult(modifyRequest *ModifyRequest) (*ModifyResult, er
|
||||||
|
|
||||||
switch packet.Children[1].Tag {
|
switch packet.Children[1].Tag {
|
||||||
case ApplicationModifyResponse:
|
case ApplicationModifyResponse:
|
||||||
if err = GetLDAPError(packet); err != nil {
|
err := GetLDAPError(packet)
|
||||||
result.Referral = getReferral(err, packet)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
for _, child := range packet.Children[2].Children {
|
for _, child := range packet.Children[2].Children {
|
||||||
|
|
17
vendor/github.com/go-ldap/ldap/v3/passwdmodify.go
generated
vendored
17
vendor/github.com/go-ldap/ldap/v3/passwdmodify.go
generated
vendored
|
@ -70,6 +70,7 @@ func (req *PasswordModifyRequest) appendTo(envelope *ber.Packet) error {
|
||||||
// newPassword is the desired user's password. If empty the server can return
|
// newPassword is the desired user's password. If empty the server can return
|
||||||
// an error or generate a new password that will be available in the
|
// an error or generate a new password that will be available in the
|
||||||
// PasswordModifyResult.GeneratedPassword
|
// PasswordModifyResult.GeneratedPassword
|
||||||
|
//
|
||||||
func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest {
|
func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *PasswordModifyRequest {
|
||||||
return &PasswordModifyRequest{
|
return &PasswordModifyRequest{
|
||||||
UserIdentity: userIdentity,
|
UserIdentity: userIdentity,
|
||||||
|
@ -94,9 +95,15 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||||
result := &PasswordModifyResult{}
|
result := &PasswordModifyResult{}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationExtendedResponse {
|
if packet.Children[1].Tag == ApplicationExtendedResponse {
|
||||||
if err = GetLDAPError(packet); err != nil {
|
err := GetLDAPError(packet)
|
||||||
result.Referral = getReferral(err, packet)
|
if err != nil {
|
||||||
|
if IsErrorWithCode(err, LDAPResultReferral) {
|
||||||
|
for _, child := range packet.Children[1].Children {
|
||||||
|
if child.Tag == 3 {
|
||||||
|
result.Referral = child.Children[0].Value.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,10 +112,10 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||||
|
|
||||||
extendedResponse := packet.Children[1]
|
extendedResponse := packet.Children[1]
|
||||||
for _, child := range extendedResponse.Children {
|
for _, child := range extendedResponse.Children {
|
||||||
if child.Tag == ber.TagEmbeddedPDV {
|
if child.Tag == 11 {
|
||||||
passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
|
passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
|
||||||
if len(passwordModifyResponseValue.Children) == 1 {
|
if len(passwordModifyResponseValue.Children) == 1 {
|
||||||
if passwordModifyResponseValue.Children[0].Tag == ber.TagEOC {
|
if passwordModifyResponseValue.Children[0].Tag == 0 {
|
||||||
result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
|
result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
vendor/github.com/go-ldap/ldap/v3/request.go
generated
vendored
41
vendor/github.com/go-ldap/ldap/v3/request.go
generated
vendored
|
@ -9,8 +9,7 @@ import (
|
||||||
var (
|
var (
|
||||||
errRespChanClosed = errors.New("ldap: response channel closed")
|
errRespChanClosed = errors.New("ldap: response channel closed")
|
||||||
errCouldNotRetMsg = errors.New("ldap: could not retrieve message")
|
errCouldNotRetMsg = errors.New("ldap: could not retrieve message")
|
||||||
// ErrNilConnection is returned if doRequest is called with a nil connection.
|
ErrNilConnection = errors.New("ldap: conn is nil, expected net.Conn")
|
||||||
ErrNilConnection = errors.New("ldap: conn is nil, expected net.Conn")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type request interface {
|
type request interface {
|
||||||
|
@ -70,41 +69,3 @@ func (l *Conn) readPacket(msgCtx *messageContext) (*ber.Packet, error) {
|
||||||
}
|
}
|
||||||
return packet, nil
|
return packet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReferral(err error, packet *ber.Packet) (referral string) {
|
|
||||||
if !IsErrorWithCode(err, LDAPResultReferral) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(packet.Children) < 2 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// The packet Tag itself (of child 2) is generally a ber.TagObjectDescriptor with referrals however OpenLDAP
|
|
||||||
// seemingly returns a ber.Tag.GeneralizedTime. Every currently tested LDAP server which returns referrals returns
|
|
||||||
// an ASN.1 BER packet with the Type of ber.TypeConstructed and Class of ber.ClassApplication however. Thus this
|
|
||||||
// check expressly checks these fields instead.
|
|
||||||
//
|
|
||||||
// Related Issues:
|
|
||||||
// - https://github.com/authelia/authelia/issues/4199 (downstream)
|
|
||||||
if len(packet.Children[1].Children) == 0 || (packet.Children[1].TagType != ber.TypeConstructed || packet.Children[1].ClassType != ber.ClassApplication) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
for _, child := range packet.Children[1].Children {
|
|
||||||
// The referral URI itself should be contained within a child which has a Tag of ber.BitString or
|
|
||||||
// ber.TagPrintableString, and the Type of ber.TypeConstructed and the Class of ClassContext. As soon as any of
|
|
||||||
// these conditions is not true we can skip this child.
|
|
||||||
if (child.Tag != ber.TagBitString && child.Tag != ber.TagPrintableString) || child.TagType != ber.TypeConstructed || child.ClassType != ber.ClassContext {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if referral, ok = child.Children[0].Value.(string); ok {
|
|
||||||
return referral
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
207
vendor/github.com/go-ldap/ldap/v3/response.go
generated
vendored
207
vendor/github.com/go-ldap/ldap/v3/response.go
generated
vendored
|
@ -1,207 +0,0 @@
|
||||||
package ldap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Response defines an interface to get data from an LDAP server
|
|
||||||
type Response interface {
|
|
||||||
Entry() *Entry
|
|
||||||
Referral() string
|
|
||||||
Controls() []Control
|
|
||||||
Err() error
|
|
||||||
Next() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type searchResponse struct {
|
|
||||||
conn *Conn
|
|
||||||
ch chan *SearchSingleResult
|
|
||||||
|
|
||||||
entry *Entry
|
|
||||||
referral string
|
|
||||||
controls []Control
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry returns an entry from the given search request
|
|
||||||
func (r *searchResponse) Entry() *Entry {
|
|
||||||
return r.entry
|
|
||||||
}
|
|
||||||
|
|
||||||
// Referral returns a referral from the given search request
|
|
||||||
func (r *searchResponse) Referral() string {
|
|
||||||
return r.referral
|
|
||||||
}
|
|
||||||
|
|
||||||
// Controls returns controls from the given search request
|
|
||||||
func (r *searchResponse) Controls() []Control {
|
|
||||||
return r.controls
|
|
||||||
}
|
|
||||||
|
|
||||||
// Err returns an error when the given search request was failed
|
|
||||||
func (r *searchResponse) Err() error {
|
|
||||||
return r.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns whether next data exist or not
|
|
||||||
func (r *searchResponse) Next() bool {
|
|
||||||
res, ok := <-r.ch
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if res == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
r.err = res.Error
|
|
||||||
if r.err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
r.entry = res.Entry
|
|
||||||
r.referral = res.Referral
|
|
||||||
r.controls = res.Controls
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest) {
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
close(r.ch)
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
r.conn.err = fmt.Errorf("ldap: recovered panic in searchResponse: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if r.conn.IsClosing() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, r.conn.nextMessageID(), "MessageID"))
|
|
||||||
// encode search request
|
|
||||||
err := searchRequest.appendTo(packet)
|
|
||||||
if err != nil {
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.conn.Debug.PrintPacket(packet)
|
|
||||||
|
|
||||||
msgCtx, err := r.conn.sendMessage(packet)
|
|
||||||
if err != nil {
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer r.conn.finishMessage(msgCtx)
|
|
||||||
|
|
||||||
foundSearchSingleResultDone := false
|
|
||||||
for !foundSearchSingleResultDone {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
r.conn.Debug.Printf("%d: %s", msgCtx.id, ctx.Err().Error())
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
r.conn.Debug.Printf("%d: waiting for response", msgCtx.id)
|
|
||||||
packetResponse, ok := <-msgCtx.responses
|
|
||||||
if !ok {
|
|
||||||
err := NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
packet, err = packetResponse.ReadPacket()
|
|
||||||
r.conn.Debug.Printf("%d: got response %p", msgCtx.id, packet)
|
|
||||||
if err != nil {
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.conn.Debug {
|
|
||||||
if err := addLDAPDescriptions(packet); err != nil {
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ber.PrintPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch packet.Children[1].Tag {
|
|
||||||
case ApplicationSearchResultEntry:
|
|
||||||
result := &SearchSingleResult{
|
|
||||||
Entry: &Entry{
|
|
||||||
DN: packet.Children[1].Children[0].Value.(string),
|
|
||||||
Attributes: unpackAttributes(packet.Children[1].Children[1].Children),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if len(packet.Children) != 3 {
|
|
||||||
r.ch <- result
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
decoded, err := DecodeControl(packet.Children[2].Children[0])
|
|
||||||
if err != nil {
|
|
||||||
werr := fmt.Errorf("failed to decode search result entry: %w", err)
|
|
||||||
result.Error = werr
|
|
||||||
r.ch <- result
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result.Controls = append(result.Controls, decoded)
|
|
||||||
r.ch <- result
|
|
||||||
|
|
||||||
case ApplicationSearchResultDone:
|
|
||||||
if err := GetLDAPError(packet); err != nil {
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(packet.Children) == 3 {
|
|
||||||
result := &SearchSingleResult{}
|
|
||||||
for _, child := range packet.Children[2].Children {
|
|
||||||
decodedChild, err := DecodeControl(child)
|
|
||||||
if err != nil {
|
|
||||||
werr := fmt.Errorf("failed to decode child control: %w", err)
|
|
||||||
r.ch <- &SearchSingleResult{Error: werr}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result.Controls = append(result.Controls, decodedChild)
|
|
||||||
}
|
|
||||||
r.ch <- result
|
|
||||||
}
|
|
||||||
foundSearchSingleResultDone = true
|
|
||||||
|
|
||||||
case ApplicationSearchResultReference:
|
|
||||||
ref := packet.Children[1].Children[0].Value.(string)
|
|
||||||
r.ch <- &SearchSingleResult{Referral: ref}
|
|
||||||
|
|
||||||
case ApplicationIntermediateResponse:
|
|
||||||
decoded, err := DecodeControl(packet.Children[1])
|
|
||||||
if err != nil {
|
|
||||||
werr := fmt.Errorf("failed to decode intermediate response: %w", err)
|
|
||||||
r.ch <- &SearchSingleResult{Error: werr}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result := &SearchSingleResult{}
|
|
||||||
result.Controls = append(result.Controls, decoded)
|
|
||||||
r.ch <- result
|
|
||||||
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("unknown tag: %d", packet.Children[1].Tag)
|
|
||||||
r.ch <- &SearchSingleResult{Error: err}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.conn.Debug.Printf("%d: returning", msgCtx.id)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSearchResponse(conn *Conn, bufferSize int) *searchResponse {
|
|
||||||
var ch chan *SearchSingleResult
|
|
||||||
if bufferSize > 0 {
|
|
||||||
ch = make(chan *SearchSingleResult, bufferSize)
|
|
||||||
} else {
|
|
||||||
ch = make(chan *SearchSingleResult)
|
|
||||||
}
|
|
||||||
return &searchResponse{
|
|
||||||
conn: conn,
|
|
||||||
ch: ch,
|
|
||||||
}
|
|
||||||
}
|
|
303
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
303
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
|
@ -1,14 +1,10 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
@ -165,155 +161,6 @@ func (e *Entry) PrettyPrint(indent int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe the tag to use for struct field tags
|
|
||||||
const decoderTagName = "ldap"
|
|
||||||
|
|
||||||
// readTag will read the reflect.StructField value for
|
|
||||||
// the key defined in decoderTagName. If omitempty is
|
|
||||||
// specified, the field may not be filled.
|
|
||||||
func readTag(f reflect.StructField) (string, bool) {
|
|
||||||
val, ok := f.Tag.Lookup(decoderTagName)
|
|
||||||
if !ok {
|
|
||||||
return f.Name, false
|
|
||||||
}
|
|
||||||
opts := strings.Split(val, ",")
|
|
||||||
omit := false
|
|
||||||
if len(opts) == 2 {
|
|
||||||
omit = opts[1] == "omitempty"
|
|
||||||
}
|
|
||||||
return opts[0], omit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal parses the Entry in the value pointed to by i
|
|
||||||
//
|
|
||||||
// Currently, this methods only supports struct fields of type
|
|
||||||
// string, []string, int, int64, []byte, *DN, []*DN or time.Time. Other field types
|
|
||||||
// will not be regarded. If the field type is a string or int but multiple
|
|
||||||
// attribute values are returned, the first value will be used to fill the field.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// type UserEntry struct {
|
|
||||||
// // Fields with the tag key `dn` are automatically filled with the
|
|
||||||
// // objects distinguishedName. This can be used multiple times.
|
|
||||||
// DN string `ldap:"dn"`
|
|
||||||
//
|
|
||||||
// // This field will be filled with the attribute value for
|
|
||||||
// // userPrincipalName. An attribute can be read into a struct field
|
|
||||||
// // multiple times. Missing attributes will not result in an error.
|
|
||||||
// UserPrincipalName string `ldap:"userPrincipalName"`
|
|
||||||
//
|
|
||||||
// // memberOf may have multiple values. If you don't
|
|
||||||
// // know the amount of attribute values at runtime, use a string array.
|
|
||||||
// MemberOf []string `ldap:"memberOf"`
|
|
||||||
//
|
|
||||||
// // ID is an integer value, it will fail unmarshaling when the given
|
|
||||||
// // attribute value cannot be parsed into an integer.
|
|
||||||
// ID int `ldap:"id"`
|
|
||||||
//
|
|
||||||
// // LongID is similar to ID but uses an int64 instead.
|
|
||||||
// LongID int64 `ldap:"longId"`
|
|
||||||
//
|
|
||||||
// // Data is similar to MemberOf a slice containing all attribute
|
|
||||||
// // values.
|
|
||||||
// Data []byte `ldap:"data"`
|
|
||||||
//
|
|
||||||
// // Time is parsed with the generalizedTime spec into a time.Time
|
|
||||||
// Created time.Time `ldap:"createdTimestamp"`
|
|
||||||
//
|
|
||||||
// // *DN is parsed with the ParseDN
|
|
||||||
// Owner *ldap.DN `ldap:"owner"`
|
|
||||||
//
|
|
||||||
// // []*DN is parsed with the ParseDN
|
|
||||||
// Children []*ldap.DN `ldap:"children"`
|
|
||||||
//
|
|
||||||
// // This won't work, as the field is not of type string. For this
|
|
||||||
// // to work, you'll have to temporarily store the result in string
|
|
||||||
// // (or string array) and convert it to the desired type afterwards.
|
|
||||||
// UserAccountControl uint32 `ldap:"userPrincipalName"`
|
|
||||||
// }
|
|
||||||
// user := UserEntry{}
|
|
||||||
//
|
|
||||||
// if err := result.Unmarshal(&user); err != nil {
|
|
||||||
// // ...
|
|
||||||
// }
|
|
||||||
func (e *Entry) Unmarshal(i interface{}) (err error) {
|
|
||||||
// Make sure it's a ptr
|
|
||||||
if vo := reflect.ValueOf(i).Kind(); vo != reflect.Ptr {
|
|
||||||
return fmt.Errorf("ldap: cannot use %s, expected pointer to a struct", vo)
|
|
||||||
}
|
|
||||||
|
|
||||||
sv, st := reflect.ValueOf(i).Elem(), reflect.TypeOf(i).Elem()
|
|
||||||
// Make sure it's pointing to a struct
|
|
||||||
if sv.Kind() != reflect.Struct {
|
|
||||||
return fmt.Errorf("ldap: expected pointer to a struct, got %s", sv.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
for n := 0; n < st.NumField(); n++ {
|
|
||||||
// Holds struct field value and type
|
|
||||||
fv, ft := sv.Field(n), st.Field(n)
|
|
||||||
|
|
||||||
// skip unexported fields
|
|
||||||
if ft.PkgPath != "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// omitempty can be safely discarded, as it's not needed when unmarshalling
|
|
||||||
fieldTag, _ := readTag(ft)
|
|
||||||
|
|
||||||
// Fill the field with the distinguishedName if the tag key is `dn`
|
|
||||||
if fieldTag == "dn" {
|
|
||||||
fv.SetString(e.DN)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values := e.GetAttributeValues(fieldTag)
|
|
||||||
if len(values) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fv.Interface().(type) {
|
|
||||||
case []string:
|
|
||||||
for _, item := range values {
|
|
||||||
fv.Set(reflect.Append(fv, reflect.ValueOf(item)))
|
|
||||||
}
|
|
||||||
case string:
|
|
||||||
fv.SetString(values[0])
|
|
||||||
case []byte:
|
|
||||||
fv.SetBytes([]byte(values[0]))
|
|
||||||
case int, int64:
|
|
||||||
intVal, err := strconv.ParseInt(values[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ldap: could not parse value '%s' into int field", values[0])
|
|
||||||
}
|
|
||||||
fv.SetInt(intVal)
|
|
||||||
case time.Time:
|
|
||||||
t, err := ber.ParseGeneralizedTime([]byte(values[0]))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ldap: could not parse value '%s' into time.Time field", values[0])
|
|
||||||
}
|
|
||||||
fv.Set(reflect.ValueOf(t))
|
|
||||||
case *DN:
|
|
||||||
dn, err := ParseDN(values[0])
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", values[0])
|
|
||||||
}
|
|
||||||
fv.Set(reflect.ValueOf(dn))
|
|
||||||
case []*DN:
|
|
||||||
for _, item := range values {
|
|
||||||
dn, err := ParseDN(item)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", item)
|
|
||||||
}
|
|
||||||
fv.Set(reflect.Append(fv, reflect.ValueOf(dn)))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("ldap: expected field to be of type string, []string, int, int64, []byte, *DN, []*DN or time.Time, got %v", ft.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
|
// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
|
||||||
func NewEntryAttribute(name string, values []string) *EntryAttribute {
|
func NewEntryAttribute(name string, values []string) *EntryAttribute {
|
||||||
var bytes [][]byte
|
var bytes [][]byte
|
||||||
|
@ -371,35 +218,6 @@ func (s *SearchResult) PrettyPrint(indent int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// appendTo appends all entries of `s` to `r`
|
|
||||||
func (s *SearchResult) appendTo(r *SearchResult) {
|
|
||||||
r.Entries = append(r.Entries, s.Entries...)
|
|
||||||
r.Referrals = append(r.Referrals, s.Referrals...)
|
|
||||||
r.Controls = append(r.Controls, s.Controls...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchSingleResult holds the server's single entry response to a search request
|
|
||||||
type SearchSingleResult struct {
|
|
||||||
// Entry is the returned entry
|
|
||||||
Entry *Entry
|
|
||||||
// Referral is the returned referral
|
|
||||||
Referral string
|
|
||||||
// Controls are the returned controls
|
|
||||||
Controls []Control
|
|
||||||
// Error is set when the search request was failed
|
|
||||||
Error error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print outputs a human-readable description
|
|
||||||
func (s *SearchSingleResult) Print() {
|
|
||||||
s.Entry.Print()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrint outputs a human-readable description with indenting
|
|
||||||
func (s *SearchSingleResult) PrettyPrint(indent int) {
|
|
||||||
s.Entry.PrettyPrint(indent)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchRequest represents a search request to send to the server
|
// SearchRequest represents a search request to send to the server
|
||||||
type SearchRequest struct {
|
type SearchRequest struct {
|
||||||
BaseDN string
|
BaseDN string
|
||||||
|
@ -467,11 +285,10 @@ func NewSearchRequest(
|
||||||
// SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the
|
// SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the
|
||||||
// search request. All paged LDAP query responses will be buffered and the final result will be returned atomically.
|
// search request. All paged LDAP query responses will be buffered and the final result will be returned atomically.
|
||||||
// The following four cases are possible given the arguments:
|
// The following four cases are possible given the arguments:
|
||||||
// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size
|
// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size
|
||||||
// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries
|
// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries
|
||||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request
|
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request
|
||||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries
|
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries
|
||||||
//
|
|
||||||
// A requested pagingSize of 0 is interpreted as no limit by LDAP servers.
|
// A requested pagingSize of 0 is interpreted as no limit by LDAP servers.
|
||||||
func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
|
func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
|
||||||
var pagingControl *ControlPaging
|
var pagingControl *ControlPaging
|
||||||
|
@ -494,19 +311,23 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
||||||
searchResult := new(SearchResult)
|
searchResult := new(SearchResult)
|
||||||
for {
|
for {
|
||||||
result, err := l.Search(searchRequest)
|
result, err := l.Search(searchRequest)
|
||||||
if result != nil {
|
l.Debug.Printf("Looking for Paging Control...")
|
||||||
result.appendTo(searchResult)
|
|
||||||
} else {
|
|
||||||
if err == nil {
|
|
||||||
// We have to do this beautifulness in case something absolutely strange happens, which
|
|
||||||
// should only occur in case there is no packet, but also no error.
|
|
||||||
return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If an error occurred, all results that have been received so far will be returned
|
|
||||||
return searchResult, err
|
return searchResult, err
|
||||||
}
|
}
|
||||||
|
if result == nil {
|
||||||
|
return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range result.Entries {
|
||||||
|
searchResult.Entries = append(searchResult.Entries, entry)
|
||||||
|
}
|
||||||
|
for _, referral := range result.Referrals {
|
||||||
|
searchResult.Referrals = append(searchResult.Referrals, referral)
|
||||||
|
}
|
||||||
|
for _, control := range result.Controls {
|
||||||
|
searchResult.Controls = append(searchResult.Controls, control)
|
||||||
|
}
|
||||||
|
|
||||||
l.Debug.Printf("Looking for Paging Control...")
|
l.Debug.Printf("Looking for Paging Control...")
|
||||||
pagingResult := FindControl(result.Controls, ControlTypePaging)
|
pagingResult := FindControl(result.Controls, ControlTypePaging)
|
||||||
|
@ -528,9 +349,7 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
||||||
if pagingControl != nil {
|
if pagingControl != nil {
|
||||||
l.Debug.Printf("Abandoning Paging...")
|
l.Debug.Printf("Abandoning Paging...")
|
||||||
pagingControl.PagingSize = 0
|
pagingControl.PagingSize = 0
|
||||||
if _, err := l.Search(searchRequest); err != nil {
|
l.Search(searchRequest)
|
||||||
return searchResult, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchResult, nil
|
return searchResult, nil
|
||||||
|
@ -547,8 +366,7 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||||
result := &SearchResult{
|
result := &SearchResult{
|
||||||
Entries: make([]*Entry, 0),
|
Entries: make([]*Entry, 0),
|
||||||
Referrals: make([]string, 0),
|
Referrals: make([]string, 0),
|
||||||
Controls: make([]Control, 0),
|
Controls: make([]Control, 0)}
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
packet, err := l.readPacket(msgCtx)
|
packet, err := l.readPacket(msgCtx)
|
||||||
|
@ -584,32 +402,6 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchAsync performs a search request and returns all search results asynchronously.
|
|
||||||
// This means you get all results until an error happens (or the search successfully finished),
|
|
||||||
// e.g. for size / time limited requests all are recieved until the limit is reached.
|
|
||||||
// To stop the search, call cancel function of the context.
|
|
||||||
func (l *Conn) SearchAsync(
|
|
||||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int) Response {
|
|
||||||
r := newSearchResponse(l, bufferSize)
|
|
||||||
r.start(ctx, searchRequest)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syncrepl is a short name for LDAP Sync Replication engine that works on the
|
|
||||||
// consumer-side. This can perform a persistent search and returns an entry
|
|
||||||
// when the entry is updated on the server side.
|
|
||||||
// To stop the search, call cancel function of the context.
|
|
||||||
func (l *Conn) Syncrepl(
|
|
||||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int,
|
|
||||||
mode ControlSyncRequestMode, cookie []byte, reloadHint bool,
|
|
||||||
) Response {
|
|
||||||
control := NewControlSyncRequest(mode, cookie, reloadHint)
|
|
||||||
searchRequest.Controls = append(searchRequest.Controls, control)
|
|
||||||
r := newSearchResponse(l, bufferSize)
|
|
||||||
r.start(ctx, searchRequest)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpackAttributes will extract all given LDAP attributes and it's values
|
// unpackAttributes will extract all given LDAP attributes and it's values
|
||||||
// from the ber.Packet
|
// from the ber.Packet
|
||||||
func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
|
func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
|
||||||
|
@ -633,58 +425,3 @@ func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirSync does a Search with dirSync Control.
|
|
||||||
func (l *Conn) DirSync(
|
|
||||||
searchRequest *SearchRequest, flags int64, maxAttrCount int64, cookie []byte,
|
|
||||||
) (*SearchResult, error) {
|
|
||||||
control := FindControl(searchRequest.Controls, ControlTypeDirSync)
|
|
||||||
if control == nil {
|
|
||||||
c := NewRequestControlDirSync(flags, maxAttrCount, cookie)
|
|
||||||
searchRequest.Controls = append(searchRequest.Controls, c)
|
|
||||||
} else {
|
|
||||||
c := control.(*ControlDirSync)
|
|
||||||
if c.Flags != flags {
|
|
||||||
return nil, fmt.Errorf("flags given in search request (%d) conflicts with flags given in search call (%d)", c.Flags, flags)
|
|
||||||
}
|
|
||||||
if c.MaxAttrCount != maxAttrCount {
|
|
||||||
return nil, fmt.Errorf("MaxAttrCnt given in search request (%d) conflicts with maxAttrCount given in search call (%d)", c.MaxAttrCount, maxAttrCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
searchResult, err := l.Search(searchRequest)
|
|
||||||
l.Debug.Printf("Looking for result...")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if searchResult == nil {
|
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Debug.Printf("Looking for DirSync Control...")
|
|
||||||
resultControl := FindControl(searchResult.Controls, ControlTypeDirSync)
|
|
||||||
if resultControl == nil {
|
|
||||||
l.Debug.Printf("Could not find dirSyncControl control. Breaking...")
|
|
||||||
return searchResult, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cookie = resultControl.(*ControlDirSync).Cookie
|
|
||||||
if len(cookie) == 0 {
|
|
||||||
l.Debug.Printf("Could not find cookie. Breaking...")
|
|
||||||
return searchResult, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return searchResult, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DirSyncDirSyncAsync performs a search request and returns all search results
|
|
||||||
// asynchronously. This is efficient when the server returns lots of entries.
|
|
||||||
func (l *Conn) DirSyncAsync(
|
|
||||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int,
|
|
||||||
flags, maxAttrCount int64, cookie []byte,
|
|
||||||
) Response {
|
|
||||||
control := NewRequestControlDirSync(flags, maxAttrCount, cookie)
|
|
||||||
searchRequest.Controls = append(searchRequest.Controls, control)
|
|
||||||
r := newSearchResponse(l, bufferSize)
|
|
||||||
r.start(ctx, searchRequest)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
1
vendor/github.com/go-ldap/ldap/v3/unbind.go
generated
vendored
1
vendor/github.com/go-ldap/ldap/v3/unbind.go
generated
vendored
|
@ -6,7 +6,6 @@ import (
|
||||||
ber "github.com/go-asn1-ber/asn1-ber"
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrConnUnbound is returned when Unbind is called on an already closing connection.
|
|
||||||
var ErrConnUnbound = NewError(ErrorNetwork, errors.New("ldap: connection is closed"))
|
var ErrConnUnbound = NewError(ErrorNetwork, errors.New("ldap: connection is closed"))
|
||||||
|
|
||||||
type unbindRequest struct{}
|
type unbindRequest struct{}
|
||||||
|
|
10
vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
10
vendor/github.com/google/uuid/CHANGELOG.md
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
# Changelog
|
|
||||||
|
|
||||||
## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0))
|
|
||||||
|
|
||||||
## Changelog
|
|
26
vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
26
vendor/github.com/google/uuid/CONTRIBUTING.md
generated
vendored
|
@ -1,26 +0,0 @@
|
||||||
# How to contribute
|
|
||||||
|
|
||||||
We definitely welcome patches and contribution to this project!
|
|
||||||
|
|
||||||
### Tips
|
|
||||||
|
|
||||||
Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org).
|
|
||||||
|
|
||||||
Always try to include a test case! If it is not possible or not necessary,
|
|
||||||
please explain why in the pull request description.
|
|
||||||
|
|
||||||
### Releasing
|
|
||||||
|
|
||||||
Commits that would precipitate a SemVer change, as desrcibed in the Conventional
|
|
||||||
Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action)
|
|
||||||
to create a release candidate pull request. Once submitted, `release-please`
|
|
||||||
will create a release.
|
|
||||||
|
|
||||||
For tips on how to work with `release-please`, see its documentation.
|
|
||||||
|
|
||||||
### Legal requirements
|
|
||||||
|
|
||||||
In order to protect both you and ourselves, you will need to sign the
|
|
||||||
[Contributor License Agreement](https://cla.developers.google.com/clas).
|
|
||||||
|
|
||||||
You may have already signed it for other Google projects.
|
|
9
vendor/github.com/google/uuid/CONTRIBUTORS
generated
vendored
9
vendor/github.com/google/uuid/CONTRIBUTORS
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
Paul Borman <borman@google.com>
|
|
||||||
bmatsuo
|
|
||||||
shawnps
|
|
||||||
theory
|
|
||||||
jboverfelt
|
|
||||||
dsymonds
|
|
||||||
cd1
|
|
||||||
wallclockbuilder
|
|
||||||
dansouza
|
|
27
vendor/github.com/google/uuid/LICENSE
generated
vendored
27
vendor/github.com/google/uuid/LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Copyright (c) 2009,2014 Google Inc. 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.
|
|
21
vendor/github.com/google/uuid/README.md
generated
vendored
21
vendor/github.com/google/uuid/README.md
generated
vendored
|
@ -1,21 +0,0 @@
|
||||||
# uuid
|
|
||||||
The uuid package generates and inspects UUIDs based on
|
|
||||||
[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122)
|
|
||||||
and DCE 1.1: Authentication and Security Services.
|
|
||||||
|
|
||||||
This package is based on the github.com/pborman/uuid package (previously named
|
|
||||||
code.google.com/p/go-uuid). It differs from these earlier packages in that
|
|
||||||
a UUID is a 16 byte array rather than a byte slice. One loss due to this
|
|
||||||
change is the ability to represent an invalid UUID (vs a NIL UUID).
|
|
||||||
|
|
||||||
###### Install
|
|
||||||
```sh
|
|
||||||
go get github.com/google/uuid
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Documentation
|
|
||||||
[](https://pkg.go.dev/github.com/google/uuid)
|
|
||||||
|
|
||||||
Full `go doc` style documentation for the package can be viewed online without
|
|
||||||
installing this package by using the GoDoc site here:
|
|
||||||
http://pkg.go.dev/github.com/google/uuid
|
|
80
vendor/github.com/google/uuid/dce.go
generated
vendored
80
vendor/github.com/google/uuid/dce.go
generated
vendored
|
@ -1,80 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Domain represents a Version 2 domain
|
|
||||||
type Domain byte
|
|
||||||
|
|
||||||
// Domain constants for DCE Security (Version 2) UUIDs.
|
|
||||||
const (
|
|
||||||
Person = Domain(0)
|
|
||||||
Group = Domain(1)
|
|
||||||
Org = Domain(2)
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDCESecurity returns a DCE Security (Version 2) UUID.
|
|
||||||
//
|
|
||||||
// The domain should be one of Person, Group or Org.
|
|
||||||
// On a POSIX system the id should be the users UID for the Person
|
|
||||||
// domain and the users GID for the Group. The meaning of id for
|
|
||||||
// the domain Org or on non-POSIX systems is site defined.
|
|
||||||
//
|
|
||||||
// For a given domain/id pair the same token may be returned for up to
|
|
||||||
// 7 minutes and 10 seconds.
|
|
||||||
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
|
|
||||||
uuid, err := NewUUID()
|
|
||||||
if err == nil {
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
|
|
||||||
uuid[9] = byte(domain)
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], id)
|
|
||||||
}
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
|
||||||
// domain with the id returned by os.Getuid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
func NewDCEPerson() (UUID, error) {
|
|
||||||
return NewDCESecurity(Person, uint32(os.Getuid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
|
||||||
// domain with the id returned by os.Getgid.
|
|
||||||
//
|
|
||||||
// NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
func NewDCEGroup() (UUID, error) {
|
|
||||||
return NewDCESecurity(Group, uint32(os.Getgid()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain returns the domain for a Version 2 UUID. Domains are only defined
|
|
||||||
// for Version 2 UUIDs.
|
|
||||||
func (uuid UUID) Domain() Domain {
|
|
||||||
return Domain(uuid[9])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
|
|
||||||
// UUIDs.
|
|
||||||
func (uuid UUID) ID() uint32 {
|
|
||||||
return binary.BigEndian.Uint32(uuid[0:4])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Domain) String() string {
|
|
||||||
switch d {
|
|
||||||
case Person:
|
|
||||||
return "Person"
|
|
||||||
case Group:
|
|
||||||
return "Group"
|
|
||||||
case Org:
|
|
||||||
return "Org"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("Domain%d", int(d))
|
|
||||||
}
|
|
12
vendor/github.com/google/uuid/doc.go
generated
vendored
12
vendor/github.com/google/uuid/doc.go
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package uuid generates and inspects UUIDs.
|
|
||||||
//
|
|
||||||
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
|
|
||||||
// Services.
|
|
||||||
//
|
|
||||||
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
|
|
||||||
// maps or compared directly.
|
|
||||||
package uuid
|
|
53
vendor/github.com/google/uuid/hash.go
generated
vendored
53
vendor/github.com/google/uuid/hash.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"hash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Well known namespace IDs and UUIDs
|
|
||||||
var (
|
|
||||||
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
|
|
||||||
Nil UUID // empty UUID, all zeros
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHash returns a new UUID derived from the hash of space concatenated with
|
|
||||||
// data generated by h. The hash should be at least 16 byte in length. The
|
|
||||||
// first 16 bytes of the hash are used to form the UUID. The version of the
|
|
||||||
// UUID will be the lower 4 bits of version. NewHash is used to implement
|
|
||||||
// NewMD5 and NewSHA1.
|
|
||||||
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
|
||||||
h.Reset()
|
|
||||||
h.Write(space[:]) //nolint:errcheck
|
|
||||||
h.Write(data) //nolint:errcheck
|
|
||||||
s := h.Sum(nil)
|
|
||||||
var uuid UUID
|
|
||||||
copy(uuid[:], s)
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(md5.New(), space, data, 3)
|
|
||||||
func NewMD5(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(md5.New(), space, data, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
|
||||||
// supplied name space and data. It is the same as calling:
|
|
||||||
//
|
|
||||||
// NewHash(sha1.New(), space, data, 5)
|
|
||||||
func NewSHA1(space UUID, data []byte) UUID {
|
|
||||||
return NewHash(sha1.New(), space, data, 5)
|
|
||||||
}
|
|
38
vendor/github.com/google/uuid/marshal.go
generated
vendored
38
vendor/github.com/google/uuid/marshal.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
|
||||||
func (uuid UUID) MarshalText() ([]byte, error) {
|
|
||||||
var js [36]byte
|
|
||||||
encodeHex(js[:], uuid)
|
|
||||||
return js[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalText(data []byte) error {
|
|
||||||
id, err := ParseBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*uuid = id
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary implements encoding.BinaryMarshaler.
|
|
||||||
func (uuid UUID) MarshalBinary() ([]byte, error) {
|
|
||||||
return uuid[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
|
||||||
func (uuid *UUID) UnmarshalBinary(data []byte) error {
|
|
||||||
if len(data) != 16 {
|
|
||||||
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
|
|
||||||
}
|
|
||||||
copy(uuid[:], data)
|
|
||||||
return nil
|
|
||||||
}
|
|
90
vendor/github.com/google/uuid/node.go
generated
vendored
90
vendor/github.com/google/uuid/node.go
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
nodeMu sync.Mutex
|
|
||||||
ifname string // name of interface being used
|
|
||||||
nodeID [6]byte // hardware for version 1 UUIDs
|
|
||||||
zeroID [6]byte // nodeID with only 0's
|
|
||||||
)
|
|
||||||
|
|
||||||
// NodeInterface returns the name of the interface from which the NodeID was
|
|
||||||
// derived. The interface "user" is returned if the NodeID was set by
|
|
||||||
// SetNodeID.
|
|
||||||
func NodeInterface() string {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return ifname
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
|
|
||||||
// If name is "" then the first usable interface found will be used or a random
|
|
||||||
// Node ID will be generated. If a named interface cannot be found then false
|
|
||||||
// is returned.
|
|
||||||
//
|
|
||||||
// SetNodeInterface never fails when name is "".
|
|
||||||
func SetNodeInterface(name string) bool {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
return setNodeInterface(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setNodeInterface(name string) bool {
|
|
||||||
iname, addr := getHardwareInterface(name) // null implementation for js
|
|
||||||
if iname != "" && addr != nil {
|
|
||||||
ifname = iname
|
|
||||||
copy(nodeID[:], addr)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// We found no interfaces with a valid hardware address. If name
|
|
||||||
// does not specify a specific interface generate a random Node ID
|
|
||||||
// (section 4.1.6)
|
|
||||||
if name == "" {
|
|
||||||
ifname = "random"
|
|
||||||
randomBits(nodeID[:])
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
|
|
||||||
// if not already set.
|
|
||||||
func NodeID() []byte {
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
nid := nodeID
|
|
||||||
return nid[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
|
|
||||||
// of id are used. If id is less than 6 bytes then false is returned and the
|
|
||||||
// Node ID is not set.
|
|
||||||
func SetNodeID(id []byte) bool {
|
|
||||||
if len(id) < 6 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer nodeMu.Unlock()
|
|
||||||
nodeMu.Lock()
|
|
||||||
copy(nodeID[:], id)
|
|
||||||
ifname = "user"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
|
|
||||||
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) NodeID() []byte {
|
|
||||||
var node [6]byte
|
|
||||||
copy(node[:], uuid[10:])
|
|
||||||
return node[:]
|
|
||||||
}
|
|
12
vendor/github.com/google/uuid/node_js.go
generated
vendored
12
vendor/github.com/google/uuid/node_js.go
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
// getHardwareInterface returns nil values for the JS version of the code.
|
|
||||||
// This removes the "net" dependency, because it is not used in the browser.
|
|
||||||
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) { return "", nil }
|
|
33
vendor/github.com/google/uuid/node_net.go
generated
vendored
33
vendor/github.com/google/uuid/node_net.go
generated
vendored
|
@ -1,33 +0,0 @@
|
||||||
// Copyright 2017 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build !js
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
var interfaces []net.Interface // cached list of interfaces
|
|
||||||
|
|
||||||
// getHardwareInterface returns the name and hardware address of interface name.
|
|
||||||
// If name is "" then the name and hardware address of one of the system's
|
|
||||||
// interfaces is returned. If no interfaces are found (name does not exist or
|
|
||||||
// there are no interfaces) then "", nil is returned.
|
|
||||||
//
|
|
||||||
// Only addresses of at least 6 bytes are returned.
|
|
||||||
func getHardwareInterface(name string) (string, []byte) {
|
|
||||||
if interfaces == nil {
|
|
||||||
var err error
|
|
||||||
interfaces, err = net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, ifs := range interfaces {
|
|
||||||
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
|
|
||||||
return ifs.Name, ifs.HardwareAddr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", nil
|
|
||||||
}
|
|
118
vendor/github.com/google/uuid/null.go
generated
vendored
118
vendor/github.com/google/uuid/null.go
generated
vendored
|
@ -1,118 +0,0 @@
|
||||||
// Copyright 2021 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var jsonNull = []byte("null")
|
|
||||||
|
|
||||||
// NullUUID represents a UUID that may be null.
|
|
||||||
// NullUUID implements the SQL driver.Scanner interface so
|
|
||||||
// it can be used as a scan destination:
|
|
||||||
//
|
|
||||||
// var u uuid.NullUUID
|
|
||||||
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
|
|
||||||
// ...
|
|
||||||
// if u.Valid {
|
|
||||||
// // use u.UUID
|
|
||||||
// } else {
|
|
||||||
// // NULL value
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
type NullUUID struct {
|
|
||||||
UUID UUID
|
|
||||||
Valid bool // Valid is true if UUID is not NULL
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan implements the SQL driver.Scanner interface.
|
|
||||||
func (nu *NullUUID) Scan(value interface{}) error {
|
|
||||||
if value == nil {
|
|
||||||
nu.UUID, nu.Valid = Nil, false
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := nu.UUID.Scan(value)
|
|
||||||
if err != nil {
|
|
||||||
nu.Valid = false
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nu.Valid = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements the driver Valuer interface.
|
|
||||||
func (nu NullUUID) Value() (driver.Value, error) {
|
|
||||||
if !nu.Valid {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
// Delegate to UUID Value function
|
|
||||||
return nu.UUID.Value()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary implements encoding.BinaryMarshaler.
|
|
||||||
func (nu NullUUID) MarshalBinary() ([]byte, error) {
|
|
||||||
if nu.Valid {
|
|
||||||
return nu.UUID[:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte(nil), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
|
||||||
func (nu *NullUUID) UnmarshalBinary(data []byte) error {
|
|
||||||
if len(data) != 16 {
|
|
||||||
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
|
|
||||||
}
|
|
||||||
copy(nu.UUID[:], data)
|
|
||||||
nu.Valid = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
|
||||||
func (nu NullUUID) MarshalText() ([]byte, error) {
|
|
||||||
if nu.Valid {
|
|
||||||
return nu.UUID.MarshalText()
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonNull, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
|
||||||
func (nu *NullUUID) UnmarshalText(data []byte) error {
|
|
||||||
id, err := ParseBytes(data)
|
|
||||||
if err != nil {
|
|
||||||
nu.Valid = false
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nu.UUID = id
|
|
||||||
nu.Valid = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
|
||||||
func (nu NullUUID) MarshalJSON() ([]byte, error) {
|
|
||||||
if nu.Valid {
|
|
||||||
return json.Marshal(nu.UUID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonNull, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
|
||||||
func (nu *NullUUID) UnmarshalJSON(data []byte) error {
|
|
||||||
if bytes.Equal(data, jsonNull) {
|
|
||||||
*nu = NullUUID{}
|
|
||||||
return nil // valid null UUID
|
|
||||||
}
|
|
||||||
err := json.Unmarshal(data, &nu.UUID)
|
|
||||||
nu.Valid = err == nil
|
|
||||||
return err
|
|
||||||
}
|
|
59
vendor/github.com/google/uuid/sql.go
generated
vendored
59
vendor/github.com/google/uuid/sql.go
generated
vendored
|
@ -1,59 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scan implements sql.Scanner so UUIDs can be read from databases transparently.
|
|
||||||
// Currently, database types that map to string and []byte are supported. Please
|
|
||||||
// consult database-specific driver documentation for matching types.
|
|
||||||
func (uuid *UUID) Scan(src interface{}) error {
|
|
||||||
switch src := src.(type) {
|
|
||||||
case nil:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case string:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if src == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// see Parse for required string format
|
|
||||||
u, err := Parse(src)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Scan: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
*uuid = u
|
|
||||||
|
|
||||||
case []byte:
|
|
||||||
// if an empty UUID comes from a table, we return a null UUID
|
|
||||||
if len(src) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// assumes a simple slice of bytes if 16 bytes
|
|
||||||
// otherwise attempts to parse
|
|
||||||
if len(src) != 16 {
|
|
||||||
return uuid.Scan(string(src))
|
|
||||||
}
|
|
||||||
copy((*uuid)[:], src)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements sql.Valuer so that UUIDs can be written to databases
|
|
||||||
// transparently. Currently, UUIDs map to strings. Please consult
|
|
||||||
// database-specific driver documentation for matching types.
|
|
||||||
func (uuid UUID) Value() (driver.Value, error) {
|
|
||||||
return uuid.String(), nil
|
|
||||||
}
|
|
123
vendor/github.com/google/uuid/time.go
generated
vendored
123
vendor/github.com/google/uuid/time.go
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
|
|
||||||
// 1582.
|
|
||||||
type Time int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
lillian = 2299160 // Julian day of 15 Oct 1582
|
|
||||||
unix = 2440587 // Julian day of 1 Jan 1970
|
|
||||||
epoch = unix - lillian // Days between epochs
|
|
||||||
g1582 = epoch * 86400 // seconds between epochs
|
|
||||||
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
timeMu sync.Mutex
|
|
||||||
lasttime uint64 // last time we returned
|
|
||||||
clockSeq uint16 // clock sequence for this run
|
|
||||||
|
|
||||||
timeNow = time.Now // for testing
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnixTime converts t the number of seconds and nanoseconds using the Unix
|
|
||||||
// epoch of 1 Jan 1970.
|
|
||||||
func (t Time) UnixTime() (sec, nsec int64) {
|
|
||||||
sec = int64(t - g1582ns100)
|
|
||||||
nsec = (sec % 10000000) * 100
|
|
||||||
sec /= 10000000
|
|
||||||
return sec, nsec
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
|
|
||||||
// clock sequence as well as adjusting the clock sequence as needed. An error
|
|
||||||
// is returned if the current time cannot be determined.
|
|
||||||
func GetTime() (Time, uint16, error) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return getTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTime() (Time, uint16, error) {
|
|
||||||
t := timeNow()
|
|
||||||
|
|
||||||
// If we don't have a clock sequence already, set one.
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
now := uint64(t.UnixNano()/100) + g1582ns100
|
|
||||||
|
|
||||||
// If time has gone backwards with this clock sequence then we
|
|
||||||
// increment the clock sequence
|
|
||||||
if now <= lasttime {
|
|
||||||
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
|
|
||||||
}
|
|
||||||
lasttime = now
|
|
||||||
return Time(now), clockSeq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the current clock sequence, generating one if not
|
|
||||||
// already set. The clock sequence is only used for Version 1 UUIDs.
|
|
||||||
//
|
|
||||||
// The uuid package does not use global static storage for the clock sequence or
|
|
||||||
// the last time a UUID was generated. Unless SetClockSequence is used, a new
|
|
||||||
// random clock sequence is generated the first time a clock sequence is
|
|
||||||
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
|
|
||||||
func ClockSequence() int {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
return clockSequence()
|
|
||||||
}
|
|
||||||
|
|
||||||
func clockSequence() int {
|
|
||||||
if clockSeq == 0 {
|
|
||||||
setClockSequence(-1)
|
|
||||||
}
|
|
||||||
return int(clockSeq & 0x3fff)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
|
|
||||||
// -1 causes a new sequence to be generated.
|
|
||||||
func SetClockSequence(seq int) {
|
|
||||||
defer timeMu.Unlock()
|
|
||||||
timeMu.Lock()
|
|
||||||
setClockSequence(seq)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setClockSequence(seq int) {
|
|
||||||
if seq == -1 {
|
|
||||||
var b [2]byte
|
|
||||||
randomBits(b[:]) // clock sequence
|
|
||||||
seq = int(b[0])<<8 | int(b[1])
|
|
||||||
}
|
|
||||||
oldSeq := clockSeq
|
|
||||||
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
|
||||||
if oldSeq != clockSeq {
|
|
||||||
lasttime = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
|
||||||
// uuid. The time is only defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) Time() Time {
|
|
||||||
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
|
||||||
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
|
||||||
return Time(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClockSequence returns the clock sequence encoded in uuid.
|
|
||||||
// The clock sequence is only well defined for version 1 and 2 UUIDs.
|
|
||||||
func (uuid UUID) ClockSequence() int {
|
|
||||||
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
|
|
||||||
}
|
|
43
vendor/github.com/google/uuid/util.go
generated
vendored
43
vendor/github.com/google/uuid/util.go
generated
vendored
|
@ -1,43 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// randomBits completely fills slice b with random data.
|
|
||||||
func randomBits(b []byte) {
|
|
||||||
if _, err := io.ReadFull(rander, b); err != nil {
|
|
||||||
panic(err.Error()) // rand should never fail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
|
||||||
var xvalues = [256]byte{
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
}
|
|
||||||
|
|
||||||
// xtob converts hex characters x1 and x2 into a byte.
|
|
||||||
func xtob(x1, x2 byte) (byte, bool) {
|
|
||||||
b1 := xvalues[x1]
|
|
||||||
b2 := xvalues[x2]
|
|
||||||
return (b1 << 4) | b2, b1 != 255 && b2 != 255
|
|
||||||
}
|
|
296
vendor/github.com/google/uuid/uuid.go
generated
vendored
296
vendor/github.com/google/uuid/uuid.go
generated
vendored
|
@ -1,296 +0,0 @@
|
||||||
// Copyright 2018 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
|
|
||||||
// 4122.
|
|
||||||
type UUID [16]byte
|
|
||||||
|
|
||||||
// A Version represents a UUID's version.
|
|
||||||
type Version byte
|
|
||||||
|
|
||||||
// A Variant represents a UUID's variant.
|
|
||||||
type Variant byte
|
|
||||||
|
|
||||||
// Constants returned by Variant.
|
|
||||||
const (
|
|
||||||
Invalid = Variant(iota) // Invalid UUID
|
|
||||||
RFC4122 // The variant specified in RFC4122
|
|
||||||
Reserved // Reserved, NCS backward compatibility.
|
|
||||||
Microsoft // Reserved, Microsoft Corporation backward compatibility.
|
|
||||||
Future // Reserved for future definition.
|
|
||||||
)
|
|
||||||
|
|
||||||
const randPoolSize = 16 * 16
|
|
||||||
|
|
||||||
var (
|
|
||||||
rander = rand.Reader // random function
|
|
||||||
poolEnabled = false
|
|
||||||
poolMu sync.Mutex
|
|
||||||
poolPos = randPoolSize // protected with poolMu
|
|
||||||
pool [randPoolSize]byte // protected with poolMu
|
|
||||||
)
|
|
||||||
|
|
||||||
type invalidLengthError struct{ len int }
|
|
||||||
|
|
||||||
func (err invalidLengthError) Error() string {
|
|
||||||
return fmt.Sprintf("invalid UUID length: %d", err.len)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsInvalidLengthError is matcher function for custom error invalidLengthError
|
|
||||||
func IsInvalidLengthError(err error) bool {
|
|
||||||
_, ok := err.(invalidLengthError)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
|
||||||
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
|
||||||
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
|
||||||
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
|
||||||
func Parse(s string) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(s) {
|
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36:
|
|
||||||
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9:
|
|
||||||
if !strings.EqualFold(s[:9], "urn:uuid:") {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
|
||||||
}
|
|
||||||
s = s[9:]
|
|
||||||
|
|
||||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
case 36 + 2:
|
|
||||||
s = s[1:]
|
|
||||||
|
|
||||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
case 32:
|
|
||||||
var ok bool
|
|
||||||
for i := range uuid {
|
|
||||||
uuid[i], ok = xtob(s[i*2], s[i*2+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, invalidLengthError{len(s)}
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34,
|
|
||||||
} {
|
|
||||||
v, ok := xtob(s[x], s[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
|
||||||
func ParseBytes(b []byte) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
switch len(b) {
|
|
||||||
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
|
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
|
||||||
}
|
|
||||||
b = b[9:]
|
|
||||||
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
||||||
b = b[1:]
|
|
||||||
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
var ok bool
|
|
||||||
for i := 0; i < 32; i += 2 {
|
|
||||||
uuid[i/2], ok = xtob(b[i], b[i+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
default:
|
|
||||||
return uuid, invalidLengthError{len(b)}
|
|
||||||
}
|
|
||||||
// s is now at least 36 bytes long
|
|
||||||
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
for i, x := range [16]int{
|
|
||||||
0, 2, 4, 6,
|
|
||||||
9, 11,
|
|
||||||
14, 16,
|
|
||||||
19, 21,
|
|
||||||
24, 26, 28, 30, 32, 34,
|
|
||||||
} {
|
|
||||||
v, ok := xtob(b[x], b[x+1])
|
|
||||||
if !ok {
|
|
||||||
return uuid, errors.New("invalid UUID format")
|
|
||||||
}
|
|
||||||
uuid[i] = v
|
|
||||||
}
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParse is like Parse but panics if the string cannot be parsed.
|
|
||||||
// It simplifies safe initialization of global variables holding compiled UUIDs.
|
|
||||||
func MustParse(s string) UUID {
|
|
||||||
uuid, err := Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`uuid: Parse(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
|
||||||
// does not have a length of 16. The bytes are copied from the slice.
|
|
||||||
func FromBytes(b []byte) (uuid UUID, err error) {
|
|
||||||
err = uuid.UnmarshalBinary(b)
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must returns uuid if err is nil and panics otherwise.
|
|
||||||
func Must(uuid UUID, err error) UUID {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
||||||
// , or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) String() string {
|
|
||||||
var buf [36]byte
|
|
||||||
encodeHex(buf[:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// URN returns the RFC 2141 URN form of uuid,
|
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
|
|
||||||
func (uuid UUID) URN() string {
|
|
||||||
var buf [36 + 9]byte
|
|
||||||
copy(buf[:], "urn:uuid:")
|
|
||||||
encodeHex(buf[9:], uuid)
|
|
||||||
return string(buf[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeHex(dst []byte, uuid UUID) {
|
|
||||||
hex.Encode(dst, uuid[:4])
|
|
||||||
dst[8] = '-'
|
|
||||||
hex.Encode(dst[9:13], uuid[4:6])
|
|
||||||
dst[13] = '-'
|
|
||||||
hex.Encode(dst[14:18], uuid[6:8])
|
|
||||||
dst[18] = '-'
|
|
||||||
hex.Encode(dst[19:23], uuid[8:10])
|
|
||||||
dst[23] = '-'
|
|
||||||
hex.Encode(dst[24:], uuid[10:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variant returns the variant encoded in uuid.
|
|
||||||
func (uuid UUID) Variant() Variant {
|
|
||||||
switch {
|
|
||||||
case (uuid[8] & 0xc0) == 0x80:
|
|
||||||
return RFC4122
|
|
||||||
case (uuid[8] & 0xe0) == 0xc0:
|
|
||||||
return Microsoft
|
|
||||||
case (uuid[8] & 0xe0) == 0xe0:
|
|
||||||
return Future
|
|
||||||
default:
|
|
||||||
return Reserved
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version returns the version of uuid.
|
|
||||||
func (uuid UUID) Version() Version {
|
|
||||||
return Version(uuid[6] >> 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Version) String() string {
|
|
||||||
if v > 15 {
|
|
||||||
return fmt.Sprintf("BAD_VERSION_%d", v)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("VERSION_%d", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Variant) String() string {
|
|
||||||
switch v {
|
|
||||||
case RFC4122:
|
|
||||||
return "RFC4122"
|
|
||||||
case Reserved:
|
|
||||||
return "Reserved"
|
|
||||||
case Microsoft:
|
|
||||||
return "Microsoft"
|
|
||||||
case Future:
|
|
||||||
return "Future"
|
|
||||||
case Invalid:
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("BadVariant%d", int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRand sets the random number generator to r, which implements io.Reader.
|
|
||||||
// If r.Read returns an error when the package requests random data then
|
|
||||||
// a panic will be issued.
|
|
||||||
//
|
|
||||||
// Calling SetRand with nil sets the random number generator to the default
|
|
||||||
// generator.
|
|
||||||
func SetRand(r io.Reader) {
|
|
||||||
if r == nil {
|
|
||||||
rander = rand.Reader
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rander = r
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableRandPool enables internal randomness pool used for Random
|
|
||||||
// (Version 4) UUID generation. The pool contains random bytes read from
|
|
||||||
// the random number generator on demand in batches. Enabling the pool
|
|
||||||
// may improve the UUID generation throughput significantly.
|
|
||||||
//
|
|
||||||
// Since the pool is stored on the Go heap, this feature may be a bad fit
|
|
||||||
// for security sensitive applications.
|
|
||||||
//
|
|
||||||
// Both EnableRandPool and DisableRandPool are not thread-safe and should
|
|
||||||
// only be called when there is no possibility that New or any other
|
|
||||||
// UUID Version 4 generation function will be called concurrently.
|
|
||||||
func EnableRandPool() {
|
|
||||||
poolEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableRandPool disables the randomness pool if it was previously
|
|
||||||
// enabled with EnableRandPool.
|
|
||||||
//
|
|
||||||
// Both EnableRandPool and DisableRandPool are not thread-safe and should
|
|
||||||
// only be called when there is no possibility that New or any other
|
|
||||||
// UUID Version 4 generation function will be called concurrently.
|
|
||||||
func DisableRandPool() {
|
|
||||||
poolEnabled = false
|
|
||||||
defer poolMu.Unlock()
|
|
||||||
poolMu.Lock()
|
|
||||||
poolPos = randPoolSize
|
|
||||||
}
|
|
44
vendor/github.com/google/uuid/version1.go
generated
vendored
44
vendor/github.com/google/uuid/version1.go
generated
vendored
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
|
|
||||||
// sequence, and the current time. If the NodeID has not been set by SetNodeID
|
|
||||||
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
|
|
||||||
// be set NewUUID returns nil. If clock sequence has not been set by
|
|
||||||
// SetClockSequence then it will be set automatically. If GetTime fails to
|
|
||||||
// return the current NewUUID returns nil and an error.
|
|
||||||
//
|
|
||||||
// In most cases, New should be used.
|
|
||||||
func NewUUID() (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
now, seq, err := GetTime()
|
|
||||||
if err != nil {
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeLow := uint32(now & 0xffffffff)
|
|
||||||
timeMid := uint16((now >> 32) & 0xffff)
|
|
||||||
timeHi := uint16((now >> 48) & 0x0fff)
|
|
||||||
timeHi |= 0x1000 // Version 1
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(uuid[0:], timeLow)
|
|
||||||
binary.BigEndian.PutUint16(uuid[4:], timeMid)
|
|
||||||
binary.BigEndian.PutUint16(uuid[6:], timeHi)
|
|
||||||
binary.BigEndian.PutUint16(uuid[8:], seq)
|
|
||||||
|
|
||||||
nodeMu.Lock()
|
|
||||||
if nodeID == zeroID {
|
|
||||||
setNodeInterface("")
|
|
||||||
}
|
|
||||||
copy(uuid[10:], nodeID[:])
|
|
||||||
nodeMu.Unlock()
|
|
||||||
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
76
vendor/github.com/google/uuid/version4.go
generated
vendored
76
vendor/github.com/google/uuid/version4.go
generated
vendored
|
@ -1,76 +0,0 @@
|
||||||
// Copyright 2016 Google Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package uuid
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
// New creates a new random UUID or panics. New is equivalent to
|
|
||||||
// the expression
|
|
||||||
//
|
|
||||||
// uuid.Must(uuid.NewRandom())
|
|
||||||
func New() UUID {
|
|
||||||
return Must(NewRandom())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewString creates a new random UUID and returns it as a string or panics.
|
|
||||||
// NewString is equivalent to the expression
|
|
||||||
//
|
|
||||||
// uuid.New().String()
|
|
||||||
func NewString() string {
|
|
||||||
return Must(NewRandom()).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRandom returns a Random (Version 4) UUID.
|
|
||||||
//
|
|
||||||
// The strength of the UUIDs is based on the strength of the crypto/rand
|
|
||||||
// package.
|
|
||||||
//
|
|
||||||
// Uses the randomness pool if it was enabled with EnableRandPool.
|
|
||||||
//
|
|
||||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
|
||||||
//
|
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
|
||||||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
|
||||||
// means the probability is about 0.00000000006 (6 × 10−11),
|
|
||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
|
||||||
// year and having one duplicate.
|
|
||||||
func NewRandom() (UUID, error) {
|
|
||||||
if !poolEnabled {
|
|
||||||
return NewRandomFromReader(rander)
|
|
||||||
}
|
|
||||||
return newRandomFromPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
|
|
||||||
func NewRandomFromReader(r io.Reader) (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
_, err := io.ReadFull(r, uuid[:])
|
|
||||||
if err != nil {
|
|
||||||
return Nil, err
|
|
||||||
}
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRandomFromPool() (UUID, error) {
|
|
||||||
var uuid UUID
|
|
||||||
poolMu.Lock()
|
|
||||||
if poolPos == randPoolSize {
|
|
||||||
_, err := io.ReadFull(rander, pool[:])
|
|
||||||
if err != nil {
|
|
||||||
poolMu.Unlock()
|
|
||||||
return Nil, err
|
|
||||||
}
|
|
||||||
poolPos = 0
|
|
||||||
}
|
|
||||||
copy(uuid[:], pool[poolPos:(poolPos+16)])
|
|
||||||
poolPos += 16
|
|
||||||
poolMu.Unlock()
|
|
||||||
|
|
||||||
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
|
|
||||||
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
|
|
||||||
return uuid, nil
|
|
||||||
}
|
|
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
|
@ -1,4 +1,4 @@
|
||||||
# github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
# github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c
|
||||||
## explicit
|
## explicit
|
||||||
github.com/Azure/go-ntlmssp
|
github.com/Azure/go-ntlmssp
|
||||||
# github.com/BurntSushi/toml v1.3.2
|
# github.com/BurntSushi/toml v1.3.2
|
||||||
|
@ -39,8 +39,8 @@ github.com/felixge/httpsnoop
|
||||||
# github.com/go-asn1-ber/asn1-ber v1.5.5
|
# github.com/go-asn1-ber/asn1-ber v1.5.5
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/go-asn1-ber/asn1-ber
|
github.com/go-asn1-ber/asn1-ber
|
||||||
# github.com/go-ldap/ldap/v3 v3.4.6
|
# github.com/go-ldap/ldap/v3 v3.4.1
|
||||||
## explicit; go 1.14
|
## explicit; go 1.13
|
||||||
github.com/go-ldap/ldap/v3
|
github.com/go-ldap/ldap/v3
|
||||||
# github.com/go-sql-driver/mysql v1.7.1
|
# github.com/go-sql-driver/mysql v1.7.1
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
|
@ -62,9 +62,6 @@ github.com/golang/glog/internal/stackdump
|
||||||
# github.com/google/go-querystring v1.1.0
|
# github.com/google/go-querystring v1.1.0
|
||||||
## explicit; go 1.10
|
## explicit; go 1.10
|
||||||
github.com/google/go-querystring/query
|
github.com/google/go-querystring/query
|
||||||
# github.com/google/uuid v1.3.1
|
|
||||||
## explicit
|
|
||||||
github.com/google/uuid
|
|
||||||
# github.com/gorilla/css v1.0.1
|
# github.com/gorilla/css v1.0.1
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/gorilla/css/scanner
|
github.com/gorilla/css/scanner
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue