Build fix, add Go unit tests for CGo Locator interface.

This commit is contained in:
Adam Ierymenko 2020-10-26 18:44:45 -04:00
parent 387d293793
commit 1bb43476e8
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
11 changed files with 145 additions and 58 deletions

View file

@ -48,20 +48,27 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
Help()
return 1
}
uniqueId, uniqueIdPrivate, err := zerotier.NewCertificateSubjectUniqueId(zerotier.CertificateUniqueIdTypeNistP384)
if err != nil {
fmt.Printf("ERROR: unable to create unique ID and private key: %s\n", err.Error())
pErr("unable to create unique ID and private key: %s", err.Error())
return 1
}
sec, err := json.MarshalIndent(&zerotier.CertificateSubjectUniqueIDSecret{UniqueID: uniqueId, UniqueIDSecret: uniqueIdPrivate}, "", " ")
sec, err := json.MarshalIndent(&zerotier.CertificateSubjectUniqueIDSecret{
UniqueID: uniqueId,
UniqueIDSecret: uniqueIdPrivate,
}, "", " ")
if err != nil {
fmt.Printf("ERROR: unable to create unique ID and private key: %s\n", err.Error())
pErr("unable to create unique ID and private key: %s", err.Error())
return 1
}
if len(args) == 1 {
fmt.Println(string(sec))
} else {
_ = ioutil.WriteFile(args[1], sec, 0600)
pResult("%s", args[1])
}
case "newcsr":
@ -69,28 +76,32 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
Help()
return 1
}
var cs zerotier.CertificateSubject
err := readJSONFile(args[1], &cs)
var subject zerotier.CertificateSubject
err := readJSONFile(args[1], &subject)
if err != nil {
fmt.Printf("ERROR: unable to read subject from %s: %s\n", args[1], err.Error())
pErr("unable to read subject from %s: %s", args[1], err.Error())
return 1
}
var subj zerotier.CertificateSubjectUniqueIDSecret
err = readJSONFile(args[2], &subj)
var uniqueIdSecret zerotier.CertificateSubjectUniqueIDSecret
err = readJSONFile(args[2], &uniqueIdSecret)
if err != nil {
fmt.Printf("ERROR: unable to read unique ID secret from %s: %s\n", args[2], err.Error())
pErr("unable to read unique ID secret from %s: %s", args[2], err.Error())
return 1
}
csr, err := zerotier.NewCertificateCSR(&cs, subj.UniqueID, subj.UniqueIDSecret)
csr, err := zerotier.NewCertificateCSR(&subject, uniqueIdSecret.UniqueID, uniqueIdSecret.UniqueIDSecret)
if err != nil {
fmt.Printf("ERROR: problem creating CSR: %s\n", err.Error())
pErr("problem creating CSR: %s", err.Error())
return 1
}
err = ioutil.WriteFile(args[3], csr, 0644)
if err == nil {
fmt.Printf("Wrote CSR to %s\n", args[3])
pResult("%s", args[3])
} else {
fmt.Printf("ERROR: unable to write CSR to %s: %s\n", args[3], err.Error())
pErr("unable to write CSR to %s: %s", args[3], err.Error())
return 1
}
@ -102,40 +113,42 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
csrBytes, err := ioutil.ReadFile(args[1])
if err != nil {
fmt.Printf("ERROR: unable to read CSR from %s: %s\n", args[1], err.Error())
pErr("unable to read CSR from %s: %s", args[1], err.Error())
return 1
}
csr, err := zerotier.NewCertificateFromBytes(csrBytes, false)
if err != nil {
fmt.Printf("ERROR: CSR in %s is invalid: %s\n", args[1], err.Error())
pErr("CSR in %s is invalid: %s", args[1], err.Error())
return 1
}
id := readIdentity(args[2])
if id == nil {
fmt.Printf("ERROR: unable to read identity from %s\n", args[2])
signingIdentity := readIdentity(args[2])
if signingIdentity == nil {
pErr("unable to read identity from %s", args[2])
return 1
}
if !id.HasPrivate() {
fmt.Printf("ERROR: signing identity in %s lacks private key\n", args[2])
if !signingIdentity.HasPrivate() {
pErr("signing identity in %s lacks private key", args[2])
return 1
}
cert, err := csr.Sign(id)
cert, err := csr.Sign(signingIdentity)
if err != nil {
fmt.Printf("ERROR: error signing CSR or generating certificate: %s\n", err.Error())
pErr("error signing CSR or generating certificate: %s", err.Error())
return 1
}
cb, err := cert.Marshal()
if err != nil {
fmt.Printf("ERROR: error marshaling signed certificate: %s\n", err.Error())
pErr("error marshaling signed certificate: %s", err.Error())
return 1
}
err = ioutil.WriteFile(args[3], cb, 0644)
if err == nil {
fmt.Printf("Wrote signed certificate to %s\n", args[3])
pResult("%s", args[3])
} else {
fmt.Printf("ERROR: unable to write signed certificate to %s: %s\n", args[3], err.Error())
pErr("unable to write signed certificate to %s: %s", args[3], err.Error())
return 1
}
@ -144,16 +157,19 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
Help()
return 1
}
certBytes, err := ioutil.ReadFile(args[1])
if err != nil {
fmt.Printf("ERROR: unable to read certificate from %s: %s\n", args[1], err.Error())
pErr("unable to read certificate from %s: %s", args[1], err.Error())
return 1
}
cert, err := zerotier.NewCertificateFromBytes(certBytes, true)
if err != nil {
fmt.Printf("FAILED: certificate in %s invalid: %s\n", args[1], err.Error())
pErr("certificate in %s invalid: %s", args[1], err.Error())
return 1
}
if args[0] == "dump" {
fmt.Println(cert.JSON())
} else {

View file

@ -97,7 +97,6 @@ Advanced Operations:
cert <command> [args]
· list List certificates at local node
· show <serial> Show certificate details
newsubject <subject out> Interactive subject creation
newsid <secret out> Create a new subject unique ID
newcsr <subject|-> <secret> <csr out> Create a subject CSR
sign <csr> <identity> <cert out> Sign a CSR to create a certificate

View file

@ -43,11 +43,13 @@ func Identity(args []string) int {
return 1
}
}
id, err := zerotier.NewIdentity(idType)
if err != nil {
fmt.Printf("ERROR: internal error generating identity: %s\n", err.Error())
pErr("internal error generating identity: %s", err.Error())
return 1
}
fmt.Println(id.PrivateKeyString())
return 0
@ -56,20 +58,24 @@ func Identity(args []string) int {
fmt.Println(readIdentity(args[1]).String())
return 0
}
pErr("no identity specified")
return 1
case "fingerprint":
if len(args) == 2 {
fmt.Println(readIdentity(args[1]).Fingerprint().String())
return 0
}
pErr("no identity specified")
return 1
case "validate":
if len(args) == 2 {
if readIdentity(args[1]).LocallyValidate() {
fmt.Println("OK")
fmt.Println("VALID")
return 0
}
fmt.Println("FAILED")
fmt.Println("INVALID")
return 1
}
@ -78,7 +84,7 @@ func Identity(args []string) int {
id := readIdentity(args[1])
msg, err := ioutil.ReadFile(args[2])
if err != nil {
fmt.Printf("ERROR: unable to read input file: %s\n", err.Error())
pErr("unable to read input file: %s", err.Error())
return 1
}
@ -99,7 +105,7 @@ func Identity(args []string) int {
} else {
sig, err := id.Sign(msg)
if err != nil {
fmt.Printf("ERROR: internal error signing message: %s\n", err.Error())
pErr("internal error signing message: %s", err.Error())
return 1
}
fmt.Println(hex.EncodeToString(sig))

View file

@ -39,10 +39,17 @@ func Join(basePath string, authTokenGenerator func() string, args []string) int
Help()
return 1
}
if len(args[0]) != zerotier.NetworkIDStringLength {
fmt.Printf("ERROR: invalid network ID: %s\n", args[0])
if !isValidNetworkID(args[0]) {
pErr("invalid network ID: %s", args[0])
return 1
}
nwid, err := strconv.ParseUint(args[0], 16, 64)
if err != nil {
pErr("ERROR: invalid network ID: %s", args[0])
return 1
}
nwids := fmt.Sprintf("%.16x", nwid)
_ = *controllerAuthToken // TODO: not implemented yet
@ -51,32 +58,25 @@ func Join(basePath string, authTokenGenerator func() string, args []string) int
if strings.ContainsRune(*controllerFingerprint, '-') {
fp, err = zerotier.NewFingerprintFromString(*controllerFingerprint)
if err != nil {
fmt.Printf("ERROR: invalid network controller fingerprint: %s\n", *controllerFingerprint)
pErr("invalid network controller fingerprint: %s", *controllerFingerprint)
return 1
}
} else {
id, err := zerotier.NewIdentityFromString(*controllerFingerprint)
if err != nil {
fmt.Printf("ERROR: invalid network controller identity: %s\n", *controllerFingerprint)
pErr("invalid network controller identity: %s", *controllerFingerprint)
return 1
}
fp = id.Fingerprint()
}
}
nwid, err := strconv.ParseUint(args[0], 16, 64)
if err != nil {
fmt.Printf("ERROR: invalid network ID: %s\n", args[0])
return 1
}
nwids := fmt.Sprintf("%.16x", nwid)
var network zerotier.APINetwork
network.ID = zerotier.NetworkID(nwid)
network.ControllerFingerprint = fp
if apiPost(basePath, authToken, "/network/"+nwids, &network, nil) <= 0 {
fmt.Printf("FAILED\n")
fmt.Println("FAILED")
} else {
if fp == nil {
fmt.Printf("OK %s\n", nwids)

View file

@ -14,18 +14,26 @@
package cli
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"zerotier/pkg/zerotier"
)
func pErr(format string, args ...interface{}) {
_, _ = fmt.Fprintf(os.Stdout, "ERROR: "+format, args...)
fmt.Println()
}
func pResult(format string, args ...interface{}) {
_, _ = fmt.Printf(format, args...)
fmt.Println()
}
func apiGet(basePath, authToken, urlPath string, result interface{}) int64 {
statusCode, clock, err := zerotier.APIGet(basePath, zerotier.APISocketName, authToken, urlPath, result)
if err != nil {
@ -238,6 +246,7 @@ func isValidNetworkID(a string) bool {
return false
}
/*
func prompt(str string, dfl string) string {
if len(dfl) > 0 {
fmt.Printf("%s [%s]: ", str, dfl)
@ -274,3 +283,4 @@ func promptFile(str string) []byte {
}
return nil
}
*/

View file

@ -124,12 +124,12 @@ func Network(basePath string, authTokenGenerator func() string, args []string, j
}
if len(args[0]) != zerotier.NetworkIDStringLength {
fmt.Printf("ERROR: invalid network ID: %s\n", args[0])
pErr("ERROR: invalid network ID: %s", args[0])
return 1
}
nwid, err := strconv.ParseUint(args[0], 16, 64)
if err != nil {
fmt.Printf("ERROR: invalid network ID: %s\n", args[0])
pErr("ERROR: invalid network ID: %s", args[0])
return 1
}
nwids := fmt.Sprintf("%.16x", nwid)

View file

@ -0,0 +1,53 @@
/*
* 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: 2025-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 (
"fmt"
"zerotier/pkg/zerotier"
)
func TestLocator() bool {
fmt.Printf("Creating Endpoint instances... ")
ep0, err := zerotier.NewEndpointFromString("1.1.1.1/1")
if err != nil {
fmt.Printf("IPv4 FAILED (%s)\n",err.Error())
return false
}
ep1, err := zerotier.NewEndpointFromString("2600:1901:0:4006::1234/2")
if err != nil {
fmt.Printf("IPv6 FAILED (%s)\n",err.Error())
return false
}
eps := []*zerotier.Endpoint{ep0, ep1}
fmt.Printf("OK\n")
fmt.Printf("Creating signing Identity... ")
signer, err := zerotier.NewIdentity(zerotier.IdentityTypeP384)
if err != nil {
fmt.Printf("FAILED (%s)\n", err.Error())
return false
}
fmt.Printf("OK %s\n",signer.String())
fmt.Printf("Creating Locator instance... ")
loc, err := zerotier.NewLocator(zerotier.TimeMs(), eps, signer)
if err != nil {
fmt.Printf("FAILED (%s)\n",err.Error())
return false
}
fmt.Printf("OK %s\n",loc.String())
return true
}

View file

@ -13,4 +13,7 @@ func main() {
if !TestCertificate() {
os.Exit(1)
}
if !TestLocator() {
os.Exit(1)
}
}

View file

@ -111,7 +111,7 @@ func NewIdentityFromString(s string) (*Identity, error) {
}
case 1:
id.publicKey, err = Base32StdLowerCase.DecodeString(ss[2])
id.publicKey, err = Base32.DecodeString(ss[2])
if err != nil {
return nil, err
}
@ -119,7 +119,7 @@ func NewIdentityFromString(s string) (*Identity, error) {
return nil, ErrInvalidKey
}
if len(ss) >= 4 {
id.privateKey, err = Base32StdLowerCase.DecodeString(ss[3])
id.privateKey, err = Base32.DecodeString(ss[3])
if err != nil {
return nil, err
}
@ -190,7 +190,7 @@ func (id *Identity) PrivateKeyString() string {
}
case IdentityTypeP384:
if len(id.publicKey) == IdentityTypeP384PublicKeySize && len(id.privateKey) == IdentityTypeP384PrivateKeySize {
return fmt.Sprintf("%.10x:1:%s:%s", uint64(id.address), Base32StdLowerCase.EncodeToString(id.publicKey), Base32StdLowerCase.EncodeToString(id.privateKey))
return fmt.Sprintf("%.10x:1:%s:%s", uint64(id.address), Base32.EncodeToString(id.publicKey), Base32.EncodeToString(id.privateKey))
}
}
return ""
@ -206,7 +206,7 @@ func (id *Identity) String() string {
}
case IdentityTypeP384:
if len(id.publicKey) == IdentityTypeP384PublicKeySize {
return fmt.Sprintf("%.10x:1:%s", uint64(id.address), Base32StdLowerCase.EncodeToString(id.publicKey))
return fmt.Sprintf("%.10x:1:%s", uint64(id.address), Base32.EncodeToString(id.publicKey))
}
}
return ""

View file

@ -39,7 +39,7 @@ func newLocatorFromCLocator(cl unsafe.Pointer, needFinalizer bool) (*Locator, er
return loc, nil
}
func NewLocator(ts int64, endpoints []Endpoint, signer *Identity) (*Locator, error) {
func NewLocator(ts int64, endpoints []*Endpoint, signer *Identity) (*Locator, error) {
if ts <= 0 || len(endpoints) == 0 || signer == nil {
return nil, ErrInvalidParameter
}
@ -110,8 +110,8 @@ func (loc *Locator) String() string {
if loc.cl == nil {
return ""
}
var buf [4096]C.char
return C.GoString(C.ZT_Locator_toString(loc.cl, &buf[0], 4096))
var buf [16384]C.char // 16384 == ZT_LOCATOR_STRING_SIZE_MAX
return C.GoString(C.ZT_Locator_toString(loc.cl, &buf[0], 16384))
}
func (loc *Locator) MarshalJSON() ([]byte, error) {

View file

@ -35,8 +35,8 @@ const pointerSize = unsafe.Sizeof(uintptr(0))
// Base32Alphabet is the Base32 alphabet used in ZeroTier.
const Base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567"
// Base32 is an encoder using the ZeroTier base32 encoding.
var Base32 = base32.NewEncoding(Base32Alphabet)
// Base32 is an encoder using the ZeroTier base32 encoding and no padding (same as core).
var Base32 = base32.NewEncoding(Base32Alphabet).WithPadding(base32.NoPadding)
// unassignedPrivilegedPorts are ports below 1024 that do not appear to be assigned by IANA.
// The new 2.0+ ZeroTier default is 793, which we will eventually seek to have assigned. These