From 451e6be1804133b069ff8bfd113e25149ce5e174 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 3 Jul 2020 16:05:43 -0700 Subject: [PATCH] Evil not very fun CGO glue for Certificate works! Also added a self-test project for Go code. Not using "go test" because of CMake build and CGO linking requirements that make it a pain in the derriere. --- CMakeLists.txt | 9 ++ cmd/zt_service_tests/certificate.go | 111 ++++++++++++++ cmd/zt_service_tests/zt_service_tests.go | 10 ++ pkg/zerotier/certificate.go | 176 +++++++++++++---------- pkg/zerotier/misc.go | 9 +- 5 files changed, 236 insertions(+), 79 deletions(-) create mode 100644 cmd/zt_service_tests/certificate.go create mode 100644 cmd/zt_service_tests/zt_service_tests.go diff --git a/CMakeLists.txt b/CMakeLists.txt index 853daae14..a600be559 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,15 @@ if(NOT PACKAGE_STATIC) endif() endif(WIN32) + add_custom_target( + zt_service_tests ALL + BYPRODUCTS ${CMAKE_BINARY_DIR}/zt_service_tests + SOURCES ${go_src} + COMMAND ${CMAKE_COMMAND} -E env ${GOARCH} ${GOARM} CGO_ENABLED=1 CGO_CFLAGS=\"-O3\" CGO_LDFLAGS=\"$ $ $ $ ${GO_EXTRA_LIBRARIES}\" ${GO} build -mod=vendor ${GOFLAGS} -o ${CMAKE_BINARY_DIR}/zt_service_tests ${CMAKE_SOURCE_DIR}/cmd/zt_service_tests/*.go + COMMENT "Compiling zt_service_tests (Go/cgo self-tests)..." + ) + add_dependencies(zt_service_tests zt_osdep zt_core zt_controller zt_service_io_core) + add_custom_target( zerotier ALL BYPRODUCTS ${CMAKE_BINARY_DIR}/zerotier diff --git a/cmd/zt_service_tests/certificate.go b/cmd/zt_service_tests/certificate.go new file mode 100644 index 000000000..56efd1fe0 --- /dev/null +++ b/cmd/zt_service_tests/certificate.go @@ -0,0 +1,111 @@ +/* + * Copyright (C)2013-2020 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2024-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "zerotier/pkg/zerotier" +) + +func TestCertificate() bool { + fmt.Println("Checking Certificate conversion to/from C ZT_Certificate structure...") + + id, err := zerotier.NewIdentityFromString("8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e") + if err != nil { + fmt.Printf(" Error deserializing test identity: %s\n", err.Error()) + return false + } + + var c zerotier.Certificate + + c.SerialNo = make([]byte, 48) + for i := 0; i < 48 ;i++ { + c.SerialNo[i] = byte(i) + } + c.Flags = 1234 + c.Timestamp = 5678 + c.Validity[0] = 1010 + c.Validity[1] = 2020 + c.Subject.Timestamp = 31337 + c.Subject.Identities = append(c.Subject.Identities, zerotier.CertificateIdentity{ + Identity: id, + Locator: nil, + }) + c.Subject.Networks = append(c.Subject.Networks, zerotier.CertificateNetwork{ + ID: 1111, + Controller: zerotier.Fingerprint{ + Address: zerotier.Address(2222), + Hash: c.SerialNo, + }, + }) + c.Subject.Certificates = append(c.Subject.Certificates, c.SerialNo) + c.Subject.UpdateURLs = append(c.Subject.UpdateURLs, "https://www.zerotier.com/asdfasdf") + c.Subject.Name.SerialNo = "a" + c.Subject.Name.CommonName = "b" + c.Subject.Name.StreetAddress = "c" + c.Subject.Name.Locality = "d" + c.Subject.Name.Province = "e" + c.Subject.Name.PostalCode = "f" + c.Subject.Name.Country = "g" + c.Subject.Name.Organization = "h" + c.Subject.Name.Unit = "i" + c.Subject.Name.Email = "j" + c.Subject.Name.URL = "k" + c.Subject.Name.Host = "l" + c.Subject.UniqueID = []byte("asdf") + c.Subject.UniqueIDProofSignature = []byte("ghij") + c.Issuer = id + c.IssuerName.SerialNo = "m" + c.IssuerName.CommonName = "n" + c.IssuerName.StreetAddress = "o" + c.IssuerName.Locality = "p" + c.IssuerName.Province = "q" + c.IssuerName.PostalCode = "r" + c.IssuerName.Country = "s" + c.IssuerName.Organization = "t" + c.IssuerName.Unit = "u" + c.IssuerName.Email = "v" + c.IssuerName.URL = "w" + c.IssuerName.Host = "x" + c.ExtendedAttributes = c.SerialNo + c.MaxPathLength = 9999 + c.Signature = []byte("qwerty") + + cc := c.CCertificate() + if cc == nil { + fmt.Println(" Error converting Certificate to ZT_Certificate") + return false + } + + c2 := zerotier.NewCertificateFromCCertificate(cc.C) + if c2 == nil { + fmt.Println(" Error converting ZT_Certificate to Certificate") + return false + } + + j, _ := json.MarshalIndent(c, "", " ") + j2, _ := json.MarshalIndent(c2, "", " ") + + if !bytes.Equal(j, j2) { + j, _ = json.MarshalIndent(c, "", " ") + fmt.Print(" Deep equality test failed: certificates do not match! (see dumps below)\n\n") + fmt.Println(string(j)) + fmt.Println(string(j2)) + return false + } + + return true +} diff --git a/cmd/zt_service_tests/zt_service_tests.go b/cmd/zt_service_tests/zt_service_tests.go new file mode 100644 index 000000000..bc0a0dde2 --- /dev/null +++ b/cmd/zt_service_tests/zt_service_tests.go @@ -0,0 +1,10 @@ +package main + +import "os" + +func main() { + if !TestCertificate() { + os.Exit(1) + } +} + diff --git a/pkg/zerotier/certificate.go b/pkg/zerotier/certificate.go index adc695c85..6d3f0a2e9 100644 --- a/pkg/zerotier/certificate.go +++ b/pkg/zerotier/certificate.go @@ -49,20 +49,20 @@ type CertificateIdentity struct { // CertificateNetwork bundles a network ID with the fingerprint of its primary controller. type CertificateNetwork struct { - ID uint64 `json:"id"` - Controller Fingerprint `json:"controller"` + ID uint64 `json:"id"` + Controller Fingerprint `json:"controller"` } // CertificateSubject contains information about the subject of a certificate. type CertificateSubject struct { - Timestamp int64 `json:"timestamp"` - Identities []CertificateIdentity `json:"identities,omitempty"` - Networks []CertificateNetwork `json:"networks,omitempty"` - Certificates [][CertificateSerialNoSize]byte `json:"certificates,omitempty"` - UpdateURLs []string `json:"updateURLs,omitempty"` - Name CertificateName `json:"name"` - UniqueID []byte `json:"uniqueId,omitempty"` - UniqueIDProofSignature []byte `json:"uniqueIdProofSignature,omitempty"` + Timestamp int64 `json:"timestamp"` + Identities []CertificateIdentity `json:"identities,omitempty"` + Networks []CertificateNetwork `json:"networks,omitempty"` + Certificates [][]byte `json:"certificates,omitempty"` + UpdateURLs []string `json:"updateURLs,omitempty"` + Name CertificateName `json:"name"` + UniqueID []byte `json:"uniqueId,omitempty"` + UniqueIDProofSignature []byte `json:"uniqueIdProofSignature,omitempty"` } // Certificate is a Go reflection of the C ZT_Certificate struct. @@ -79,25 +79,30 @@ type Certificate struct { Signature []byte `json:"signature,omitempty"` } -type cCertificate struct { - C C.ZT_Certificate +type CCertificate struct { + C unsafe.Pointer + internalCertificate C.ZT_Certificate internalSubjectIdentities []C.ZT_Certificate_Identity internalSubjectNetworks []C.ZT_Certificate_Network - internalSubjectUpdateURLs []*C.char + internalSubjectCertificates []uintptr + internalSubjectUpdateURLs []uintptr internalSubjectUpdateURLsData [][]byte } -// newCertificateFromCCertificate translates a C ZT_Certificate into a Go Certificate. -func newCertificateFromCCertificate(cc *C.ZT_Certificate) *Certificate { +// NewCertificateFromCCertificate translates a C ZT_Certificate into a Go Certificate. +func NewCertificateFromCCertificate(ccptr unsafe.Pointer) *Certificate { + cc := (*C.ZT_Certificate)(ccptr) c := new(Certificate) if cc == nil { return c } - c.SerialNo = C.GoBytes(unsafe.Pointer(&cc.serialNo[0]), 48) - if allZero(c.SerialNo) { - c.SerialNo = nil + sn := (*[48]byte)(unsafe.Pointer(&cc.serialNo[0]))[:] + if !allZero(sn) { + var tmp [48]byte + copy(tmp[:], sn) + c.SerialNo = tmp[:] } c.Flags = uint64(cc.flags) c.Timestamp = int64(cc.timestamp) @@ -135,14 +140,16 @@ func newCertificateFromCCertificate(cc *C.ZT_Certificate) *Certificate { return nil } c.Subject.Networks = append(c.Subject.Networks, CertificateNetwork{ - ID: uint64(cn.id), + ID: uint64(cn.id), Controller: *fp, }) } for i := 0; i < int(cc.subject.certificateCount); i++ { - csn := (*[48]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.certificates)) + (uintptr(i) * pointerSize))) - c.Subject.Certificates = append(c.Subject.Certificates, *csn) + csn := *((**[48]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(cc.subject.certificates)) + (uintptr(i) * pointerSize)))) + var tmp [48]byte + copy(tmp[:], csn[:]) + c.Subject.Certificates = append(c.Subject.Certificates, tmp[:]) } for i := 0; i < int(cc.subject.updateURLCount); i++ { @@ -204,26 +211,36 @@ func newCertificateFromCCertificate(cc *C.ZT_Certificate) *Certificate { return c } -// cCertificate creates a C ZT_Certificate structure from the content of a Certificate. +// CCertificate creates a C ZT_Certificate structure from the content of a Certificate. +// // This will return nil if an error occurs, which would indicate an invalid C // structure or one with invalid values. +// // The returned Go structure bundles this with some objects that have // to be created to set their pointers in ZT_Certificate. It's easier to // manage allocation of these in Go and bundle them so Go's GC will clean -// them up automatically when cCertificate is released. Only the 'C' field -// in cCertificate should be directly used. -func (c *Certificate) cCertificate() *cCertificate { - var cc cCertificate +// them up automatically when CCertificate is released. Only the 'C' field +// in CCertificate should be directly used. The rest are internal and are +// hidden outside the package. +// +// Ensure that Certificate is not modified until the generated C certificate +// is no longer in use. +func (c *Certificate) CCertificate() *CCertificate { + var cc CCertificate + var ccC *C.ZT_Certificate + + cc.C = unsafe.Pointer(&cc.internalCertificate) + ccC = &cc.internalCertificate if len(c.SerialNo) == 48 { - copy((*[48]byte)(unsafe.Pointer(&cc.C.serialNo[0]))[:], c.SerialNo[:]) + copy((*[48]byte)(unsafe.Pointer(&ccC.serialNo[0]))[:], c.SerialNo) } - cc.C.flags = C.uint64_t(c.Flags) - cc.C.timestamp = C.int64_t(c.Timestamp) - cc.C.validity[0] = C.int64_t(c.Validity[0]) - cc.C.validity[1] = C.int64_t(c.Validity[1]) + ccC.flags = C.uint64_t(c.Flags) + ccC.timestamp = C.int64_t(c.Timestamp) + ccC.validity[0] = C.int64_t(c.Validity[0]) + ccC.validity[1] = C.int64_t(c.Validity[1]) - cc.C.subject.timestamp = C.int64_t(c.Subject.Timestamp) + ccC.subject.timestamp = C.int64_t(c.Subject.Timestamp) if len(c.Subject.Identities) > 0 { cc.internalSubjectIdentities = make([]C.ZT_Certificate_Identity, len(c.Subject.Identities)) @@ -236,8 +253,8 @@ func (c *Certificate) cCertificate() *cCertificate { cc.internalSubjectIdentities[i].locator = id.Locator.cl } } - cc.C.subject.identities = &cc.internalSubjectIdentities[0] - cc.C.subject.identityCount = C.uint(len(c.Subject.Identities)) + ccC.subject.identities = &cc.internalSubjectIdentities[0] + ccC.subject.identityCount = C.uint(len(c.Subject.Identities)) } if len(c.Subject.Networks) > 0 { @@ -249,45 +266,52 @@ func (c *Certificate) cCertificate() *cCertificate { copy((*[48]byte)(unsafe.Pointer(&cc.internalSubjectNetworks[i].controller.hash[0]))[:], n.Controller.Hash) } } - cc.C.subject.networks = &cc.internalSubjectNetworks[0] - cc.C.subject.networkCount = C.uint(len(c.Subject.Networks)) + ccC.subject.networks = &cc.internalSubjectNetworks[0] + ccC.subject.networkCount = C.uint(len(c.Subject.Networks)) } if len(c.Subject.Certificates) > 0 { - cc.C.subject.certificates = (**C.uint8_t)(unsafe.Pointer(&c.Subject.Certificates[0])) - cc.C.subject.certificateCount = C.uint(len(c.Subject.Certificates)) + cc.internalSubjectCertificates = make([]uintptr, len(c.Subject.Certificates)) + for i, cert := range c.Subject.Certificates { + if len(cert) != 48 { + return nil + } + cc.internalSubjectCertificates[i] = uintptr(unsafe.Pointer(&cert[0])) + } + ccC.subject.certificates = (**C.uint8_t)(unsafe.Pointer(&cc.internalSubjectCertificates[0])) + ccC.subject.certificateCount = C.uint(len(c.Subject.Certificates)) } if len(c.Subject.UpdateURLs) > 0 { - cc.internalSubjectUpdateURLs = make([]*C.char, len(c.Subject.UpdateURLs)) + cc.internalSubjectUpdateURLs = make([]uintptr, len(c.Subject.UpdateURLs)) cc.internalSubjectUpdateURLsData = make([][]byte, len(c.Subject.UpdateURLs)) for i, u := range c.Subject.UpdateURLs { cc.internalSubjectUpdateURLsData[i] = stringAsZeroTerminatedBytes(u) - cc.internalSubjectUpdateURLs[i] = (*C.char)(unsafe.Pointer(&cc.internalSubjectUpdateURLsData[0])) + cc.internalSubjectUpdateURLs[i] = uintptr(unsafe.Pointer(&cc.internalSubjectUpdateURLsData[0][0])) } - cc.C.subject.updateURLs = (**C.char)(unsafe.Pointer(&cc.internalSubjectUpdateURLs[0])) - cc.C.subject.updateURLCount = C.uint(len(c.Subject.UpdateURLs)) + ccC.subject.updateURLs = (**C.char)(unsafe.Pointer(&cc.internalSubjectUpdateURLs[0])) + ccC.subject.updateURLCount = C.uint(len(c.Subject.UpdateURLs)) } - cStrCopy(unsafe.Pointer(&cc.C.subject.name.serialNo[0]), CertificateMaxStringLength+1, c.Subject.Name.SerialNo) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.commonName[0]), CertificateMaxStringLength+1, c.Subject.Name.CommonName) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.country[0]), CertificateMaxStringLength+1, c.Subject.Name.Country) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.organization[0]), CertificateMaxStringLength+1, c.Subject.Name.Organization) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.unit[0]), CertificateMaxStringLength+1, c.Subject.Name.Unit) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.locality[0]), CertificateMaxStringLength+1, c.Subject.Name.Locality) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.province[0]), CertificateMaxStringLength+1, c.Subject.Name.Province) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.streetAddress[0]), CertificateMaxStringLength+1, c.Subject.Name.StreetAddress) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.postalCode[0]), CertificateMaxStringLength+1, c.Subject.Name.PostalCode) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.email[0]), CertificateMaxStringLength+1, c.Subject.Name.Email) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.url[0]), CertificateMaxStringLength+1, c.Subject.Name.URL) - cStrCopy(unsafe.Pointer(&cc.C.subject.name.host[0]), CertificateMaxStringLength+1, c.Subject.Name.Host) + cStrCopy(unsafe.Pointer(&ccC.subject.name.serialNo[0]), CertificateMaxStringLength+1, c.Subject.Name.SerialNo) + cStrCopy(unsafe.Pointer(&ccC.subject.name.commonName[0]), CertificateMaxStringLength+1, c.Subject.Name.CommonName) + cStrCopy(unsafe.Pointer(&ccC.subject.name.country[0]), CertificateMaxStringLength+1, c.Subject.Name.Country) + cStrCopy(unsafe.Pointer(&ccC.subject.name.organization[0]), CertificateMaxStringLength+1, c.Subject.Name.Organization) + cStrCopy(unsafe.Pointer(&ccC.subject.name.unit[0]), CertificateMaxStringLength+1, c.Subject.Name.Unit) + cStrCopy(unsafe.Pointer(&ccC.subject.name.locality[0]), CertificateMaxStringLength+1, c.Subject.Name.Locality) + cStrCopy(unsafe.Pointer(&ccC.subject.name.province[0]), CertificateMaxStringLength+1, c.Subject.Name.Province) + cStrCopy(unsafe.Pointer(&ccC.subject.name.streetAddress[0]), CertificateMaxStringLength+1, c.Subject.Name.StreetAddress) + cStrCopy(unsafe.Pointer(&ccC.subject.name.postalCode[0]), CertificateMaxStringLength+1, c.Subject.Name.PostalCode) + cStrCopy(unsafe.Pointer(&ccC.subject.name.email[0]), CertificateMaxStringLength+1, c.Subject.Name.Email) + cStrCopy(unsafe.Pointer(&ccC.subject.name.url[0]), CertificateMaxStringLength+1, c.Subject.Name.URL) + cStrCopy(unsafe.Pointer(&ccC.subject.name.host[0]), CertificateMaxStringLength+1, c.Subject.Name.Host) if len(c.Subject.UniqueID) > 0 { - cc.C.subject.uniqueId = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueID[0])) - cc.C.subject.uniqueIdSize = C.uint(len(c.Subject.UniqueID)) + ccC.subject.uniqueId = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueID[0])) + ccC.subject.uniqueIdSize = C.uint(len(c.Subject.UniqueID)) if len(c.Subject.UniqueIDProofSignature) > 0 { - cc.C.subject.uniqueIdProofSignature = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueIDProofSignature[0])) - cc.C.subject.uniqueIdProofSignatureSize = C.uint(len(c.Subject.UniqueIDProofSignature)) + ccC.subject.uniqueIdProofSignature = (*C.uint8_t)(unsafe.Pointer(&c.Subject.UniqueIDProofSignature[0])) + ccC.subject.uniqueIdProofSignatureSize = C.uint(len(c.Subject.UniqueIDProofSignature)) } } @@ -295,32 +319,32 @@ func (c *Certificate) cCertificate() *cCertificate { if !c.Issuer.initCIdentityPtr() { return nil } - cc.C.issuer = c.Issuer.cid + ccC.issuer = c.Issuer.cid } - cStrCopy(unsafe.Pointer(&cc.C.issuerName.serialNo[0]), CertificateMaxStringLength+1, c.IssuerName.SerialNo) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.commonName[0]), CertificateMaxStringLength+1, c.IssuerName.CommonName) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.country[0]), CertificateMaxStringLength+1, c.IssuerName.Country) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.organization[0]), CertificateMaxStringLength+1, c.IssuerName.Organization) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.unit[0]), CertificateMaxStringLength+1, c.IssuerName.Unit) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.locality[0]), CertificateMaxStringLength+1, c.IssuerName.Locality) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.province[0]), CertificateMaxStringLength+1, c.IssuerName.Province) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.streetAddress[0]), CertificateMaxStringLength+1, c.IssuerName.StreetAddress) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.postalCode[0]), CertificateMaxStringLength+1, c.IssuerName.PostalCode) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.email[0]), CertificateMaxStringLength+1, c.IssuerName.Email) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.url[0]), CertificateMaxStringLength+1, c.IssuerName.URL) - cStrCopy(unsafe.Pointer(&cc.C.issuerName.host[0]), CertificateMaxStringLength+1, c.IssuerName.Host) + cStrCopy(unsafe.Pointer(&ccC.issuerName.serialNo[0]), CertificateMaxStringLength+1, c.IssuerName.SerialNo) + cStrCopy(unsafe.Pointer(&ccC.issuerName.commonName[0]), CertificateMaxStringLength+1, c.IssuerName.CommonName) + cStrCopy(unsafe.Pointer(&ccC.issuerName.country[0]), CertificateMaxStringLength+1, c.IssuerName.Country) + cStrCopy(unsafe.Pointer(&ccC.issuerName.organization[0]), CertificateMaxStringLength+1, c.IssuerName.Organization) + cStrCopy(unsafe.Pointer(&ccC.issuerName.unit[0]), CertificateMaxStringLength+1, c.IssuerName.Unit) + cStrCopy(unsafe.Pointer(&ccC.issuerName.locality[0]), CertificateMaxStringLength+1, c.IssuerName.Locality) + cStrCopy(unsafe.Pointer(&ccC.issuerName.province[0]), CertificateMaxStringLength+1, c.IssuerName.Province) + cStrCopy(unsafe.Pointer(&ccC.issuerName.streetAddress[0]), CertificateMaxStringLength+1, c.IssuerName.StreetAddress) + cStrCopy(unsafe.Pointer(&ccC.issuerName.postalCode[0]), CertificateMaxStringLength+1, c.IssuerName.PostalCode) + cStrCopy(unsafe.Pointer(&ccC.issuerName.email[0]), CertificateMaxStringLength+1, c.IssuerName.Email) + cStrCopy(unsafe.Pointer(&ccC.issuerName.url[0]), CertificateMaxStringLength+1, c.IssuerName.URL) + cStrCopy(unsafe.Pointer(&ccC.issuerName.host[0]), CertificateMaxStringLength+1, c.IssuerName.Host) if len(c.ExtendedAttributes) > 0 { - cc.C.extendedAttributes = (*C.uint8_t)(unsafe.Pointer(&c.ExtendedAttributes[0])) - cc.C.extendedAttributesSize = C.uint(len(c.ExtendedAttributes)) + ccC.extendedAttributes = (*C.uint8_t)(unsafe.Pointer(&c.ExtendedAttributes[0])) + ccC.extendedAttributesSize = C.uint(len(c.ExtendedAttributes)) } - cc.C.maxPathLength = C.uint(c.MaxPathLength) + ccC.maxPathLength = C.uint(c.MaxPathLength) if len(c.Signature) > 0 { - cc.C.signature = (*C.uint8_t)(unsafe.Pointer(&c.Signature[0])) - cc.C.signatureSize = C.uint(len(c.Signature)) + ccC.signature = (*C.uint8_t)(unsafe.Pointer(&c.Signature[0])) + ccC.signatureSize = C.uint(len(c.Signature)) } return &cc diff --git a/pkg/zerotier/misc.go b/pkg/zerotier/misc.go index f04669806..33222b397 100644 --- a/pkg/zerotier/misc.go +++ b/pkg/zerotier/misc.go @@ -279,10 +279,13 @@ func stringAsZeroTerminatedBytes(s string) (b []byte) { // cStrCopy copies src into dest as a zero-terminated C string func cStrCopy(dest unsafe.Pointer, destSize int, src string) { sb := []byte(src) - b := C.GoBytes(dest, C.int(destSize)) if len(sb) > (destSize - 1) { sb = sb[0:destSize - 1] } - copy(b[:], sb[:]) - b[len(sb)] = 0 + dp := dest + for _, c := range sb { + *((*byte)(dp)) = c + dp = unsafe.Pointer(uintptr(dp) + 1) + } + *((*byte)(dp)) = 0 }