A whole bunch of minor refactoring, and rename a bunch of classes to be more canonical. A credential really is not a certficiate, so just call IdentificationCertificate Certificate and call the network auth stuff credentials.

This commit is contained in:
Adam Ierymenko 2020-06-18 17:02:36 -07:00
parent c348bfff30
commit cfc2a43f51
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
44 changed files with 654 additions and 606 deletions

View file

@ -30,8 +30,6 @@ if(WIN32)
set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE) set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
endif(WIN32) endif(WIN32)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X Deployment Version")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.") message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
@ -64,10 +62,25 @@ endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(WIN32) if(WIN32)
message("++ Setting Windows Compiler Flags ${CMAKE_BUILD_TYPE}") message("++ Setting Windows Compiler Flags ${CMAKE_BUILD_TYPE}")
add_definitions(-DNOMINMAX) add_definitions(-DNOMINMAX)
add_compile_options(
-Wall
-Wno-deprecated
-Wno-unused-function
-Wno-format
$<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-O3>
$<$<CONFIG:RELEASE>:-ffast-math>
$<$<CONFIG:RELWITHDEBINFO>:-O3>
$<$<CONFIG:RELWITHDEBINFO>:-g>
)
set(GOFLAGS set(GOFLAGS
-a
-trimpath -trimpath
-ldflags '-w'
) )
else(WIN32) else(WIN32)
@ -77,6 +90,8 @@ else(WIN32)
-buildmode=pie -buildmode=pie
) )
set(MACOS_VERSION_MIN "10.12")
if(APPLE) if(APPLE)
message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}") message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
@ -85,7 +100,7 @@ else(WIN32)
-Wall -Wall
-Wno-deprecated -Wno-deprecated
-Wno-unused-function -Wno-unused-function
-mmacosx-version-min=10.12 -mmacosx-version-min=${MACOS_VERSION_MIN}
$<$<CONFIG:DEBUG>:-g> $<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0> $<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-Ofast> $<$<CONFIG:RELEASE>:-Ofast>
@ -98,7 +113,7 @@ else(WIN32)
) )
add_link_options( add_link_options(
-mmacosx-version-min=10.12 -mmacosx-version-min=${MACOS_VERSION_MIN}
$<$<CONFIG:RELEASE>:-flto> $<$<CONFIG:RELEASE>:-flto>
) )
@ -111,6 +126,7 @@ else(WIN32)
else(APPLE) else(APPLE)
message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})") message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
add_compile_options( add_compile_options(
-Wall -Wall
-Wno-deprecated -Wno-deprecated
@ -186,7 +202,8 @@ add_subdirectory(serviceiocore)
file(GLOB go_src file(GLOB go_src
${CMAKE_SOURCE_DIR}/cmd/*.go ${CMAKE_SOURCE_DIR}/cmd/*.go
${CMAKE_SOURCE_DIR}/cmd/cmd/*.go ${CMAKE_SOURCE_DIR}/cmd/cmd/*.go
${CMAKE_SOURCE_DIR}/pkg/zerotier/*.go) ${CMAKE_SOURCE_DIR}/pkg/zerotier/*.go
)
if(WIN32) if(WIN32)
set(GO_EXE_NAME "zerotier.exe") set(GO_EXE_NAME "zerotier.exe")

View file

@ -17,8 +17,8 @@ LOCAL_CFLAGS := -DZT_USE_MINIUPNPC
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
$(ZT1)/node/C25519.cpp \ $(ZT1)/node/C25519.cpp \
$(ZT1)/node/Capability.cpp \ $(ZT1)/node/Capability.cpp \
$(ZT1)/node/CertificateOfMembership.cpp \ $(ZT1)/node/MembershipCredential.cpp \
$(ZT1)/node/CertificateOfOwnership.cpp \ $(ZT1)/node/OwnershipCredential.cpp \
$(ZT1)/node/Identity.cpp \ $(ZT1)/node/Identity.cpp \
$(ZT1)/node/IncomingPacket.cpp \ $(ZT1)/node/IncomingPacket.cpp \
$(ZT1)/node/InetAddress.cpp \ $(ZT1)/node/InetAddress.cpp \

View file

@ -3,3 +3,4 @@ mkdir build
cd build cd build
cmake .. -G "MinGW Makefiles" cmake .. -G "MinGW Makefiles"
make -j4 make -j4
cd ..

View file

@ -54,17 +54,16 @@ Commands:
peer <address> [command] [option] - Peer management commands peer <address> [command] [option] - Peer management commands
show Show peer details (default) show Show peer details (default)
try <endpoint> [...] Try peer at explicit endpoint try <endpoint> [...] Try peer at explicit endpoint
locator <locator> Explicitly update peer locator
roots List root peers
root [command] - Root management commands
add <identity | url> [endpoint] Add a root or a set of roots
remove <address | url | serial> Remove a root or set of roots
set [option] [value] - Get or set a core config option set [option] [value] - Get or set a core config option
port <port> Primary P2P port port <port> Primary P2P port
secondaryport <port/0> Secondary P2P port (0 to disable) secondaryport <port/0> Secondary P2P port (0 to disable)
blacklist cidr <IP/bits> <boolean> Toggle physical path blacklisting blacklist cidr <IP/bits> <boolean> Toggle physical path blacklisting
blacklist if <prefix> <boolean> Toggle interface prefix blacklisting blacklist if <prefix> <boolean> Toggle interface prefix blacklisting
portmap <boolean> Toggle use of uPnP or NAT-PMP portmap <boolean> Toggle use of uPnP or NAT-PMP
roots List root peers
root [command] - Root management commands
trust <identity | url> [endpoint] Add a root or a set of roots
remove <address | url | serial> Remove a root or set of roots
controller <command> [option] - Local controller management commands controller <command> [option] - Local controller management commands
networks List networks run by local controller networks List networks run by local controller
new Create a new network new Create a new network
@ -80,6 +79,7 @@ Commands:
validate <identity> Locally validate an identity validate <identity> Locally validate an identity
sign <identity> <file> Sign a file with an identity's key sign <identity> <file> Sign a file with an identity's key
verify <identity> <file> <sig> Verify a signature verify <identity> <file> <sig> Verify a signature
certificate <command> [args] - Certificate commands
An <address> may be specified as a 10-digit short ZeroTier address, a An <address> may be specified as a 10-digit short ZeroTier address, a
fingerprint containing both an address and a SHA384 hash, or an identity. fingerprint containing both an address and a SHA384 hash, or an identity.

View file

@ -25,7 +25,7 @@ import (
"zerotier/pkg/zerotier" "zerotier/pkg/zerotier"
) )
func Service(basePath, authToken string, args []string) { func Service(basePath string, args []string) {
if len(args) > 0 { if len(args) > 0 {
Help() Help()
os.Exit(1) os.Exit(1)

View file

@ -43,12 +43,40 @@ func getAuthTokenPaths(basePath string) (p []string) {
return p return p
} }
func authTokenRequired(authToken string) { func authTokenRequired(basePath, tflag, tTflag string) string {
authTokenPaths := getAuthTokenPaths(basePath)
var authToken string
if len(tflag) > 0 {
at, err := ioutil.ReadFile(tflag)
if err != nil || len(at) == 0 {
fmt.Println("FATAL: unable to read local service API authorization token from " + tflag)
os.Exit(1)
}
authToken = string(at)
} else if len(tTflag) > 0 {
authToken = tTflag
} else {
for _, p := range authTokenPaths {
tmp, _ := ioutil.ReadFile(p)
if len(tmp) > 0 {
authToken = string(tmp)
break
}
}
if len(authToken) == 0 {
fmt.Println("FATAL: unable to read local service API authorization token from any of:")
for _, p := range authTokenPaths {
fmt.Println(" " + p)
}
os.Exit(1)
}
}
authToken = strings.TrimSpace(authToken)
if len(authToken) == 0 { if len(authToken) == 0 {
fmt.Println("FATAL: unable to read API authorization token from command line or any filesystem location.") fmt.Println("FATAL: unable to read API authorization token from command line or any filesystem location.")
os.Exit(1) os.Exit(1)
} }
return authToken
} }
func main() { func main() {
@ -56,7 +84,7 @@ func main() {
// were doing a lot, but it's not. It just manages the core and is not directly involved // were doing a lot, but it's not. It just manages the core and is not directly involved
// in pushing a lot of packets around. If that ever changes this should be adjusted. // in pushing a lot of packets around. If that ever changes this should be adjusted.
runtime.GOMAXPROCS(1) runtime.GOMAXPROCS(1)
debug.SetGCPercent(20) debug.SetGCPercent(15)
globalOpts := flag.NewFlagSet("global", flag.ContinueOnError) globalOpts := flag.NewFlagSet("global", flag.ContinueOnError)
hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities
@ -80,89 +108,43 @@ func main() {
if len(args) > 1 { if len(args) > 1 {
cmdArgs = args[1:] cmdArgs = args[1:]
} }
basePath := zerotier.PlatformDefaultHomePath basePath := zerotier.PlatformDefaultHomePath
if len(*pflag) > 0 { if len(*pflag) > 0 {
basePath = *pflag basePath = *pflag
} }
authTokenPaths := getAuthTokenPaths(basePath)
var authToken string
if len(*tflag) > 0 {
at, err := ioutil.ReadFile(*tflag)
if err != nil || len(at) == 0 {
fmt.Println("FATAL: unable to read local service API authorization token from " + *tflag)
os.Exit(1)
}
authToken = string(at)
} else if len(*tTflag) > 0 {
authToken = *tTflag
} else {
for _, p := range authTokenPaths {
tmp, _ := ioutil.ReadFile(p)
if len(tmp) > 0 {
authToken = string(tmp)
break
}
}
if len(authToken) == 0 {
fmt.Println("FATAL: unable to read local service API authorization token from any of:")
for _, p := range authTokenPaths {
fmt.Println(" " + p)
}
os.Exit(1)
}
}
authToken = strings.TrimSpace(authToken)
switch args[0] { switch args[0] {
case "help": default:
//case "help":
cli.Help() cli.Help()
os.Exit(0)
case "version": case "version":
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision) fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
os.Exit(0)
case "service": case "service":
cli.Service(basePath, authToken, cmdArgs) cli.Service(basePath, cmdArgs)
case "status", "info": case "status", "info":
authTokenRequired(authToken) cli.Status(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
cli.Status(basePath, authToken, cmdArgs, *jflag)
case "join": case "join":
authTokenRequired(authToken) cli.Join(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
cli.Join(basePath, authToken, cmdArgs)
case "leave": case "leave":
authTokenRequired(authToken) cli.Leave(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
cli.Leave(basePath, authToken, cmdArgs)
case "networks", "listnetworks": case "networks", "listnetworks":
authTokenRequired(authToken) cli.Networks(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
cli.Networks(basePath, authToken, cmdArgs, *jflag)
case "network": case "network":
authTokenRequired(authToken) cli.Network(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
cli.Network(basePath, authToken, cmdArgs, *jflag)
case "peers", "listpeers", "lspeers": case "peers", "listpeers", "lspeers":
authTokenRequired(authToken) cli.Peers(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag, false)
cli.Peers(basePath, authToken, cmdArgs, *jflag, false)
case "peer": case "peer":
authTokenRequired(authToken) authTokenRequired(basePath, *tflag, *tTflag)
case "roots": case "roots":
authTokenRequired(authToken) cli.Peers(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag, true)
cli.Peers(basePath, authToken, cmdArgs, *jflag, true)
case "root": case "root":
authTokenRequired(authToken) cli.Root(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
cli.Root(basePath, authToken, cmdArgs, *jflag)
case "set": case "set":
authTokenRequired(authToken) cli.Set(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
cli.Set(basePath, authToken, cmdArgs)
case "controller": case "controller":
authTokenRequired(authToken) cli.Controller(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
cli.Controller(basePath, authToken, cmdArgs, *jflag)
case "identity": case "identity":
cli.Identity(cmdArgs) cli.Identity(cmdArgs)
} }
os.Exit(0)
// Commands in the 'cli' sub-package do not return, so if we make
// it here the command was not recognized.
cli.Help()
os.Exit(1)
} }

View file

@ -23,7 +23,7 @@
#include "../core/Constants.hpp" #include "../core/Constants.hpp"
#include "../core/Node.hpp" #include "../core/Node.hpp"
#include "../core/CertificateOfMembership.hpp" #include "../core/MembershipCredential.hpp"
#include "../core/NetworkConfig.hpp" #include "../core/NetworkConfig.hpp"
#include "../core/Dictionary.hpp" #include "../core/Dictionary.hpp"
#include "../core/MAC.hpp" #include "../core/MAC.hpp"
@ -1123,7 +1123,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const void *db,uint64_t ne
void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId) void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId)
{ {
const int64_t now = OSUtils::now(); const int64_t now = OSUtils::now();
Revocation rev((uint32_t)Utils::random(),networkId,0,now,ZT_REVOCATION_FLAG_FAST_PROPAGATE,Address(memberId),ZT_CREDENTIAL_TYPE_COM); RevocationCredential rev((uint32_t)Utils::random(), networkId, 0, now, ZT_REVOCATION_FLAG_FAST_PROPAGATE, Address(memberId), ZT_CREDENTIAL_TYPE_COM);
rev.sign(_signingId); rev.sign(_signingId);
{ {
std::lock_guard<std::mutex> l(_memberStatus_l); std::lock_guard<std::mutex> l(_memberStatus_l);
@ -1370,7 +1370,7 @@ void EmbeddedNetworkController::_request(
++caprc; ++caprc;
} }
} }
nc->capabilities[nc->capabilityCount] = Capability((uint32_t)capId,nwid,now,capr,caprc); nc->capabilities[nc->capabilityCount] = CapabilityCredential((uint32_t)capId, nwid, now, capr, caprc);
if (nc->capabilities[nc->capabilityCount].sign(_signingId,identity.address())) if (nc->capabilities[nc->capabilityCount].sign(_signingId,identity.address()))
++nc->capabilityCount; ++nc->capabilityCount;
if (nc->capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES) if (nc->capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES)
@ -1406,7 +1406,7 @@ void EmbeddedNetworkController::_request(
for(std::map< uint32_t,uint32_t >::const_iterator t(memberTagsById.begin());t!=memberTagsById.end();++t) { for(std::map< uint32_t,uint32_t >::const_iterator t(memberTagsById.begin());t!=memberTagsById.end();++t) {
if (nc->tagCount >= ZT_MAX_NETWORK_TAGS) if (nc->tagCount >= ZT_MAX_NETWORK_TAGS)
break; break;
nc->tags[nc->tagCount] = Tag(nwid,now,identity.address(),t->first,t->second); nc->tags[nc->tagCount] = TagCredential(nwid, now, identity.address(), t->first, t->second);
if (nc->tags[nc->tagCount].sign(_signingId)) if (nc->tags[nc->tagCount].sign(_signingId))
++nc->tagCount; ++nc->tagCount;
} }
@ -1609,14 +1609,14 @@ void EmbeddedNetworkController::_request(
// Issue a certificate of ownership for all static IPs // Issue a certificate of ownership for all static IPs
if (nc->staticIpCount) { if (nc->staticIpCount) {
nc->certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1); nc->certificatesOfOwnership[0] = OwnershipCredential(nwid, now, identity.address(), 1);
for(unsigned int i=0;i<nc->staticIpCount;++i) for(unsigned int i=0;i<nc->staticIpCount;++i)
nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]); nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]);
nc->certificatesOfOwnership[0].sign(_signingId); nc->certificatesOfOwnership[0].sign(_signingId);
nc->certificateOfOwnershipCount = 1; nc->certificateOfOwnershipCount = 1;
} }
CertificateOfMembership com(now,credentialtmd,nwid,identity); MembershipCredential com(now, credentialtmd, nwid, identity);
if (com.sign(_signingId)) { if (com.sign(_signingId)) {
nc->com = com; nc->com = com;
} else { } else {

View file

@ -136,37 +136,26 @@ public:
ZT_INLINE bool operator==(const Address &a) const noexcept ZT_INLINE bool operator==(const Address &a) const noexcept
{ return _a == a._a; } { return _a == a._a; }
ZT_INLINE bool operator!=(const Address &a) const noexcept ZT_INLINE bool operator!=(const Address &a) const noexcept
{ return _a != a._a; } { return _a != a._a; }
ZT_INLINE bool operator>(const Address &a) const noexcept ZT_INLINE bool operator>(const Address &a) const noexcept
{ return _a > a._a; } { return _a > a._a; }
ZT_INLINE bool operator<(const Address &a) const noexcept ZT_INLINE bool operator<(const Address &a) const noexcept
{ return _a < a._a; } { return _a < a._a; }
ZT_INLINE bool operator>=(const Address &a) const noexcept ZT_INLINE bool operator>=(const Address &a) const noexcept
{ return _a >= a._a; } { return _a >= a._a; }
ZT_INLINE bool operator<=(const Address &a) const noexcept ZT_INLINE bool operator<=(const Address &a) const noexcept
{ return _a <= a._a; } { return _a <= a._a; }
ZT_INLINE bool operator==(const uint64_t a) const noexcept ZT_INLINE bool operator==(const uint64_t a) const noexcept
{ return _a == a; } { return _a == a; }
ZT_INLINE bool operator!=(const uint64_t a) const noexcept ZT_INLINE bool operator!=(const uint64_t a) const noexcept
{ return _a != a; } { return _a != a; }
ZT_INLINE bool operator>(const uint64_t a) const noexcept ZT_INLINE bool operator>(const uint64_t a) const noexcept
{ return _a > a; } { return _a > a; }
ZT_INLINE bool operator<(const uint64_t a) const noexcept ZT_INLINE bool operator<(const uint64_t a) const noexcept
{ return _a < a; } { return _a < a; }
ZT_INLINE bool operator>=(const uint64_t a) const noexcept ZT_INLINE bool operator>=(const uint64_t a) const noexcept
{ return _a >= a; } { return _a >= a; }
ZT_INLINE bool operator<=(const uint64_t a) const noexcept ZT_INLINE bool operator<=(const uint64_t a) const noexcept
{ return _a <= a; } { return _a <= a; }

View file

@ -29,7 +29,10 @@ struct Blob
{ {
uint8_t data[S]; uint8_t data[S];
ZT_INLINE Blob() { Utils::zero<S>(data); } ZT_INLINE Blob() noexcept { Utils::zero<S>(data); }
explicit ZT_INLINE Blob(const void *const d) noexcept { Utils::copy<S>(data,d); }
ZT_INLINE operator bool() const noexcept { return !Utils::allZero(data); }
ZT_INLINE bool operator==(const Blob &b) const noexcept { return (memcmp(data,b.data,S) == 0); } ZT_INLINE bool operator==(const Blob &b) const noexcept { return (memcmp(data,b.data,S) == 0); }
ZT_INLINE bool operator!=(const Blob &b) const noexcept { return (memcmp(data,b.data,S) != 0); } ZT_INLINE bool operator!=(const Blob &b) const noexcept { return (memcmp(data,b.data,S) != 0); }

View file

@ -12,9 +12,10 @@ set(core_headers
Blob.hpp Blob.hpp
Buf.hpp Buf.hpp
C25519.hpp C25519.hpp
Capability.hpp CapabilityCredential.hpp
CertificateOfMembership.hpp Certificate.hpp
CertificateOfOwnership.hpp MembershipCredential.hpp
OwnershipCredential.hpp
Constants.hpp Constants.hpp
Containers.hpp Containers.hpp
Credential.hpp Credential.hpp
@ -25,13 +26,12 @@ set(core_headers
Expect.hpp Expect.hpp
FCV.hpp FCV.hpp
Fingerprint.hpp Fingerprint.hpp
IdentificationCertificate.hpp
Identity.hpp Identity.hpp
InetAddress.hpp InetAddress.hpp
Locator.hpp Locator.hpp
LZ4.hpp LZ4.hpp
MAC.hpp MAC.hpp
Membership.hpp Member.hpp
MulticastGroup.hpp MulticastGroup.hpp
Mutex.hpp Mutex.hpp
Network.hpp Network.hpp
@ -49,7 +49,7 @@ set(core_headers
SHA512.hpp SHA512.hpp
SharedPtr.hpp SharedPtr.hpp
SymmetricKey.hpp SymmetricKey.hpp
Tag.hpp TagCredential.hpp
Topology.hpp Topology.hpp
Trace.hpp Trace.hpp
TriviallyCopyable.hpp TriviallyCopyable.hpp
@ -62,30 +62,30 @@ set(core_src
AES.cpp AES.cpp
Buf.cpp Buf.cpp
C25519.cpp C25519.cpp
Capability.cpp CapabilityCredential.cpp
CertificateOfMembership.cpp Certificate.cpp
CertificateOfOwnership.cpp MembershipCredential.cpp
OwnershipCredential.cpp
Credential.cpp Credential.cpp
Dictionary.cpp Dictionary.cpp
ECC384.cpp ECC384.cpp
Endpoint.cpp Endpoint.cpp
IdentificationCertificate.cpp
Identity.cpp Identity.cpp
InetAddress.cpp InetAddress.cpp
Locator.cpp Locator.cpp
LZ4.cpp LZ4.cpp
Membership.cpp Member.cpp
Network.cpp Network.cpp
NetworkConfig.cpp NetworkConfig.cpp
Node.cpp Node.cpp
Path.cpp Path.cpp
Peer.cpp Peer.cpp
Poly1305.cpp Poly1305.cpp
Revocation.cpp RevocationCredential.cpp
Salsa20.cpp Salsa20.cpp
SelfAwareness.cpp SelfAwareness.cpp
SHA512.cpp SHA512.cpp
Tag.cpp TagCredential.cpp
Topology.cpp Topology.cpp
Trace.cpp Trace.cpp
Utils.cpp Utils.cpp

View file

@ -11,14 +11,14 @@
*/ */
/****/ /****/
#include "Capability.hpp" #include "CapabilityCredential.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Constants.hpp" #include "Constants.hpp"
#include "MAC.hpp" #include "MAC.hpp"
namespace ZeroTier { namespace ZeroTier {
bool Capability::sign(const Identity &from, const Address &to) noexcept bool CapabilityCredential::sign(const Identity &from, const Address &to) noexcept
{ {
uint8_t buf[ZT_CAPABILITY_MARSHAL_SIZE_MAX + 16]; uint8_t buf[ZT_CAPABILITY_MARSHAL_SIZE_MAX + 16];
m_issuedTo = to; m_issuedTo = to;
@ -27,7 +27,7 @@ bool Capability::sign(const Identity &from, const Address &to) noexcept
return m_signatureLength > 0; return m_signatureLength > 0;
} }
int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], const bool forSign) const noexcept int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], const bool forSign) const noexcept
{ {
int p = 0; int p = 0;
@ -45,7 +45,7 @@ int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], const bool
Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_ruleCount); Utils::storeBigEndian<uint16_t>(data + p, (uint16_t) m_ruleCount);
p += 2; p += 2;
p += Capability::marshalVirtualNetworkRules(data + p, m_rules, m_ruleCount); p += CapabilityCredential::marshalVirtualNetworkRules(data + p, m_rules, m_ruleCount);
// LEGACY: older versions supported multiple records with this being a maximum custody // LEGACY: older versions supported multiple records with this being a maximum custody
// chain length. This is deprecated so set the max chain length to one. // chain length. This is deprecated so set the max chain length to one.
@ -78,7 +78,7 @@ int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], const bool
return p; return p;
} }
int Capability::unmarshal(const uint8_t *data, int len) noexcept int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
{ {
if (len < 22) if (len < 22)
return -1; return -1;
@ -138,7 +138,7 @@ int Capability::unmarshal(const uint8_t *data, int len) noexcept
return p; return p;
} }
int Capability::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept int CapabilityCredential::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept
{ {
int p = 0; int p = 0;
for (unsigned int i = 0;i < ruleCount;++i) { for (unsigned int i = 0;i < ruleCount;++i) {
@ -273,7 +273,7 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetwor
return p; return p;
} }
int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data, const int len, ZT_VirtualNetworkRule *const rules, unsigned int &ruleCount, const unsigned int maxRuleCount) noexcept int CapabilityCredential::unmarshalVirtualNetworkRules(const uint8_t *const data, const int len, ZT_VirtualNetworkRule *const rules, unsigned int &ruleCount, const unsigned int maxRuleCount) noexcept
{ {
int p = 0; int p = 0;
unsigned int rc = 0; unsigned int rc = 0;

View file

@ -50,14 +50,14 @@ class RuntimeEnvironment;
* Note that this is after evaluation of network scope rules and only if * Note that this is after evaluation of network scope rules and only if
* network scope rules do not deliver an explicit match. * network scope rules do not deliver an explicit match.
*/ */
class Capability : public Credential class CapabilityCredential : public Credential
{ {
friend class Credential; friend class Credential;
public: public:
static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_CAPABILITY; } static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_CAPABILITY; }
ZT_INLINE Capability() noexcept { memoryZero(this); } ZT_INLINE CapabilityCredential() noexcept { memoryZero(this); }
/** /**
* @param id Capability ID * @param id Capability ID
@ -67,7 +67,7 @@ public:
* @param rules Network flow rules for this capability * @param rules Network flow rules for this capability
* @param ruleCount Number of flow rules * @param ruleCount Number of flow rules
*/ */
ZT_INLINE Capability(const uint32_t id,const uint64_t nwid,const int64_t ts,const ZT_VirtualNetworkRule *const rules,const unsigned int ruleCount) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE CapabilityCredential(const uint32_t id, const uint64_t nwid, const int64_t ts, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
m_nwid(nwid), m_nwid(nwid),
m_ts(ts), m_ts(ts),
m_id(id), m_id(id),
@ -145,10 +145,10 @@ public:
static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount) noexcept; static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount) noexcept;
// Provides natural sort order by ID // Provides natural sort order by ID
ZT_INLINE bool operator<(const Capability &c) const noexcept { return (m_id < c.m_id); } ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept { return (m_id < c.m_id); }
ZT_INLINE bool operator==(const Capability &c) const noexcept { return (memcmp(this,&c,sizeof(Capability)) == 0); } ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); }
ZT_INLINE bool operator!=(const Capability &c) const noexcept { return (memcmp(this,&c,sizeof(Capability)) != 0); } ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); }
private: private:
uint64_t m_nwid; uint64_t m_nwid;

View file

@ -11,118 +11,177 @@
*/ */
/****/ /****/
#include "IdentificationCertificate.hpp" #include "Certificate.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
namespace ZeroTier { namespace ZeroTier {
void IdentificationCertificate::clear() void Certificate::clear()
{ {
Utils::zero< sizeof(ZT_IdentificationCertificate) >((ZT_IdentificationCertificate *)this); Utils::zero< sizeof(ZT_Certificate) >((ZT_Certificate *)this);
m_identities.clear(); m_identities.clear();
m_locators.clear(); m_locators.clear();
m_strings.clear(); m_strings.clear();
m_nodes.clear(); m_serials.clear();
m_networks.clear();
m_subjectIdentities.clear();
m_subjectNetworks.clear();
m_updateUrls.clear(); m_updateUrls.clear();
m_subjectCertificates.clear();
} }
IdentificationCertificate &IdentificationCertificate::operator=(const ZT_IdentificationCertificate &apiCert) Certificate &Certificate::operator=(const ZT_Certificate &apiCert)
{ {
clear(); clear();
Utils::copy< sizeof(ZT_IdentificationCertificate) >((ZT_IdentificationCertificate *)this, &apiCert); Utils::copy< sizeof(ZT_Certificate) >((ZT_Certificate *)this, &apiCert);
return *this; return *this;
} }
IdentificationCertificate &IdentificationCertificate::operator=(const IdentificationCertificate &cert) Certificate &Certificate::operator=(const Certificate &cert)
{ {
*this = *((const ZT_IdentificationCertificate *)(&cert)); *this = *((const ZT_Certificate *)(&cert));
this->subject.nodeCount = 0; // Zero these since we must explicitly attach all the objects from
// the other certificate to copy them into our containers.
this->subject.identityCount = 0;
this->subject.networkCount = 0; this->subject.networkCount = 0;
this->subject.certificateCount = 0;
for (unsigned int i = 0; i < cert.subject.identityCount; ++i) {
if (cert.subject.identities[i].identity) {
if (cert.subject.identities[i].locator)
addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity), *reinterpret_cast<const Locator *>(cert.subject.identities[i].locator));
else addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.identities[i].identity));
}
}
for (unsigned int i = 0; i < cert.subject.networkCount; ++i) {
if (cert.subject.networks[i].id)
addSubjectNetwork(cert.subject.networks[i].id, cert.subject.networks[i].controller);
}
for (unsigned int i = 0; i < cert.subject.certificateCount; ++i) {
if (cert.subject.certificates[i])
addSubjectCertificate(cert.subject.certificates[i]);
}
if (cert.issuer) { if (cert.issuer) {
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer)); m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
this->issuer = reinterpret_cast<ZT_Identity *>(&(m_identities.back())); this->issuer = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
} }
for (unsigned int i = 0; i < cert.subject.nodeCount; ++i) {
if (cert.subject.nodes[i].locator)
addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.nodes[i].identity), *reinterpret_cast<const Locator *>(cert.subject.nodes[i].locator));
else if (cert.subject.nodes[i].identity)
addSubjectNode(*reinterpret_cast<const Identity *>(cert.subject.nodes[i].identity));
}
for (unsigned int i = 0; i < cert.subject.networkCount; ++i)
addSubjectNetwork(cert.subject.networks[i].id, cert.subject.networks[i].controller);
if (cert.updateUrls) { if (cert.updateUrls) {
for (unsigned int i = 0; i < cert.updateUrlCount; ++i) for (unsigned int i = 0; i < cert.updateUrlCount; ++i) {
addUpdateUrl(cert.updateUrls[i]); if (cert.updateUrls[i])
addUpdateUrl(cert.updateUrls[i]);
}
} }
return *this; return *this;
} }
ZT_IdentificationCertificate_Node *IdentificationCertificate::addSubjectNode(const Identity &id) ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id)
{ {
m_nodes.resize(++this->subject.nodeCount); // Enlarge array of ZT_Certificate_Identity structs and set pointer to potentially reallocated array.
this->subject.nodes = m_nodes.data(); m_subjectIdentities.resize(++this->subject.identityCount);
this->subject.identities = m_subjectIdentities.data();
// Store a local copy of the actual identity.
m_identities.push_back(id); m_identities.push_back(id);
m_nodes.back().identity = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
m_nodes.back().locator = nullptr; // Set ZT_Certificate_Identity struct fields to point to local copy of identity.
return &(m_nodes.back()); m_subjectIdentities.back().identity = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
m_subjectIdentities.back().locator = nullptr;
return &(m_subjectIdentities.back());
} }
ZT_IdentificationCertificate_Node *IdentificationCertificate::addSubjectNode(const Identity &id, const Locator &loc) ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id, const Locator &loc)
{ {
ZT_IdentificationCertificate_Node *n = addSubjectNode(id); // Add identity as above.
ZT_Certificate_Identity *const n = addSubjectNode(id);
// Store local copy of locator.
m_locators.push_back(loc); m_locators.push_back(loc);
// Set pointer to stored local copy of locator.
n->locator = reinterpret_cast<ZT_Locator *>(&(m_locators.back())); n->locator = reinterpret_cast<ZT_Locator *>(&(m_locators.back()));
return n; return n;
} }
ZT_IdentificationCertificate_Network *IdentificationCertificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller) ZT_Certificate_Network *Certificate::addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller)
{ {
m_networks.resize(++this->subject.networkCount); // Enlarge array of ZT_Certificate_Network and set pointer to potentially reallocated array.
this->subject.networks = m_networks.data(); m_subjectNetworks.resize(++this->subject.networkCount);
m_networks.back().id = id; this->subject.networks = m_subjectNetworks.data();
Utils::copy< sizeof(ZT_Fingerprint) >(&(m_networks.back().controller), &controller);
return &(m_networks.back()); // Set fields in new ZT_Certificate_Network structure.
m_subjectNetworks.back().id = id;
Utils::copy< sizeof(ZT_Fingerprint) >(&(m_subjectNetworks.back().controller), &controller);
return &(m_subjectNetworks.back());
} }
void IdentificationCertificate::addUpdateUrl(const char *url) void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE])
{ {
// Store local copy of serial in m_serials container.
m_serials.push_back(Blob< ZT_SHA384_DIGEST_SIZE >(serialNo));
// Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set
// certificates to point to potentially reallocated array.
m_subjectCertificates.resize(++this->subject.certificateCount);
m_subjectCertificates.back() = m_serials.back().data;
this->subject.certificates = m_subjectCertificates.data();
}
void Certificate::addUpdateUrl(const char *url)
{
// Store local copy of URL.
m_strings.push_back(url); m_strings.push_back(url);
// Add pointer to local copy to pointer array and update C structure to point to
// potentially reallocated array.
m_updateUrls.push_back(m_strings.back().c_str()); m_updateUrls.push_back(m_strings.back().c_str());
this->updateUrls = m_updateUrls.data(); this->updateUrls = m_updateUrls.data();
this->updateUrlCount = (unsigned int)m_updateUrls.size(); this->updateUrlCount = (unsigned int)m_updateUrls.size();
} }
Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) const Vector< uint8_t > Certificate::encode(const bool omitSignature) const
{ {
char tmp[256]; char tmp[256];
Vector< uint8_t > enc; Vector< uint8_t > enc;
Dictionary d; Dictionary d;
d.add("v", (uint64_t)this->version); // A Dictionary is used to encode certificates as it's a common and extensible
d.add("mP", (uint64_t)this->maxPathLength); // format. Custom packed formats are used for credentials as these are smaller
// and faster to marshal/unmarshal.
d.add("f", this->flags); d.add("f", this->flags);
d.add("v0", this->validity[0]); d.add("v0", this->validity[0]);
d.add("v1", this->validity[1]); d.add("v1", this->validity[1]);
d.add("mP", (uint64_t)this->maxPathLength);
d.add("s.n[]", (uint64_t)this->subject.nodeCount); d.add("s.i$", (uint64_t)this->subject.identityCount);
for (unsigned int i = 0; i < this->subject.nodeCount; ++i) { for (unsigned int i = 0; i < this->subject.identityCount; ++i) {
d.addO(Dictionary::arraySubscript(tmp, "s.n[].i", i), *reinterpret_cast<const Identity *>(this->subject.nodes[i].identity)); if (this->subject.identities[i].identity)
if (this->subject.nodes[i].locator) d.addO(Dictionary::arraySubscript(tmp, "s.i$.i", i), *reinterpret_cast<const Identity *>(this->subject.identities[i].identity));
d.addO(Dictionary::arraySubscript(tmp, "s.n[].l", i), *reinterpret_cast<const Locator *>(this->subject.nodes[i].locator)); if (this->subject.identities[i].locator)
d.addO(Dictionary::arraySubscript(tmp, "s.i$.l", i), *reinterpret_cast<const Locator *>(this->subject.identities[i].locator));
} }
d.add("s.nw[]", (uint64_t)this->subject.networkCount); d.add("s.n$", (uint64_t)this->subject.networkCount);
for (unsigned int i = 0; i < this->subject.networkCount; ++i) { for (unsigned int i = 0; i < this->subject.networkCount; ++i) {
d.add(Dictionary::arraySubscript(tmp, "s.nw[].i", i), this->subject.networks[i].id); d.add(Dictionary::arraySubscript(tmp, "s.n$.i", i), this->subject.networks[i].id);
Fingerprint fp(this->subject.networks[i].controller); Fingerprint fp(this->subject.networks[i].controller);
d.addO(Dictionary::arraySubscript(tmp, "s.nw[].c", i), fp); d.addO(Dictionary::arraySubscript(tmp, "s.n$.c", i), fp);
}
d.add("s.c$", (uint64_t)this->subject.certificateCount);
for (unsigned int i = 0; i < this->subject.certificateCount; ++i) {
if (this->subject.certificates[i])
d[Dictionary::arraySubscript(tmp, "s.c$", i)].assign(this->subject.certificates[i], this->subject.certificates[i] + ZT_SHA384_DIGEST_SIZE);
} }
d.add("s.n.c", this->subject.name.country); d.add("s.n.c", this->subject.name.country);
@ -152,10 +211,10 @@ Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) co
d.add("iN.e", this->issuerName.email); d.add("iN.e", this->issuerName.email);
d.add("iN.ur", this->issuerName.url); d.add("iN.ur", this->issuerName.url);
d.add("uU[]", (uint64_t)this->updateUrlCount); d.add("u$", (uint64_t)this->updateUrlCount);
if (this->updateUrls) { if (this->updateUrls) {
for (unsigned int i = 0; i < this->updateUrlCount; ++i) for (unsigned int i = 0; i < this->updateUrlCount; ++i)
d.add(Dictionary::arraySubscript(tmp, "uU[]", i), this->updateUrls[i]); d.add(Dictionary::arraySubscript(tmp, "u$", i), this->updateUrls[i]);
} }
if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature))) if ((!omitSignature) && (this->signatureSize > 0) && (this->signatureSize <= sizeof(this->signature)))
@ -165,9 +224,9 @@ Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) co
return enc; return enc;
} }
bool IdentificationCertificate::decode(const Vector< uint8_t > &data) bool Certificate::decode(const Vector< uint8_t > &data)
{ {
char tmp[256], tmp2[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char tmp[256], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
clear(); clear();
@ -175,21 +234,20 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
if (!d.decode(data.data(), (unsigned int)data.size())) if (!d.decode(data.data(), (unsigned int)data.size()))
return false; return false;
this->version = (unsigned int)d.getUI("v");
this->maxPathLength = (unsigned int)d.getUI("mP");
this->flags = d.getUI("f"); this->flags = d.getUI("f");
this->validity[0] = (int64_t)d.getUI("v0"); this->validity[0] = (int64_t)d.getUI("v0");
this->validity[1] = (int64_t)d.getUI("v1"); this->validity[1] = (int64_t)d.getUI("v1");
this->maxPathLength = (unsigned int)d.getUI("mP");
unsigned int cnt = (unsigned int)d.getUI("s.n[]"); unsigned int cnt = (unsigned int)d.getUI("s.i$");
for (unsigned int i = 0; i < cnt; ++i) { for (unsigned int i = 0; i < cnt; ++i) {
const Vector< uint8_t > &identityData = d[Dictionary::arraySubscript(tmp, "s.n[].i", i)]; const Vector< uint8_t > &identityData = d[Dictionary::arraySubscript(tmp, "s.i$.i", i)];
if (identityData.empty()) if (identityData.empty())
return false; return false;
Identity id; Identity id;
if (id.unmarshal(identityData.data(), (unsigned int)identityData.size()) <= 0) if (id.unmarshal(identityData.data(), (unsigned int)identityData.size()) <= 0)
return false; return false;
const Vector< uint8_t > &locatorData = d[Dictionary::arraySubscript(tmp, "s.n[].l", i)]; const Vector< uint8_t > &locatorData = d[Dictionary::arraySubscript(tmp, "s.i$.l", i)];
if (!locatorData.empty()) { if (!locatorData.empty()) {
Locator loc; Locator loc;
if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0) if (loc.unmarshal(locatorData.data(), (unsigned int)locatorData.size()) <= 0)
@ -200,13 +258,11 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
} }
} }
cnt = (unsigned int)d.getUI("s.nw[]"); cnt = (unsigned int)d.getUI("s.n$");
for (unsigned int i = 0; i < cnt; ++i) { for (unsigned int i = 0; i < cnt; ++i) {
const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.nw[].i", i)); const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.n$.i", i));
if (nwid == 0) const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.n$.c", i)];
return false; if ((nwid == 0) || (fingerprintData.empty()))
const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.nw[].c", i)];
if (fingerprintData.empty())
return false; return false;
Fingerprint fp; Fingerprint fp;
if (fp.unmarshal(fingerprintData.data(), (unsigned int)fingerprintData.size()) <= 0) if (fp.unmarshal(fingerprintData.data(), (unsigned int)fingerprintData.size()) <= 0)
@ -214,6 +270,14 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
this->addSubjectNetwork(nwid, fp); this->addSubjectNetwork(nwid, fp);
} }
cnt = (unsigned int)d.getUI("s.c$");
for (unsigned int i=0;i<cnt;++i) {
const Vector< uint8_t > &serial = d[Dictionary::arraySubscript(tmp, "s.c$", i)];
if (serial.size() != ZT_SHA384_DIGEST_SIZE)
return false;
this->addSubjectCertificate(serial.data());
}
d.getS("s.n.c", this->subject.name.country, sizeof(this->subject.name.country)); d.getS("s.n.c", this->subject.name.country, sizeof(this->subject.name.country));
d.getS("s.n.o", this->subject.name.organization, sizeof(this->subject.name.organization)); d.getS("s.n.o", this->subject.name.organization, sizeof(this->subject.name.organization));
d.getS("s.n.u", this->subject.name.unit, sizeof(this->subject.name.unit)); d.getS("s.n.u", this->subject.name.unit, sizeof(this->subject.name.unit));
@ -247,9 +311,9 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email)); d.getS("iN.e", this->issuerName.email, sizeof(this->issuerName.email));
d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url)); d.getS("iN.ur", this->issuerName.url, sizeof(this->issuerName.url));
cnt = (unsigned int)d.getUI("uU[]"); cnt = (unsigned int)d.getUI("u$");
for (unsigned int i = 0; i < cnt; ++i) { for (unsigned int i = 0; i < cnt; ++i) {
const char *const url = d.getS(Dictionary::arraySubscript(tmp, "uU[]", i), tmp2, sizeof(tmp2)); const char *const url = d.getS(Dictionary::arraySubscript(tmp, "u$", i), tmp2, sizeof(tmp2));
if (url) if (url)
addUpdateUrl(tmp2); addUpdateUrl(tmp2);
else return false; else return false;
@ -267,19 +331,21 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
return true; return true;
} }
bool IdentificationCertificate::sign(const Identity &issuer) bool Certificate::sign(const Identity &issuer)
{ {
Vector< uint8_t > enc(encode(true)); Vector< uint8_t > enc(encode(true));
SHA384(this->serialNo, enc.data(), (unsigned int)enc.size()); SHA384(this->serialNo, enc.data(), (unsigned int)enc.size());
return (this->signatureSize = issuer.sign(enc.data(), (unsigned int)enc.size(), this->signature, sizeof(this->signature))) > 0; return (this->signatureSize = issuer.sign(enc.data(), (unsigned int)enc.size(), this->signature, sizeof(this->signature))) > 0;
} }
bool IdentificationCertificate::verify() const bool Certificate::verify() const
{ {
if (this->issuer) { try {
Vector< uint8_t > enc(encode(true)); if (this->issuer) {
return reinterpret_cast<const Identity *>(this->issuer)->verify(enc.data(), (unsigned int)enc.size(), this->signature, this->signatureSize); Vector< uint8_t > enc(encode(true));
} return reinterpret_cast<const Identity *>(this->issuer)->verify(enc.data(), (unsigned int)enc.size(), this->signature, this->signatureSize);
}
} catch ( ... ) {}
return false; return false;
} }

View file

@ -11,8 +11,8 @@
*/ */
/****/ /****/
#ifndef ZT_IDENTIFICATIONCERTIFICATE_HPP #ifndef ZT_CERTIFICATE_HPP
#define ZT_IDENTIFICATIONCERTIFICATE_HPP #define ZT_CERTIFICATE_HPP
#include "Constants.hpp" #include "Constants.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"
@ -23,12 +23,13 @@
#include "Locator.hpp" #include "Locator.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Blob.hpp"
#include "Containers.hpp" #include "Containers.hpp"
namespace ZeroTier { namespace ZeroTier {
/** /**
* Certificate identifying the real world owner of an identity or network. * Certificate describing and grouping a set of objects.
* *
* This is a wrapper around the straight C ZT_IdentificationCertificate and * This is a wrapper around the straight C ZT_IdentificationCertificate and
* handles allocating memory for objects added via addXXX() and disposing of * handles allocating memory for objects added via addXXX() and disposing of
@ -44,16 +45,16 @@ namespace ZeroTier {
* field, so these will not work correctly before sign() or decode() is * field, so these will not work correctly before sign() or decode() is
* called. * called.
*/ */
class IdentificationCertificate : public ZT_IdentificationCertificate class Certificate : public ZT_Certificate
{ {
public: public:
ZT_INLINE IdentificationCertificate() noexcept ZT_INLINE Certificate() noexcept
{ this->clear(); } { this->clear(); }
ZT_INLINE IdentificationCertificate(const ZT_IdentificationCertificate &apiCert) ZT_INLINE Certificate(const ZT_Certificate &apiCert)
{ *this = apiCert; } { *this = apiCert; }
ZT_INLINE IdentificationCertificate(const IdentificationCertificate &cert) ZT_INLINE Certificate(const Certificate &cert)
{ *this = cert; } { *this = cert; }
/** /**
@ -61,9 +62,9 @@ public:
*/ */
void clear(); void clear();
IdentificationCertificate &operator=(const ZT_IdentificationCertificate &apiCert); Certificate &operator=(const ZT_Certificate &apiCert);
IdentificationCertificate &operator=(const IdentificationCertificate &cert); Certificate &operator=(const Certificate &cert);
/** /**
* Add a subject node/identity without a locator * Add a subject node/identity without a locator
@ -71,7 +72,7 @@ public:
* @param id Identity * @param id Identity
* @return Pointer to C struct * @return Pointer to C struct
*/ */
ZT_IdentificationCertificate_Node *addSubjectNode(const Identity &id); ZT_Certificate_Identity *addSubjectNode(const Identity &id);
/** /**
* Add a subject node/identity with a locator * Add a subject node/identity with a locator
@ -80,7 +81,7 @@ public:
* @param loc Locator signed by identity (signature is NOT checked here) * @param loc Locator signed by identity (signature is NOT checked here)
* @return Pointer to C struct * @return Pointer to C struct
*/ */
ZT_IdentificationCertificate_Node *addSubjectNode(const Identity &id, const Locator &loc); ZT_Certificate_Identity *addSubjectNode(const Identity &id, const Locator &loc);
/** /**
* Add a subject network * Add a subject network
@ -89,7 +90,14 @@ public:
* @param controller Network controller's full fingerprint * @param controller Network controller's full fingerprint
* @return Pointer to C struct * @return Pointer to C struct
*/ */
ZT_IdentificationCertificate_Network *addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller); ZT_Certificate_Network *addSubjectNetwork(const uint64_t id, const ZT_Fingerprint &controller);
/**
* Add a subject certificate (by its serial number)
*
* @param serialNo 384-bit serial number
*/
void addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_SIZE]);
/** /**
* Add an update URL to the updateUrls list * Add an update URL to the updateUrls list
@ -135,22 +143,22 @@ public:
ZT_INLINE unsigned long hashCode() const noexcept ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long)Utils::loadAsIsEndian< uint32_t >(this->serialNo); } { return (unsigned long)Utils::loadAsIsEndian< uint32_t >(this->serialNo); }
ZT_INLINE bool operator==(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator==(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) == 0; }
ZT_INLINE bool operator!=(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator!=(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) != 0; }
ZT_INLINE bool operator<(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator<(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) < 0; }
ZT_INLINE bool operator<=(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator<=(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) <= 0; }
ZT_INLINE bool operator>(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator>(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) > 0; }
ZT_INLINE bool operator>=(const ZT_IdentificationCertificate &c) const noexcept ZT_INLINE bool operator>=(const ZT_Certificate &c) const noexcept
{ return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; } { return memcmp(this->serialNo, c.serialNo, ZT_SHA384_DIGEST_SIZE) >= 0; }
private: private:
@ -160,10 +168,12 @@ private:
List< Identity > m_identities; List< Identity > m_identities;
List< Locator > m_locators; List< Locator > m_locators;
List< String > m_strings; List< String > m_strings;
List< Blob< ZT_SHA384_DIGEST_SIZE > > m_serials;
// These are stored in a vector because the memory needs to be contiguous. // These are stored in a vector because the memory needs to be contiguous.
Vector< ZT_IdentificationCertificate_Node > m_nodes; Vector< ZT_Certificate_Identity > m_subjectIdentities;
Vector< ZT_IdentificationCertificate_Network > m_networks; Vector< ZT_Certificate_Network > m_subjectNetworks;
Vector< const uint8_t * > m_subjectCertificates;
Vector< const char * > m_updateUrls; Vector< const char * > m_updateUrls;
}; };

View file

@ -11,8 +11,8 @@
*/ */
/****/ /****/
#ifndef ZT_MAP_HPP #ifndef ZT_CONTAINERS_HPP
#define ZT_MAP_HPP #define ZT_CONTAINERS_HPP
/* This defines a Map, SortedMap, Vector, etc. based on STL templates. */ /* This defines a Map, SortedMap, Vector, etc. based on STL templates. */
@ -40,51 +40,40 @@ struct intl_MapHasher
template< typename O > template< typename O >
std::size_t operator()(const O &obj) const noexcept std::size_t operator()(const O &obj) const noexcept
{ return (std::size_t)obj.hashCode(); } { return (std::size_t)obj.hashCode(); }
std::size_t operator()(const uint64_t i) const noexcept std::size_t operator()(const uint64_t i) const noexcept
{ return (std::size_t)Utils::hash64(i + Utils::s_mapNonce); } { return (std::size_t)Utils::hash64(i + Utils::s_mapNonce); }
std::size_t operator()(const int64_t i) const noexcept std::size_t operator()(const int64_t i) const noexcept
{ return (std::size_t)Utils::hash64((uint64_t)i + Utils::s_mapNonce); } { return (std::size_t)Utils::hash64((uint64_t)i + Utils::s_mapNonce); }
std::size_t operator()(const uint32_t i) const noexcept std::size_t operator()(const uint32_t i) const noexcept
{ return (std::size_t)Utils::hash32(i + (uint32_t)Utils::s_mapNonce); } { return (std::size_t)Utils::hash32(i + (uint32_t)Utils::s_mapNonce); }
std::size_t operator()(const int32_t i) const noexcept std::size_t operator()(const int32_t i) const noexcept
{ return (std::size_t)Utils::hash32((uint32_t)i + (uint32_t)Utils::s_mapNonce); } { return (std::size_t)Utils::hash32((uint32_t)i + (uint32_t)Utils::s_mapNonce); }
}; };
template< typename K, typename V > template< typename K, typename V >
class Map : public std::unordered_map< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, V > > class Map : public std::unordered_map< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, V > > >
{
> {
public: public:
ZT_INLINE V *get(const K &key) noexcept ZT_INLINE V *get(const K &key) noexcept
{ {
typename Map::iterator i(this->find(key)); typename Map::iterator i(this->find(key));
if (i == this->end()) if (i == this->end())
return nullptr; return nullptr;
return &(i->second); return &(i->second);
} }
ZT_INLINE const V *get(const K &key) const noexcept
ZT_INLINE const V *get(const K &key) const noexcept {
{ typename Map::const_iterator i(this->find(key));
typename Map::const_iterator i(this->find(key)); if (i == this->end())
if (i == this->end()) return nullptr;
return nullptr; return &(i->second);
return &(i->second); }
} ZT_INLINE void set(const K &key, const V &value) { this->emplace(key, value); }
ZT_INLINE void set(const K &key, const V &value)
{ this->emplace(key, value); }
}; };
template< typename K, typename V > template< typename K, typename V >
class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, V > > class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K >, Utils::Mallocator < std::pair< const K, V > > >
{};
>
{
};
#else #else
@ -120,103 +109,54 @@ class MultiMap : public std::multimap< K,V,std::less<K>,Utils::Mallocator< std::
#endif #endif
template< typename K, typename V > template< typename K, typename V >
class SortedMap : public std::map< K, V, std::less< K >, Utils::Mallocator < std::pair< const K, V > > class SortedMap : public std::map< K, V, std::less< K >, Utils::Mallocator < std::pair< const K, V > > >
>
{ {
public: public:
ZT_INLINE V *get(const K &key) noexcept ZT_INLINE V *get(const K &key) noexcept
{ {
typename SortedMap::iterator i(this->find(key)); typename SortedMap::iterator i(this->find(key));
if (i == this->end()) if (i == this->end())
return nullptr; return nullptr;
return &(i->second); return &(i->second);
} }
ZT_INLINE const V *get(const K &key) const noexcept
ZT_INLINE const V *get(const K &key) const noexcept {
{ typename SortedMap::const_iterator i(this->find(key));
typename SortedMap::const_iterator i(this->find(key)); if (i == this->end())
if (i == this->end()) return nullptr;
return nullptr; return &(i->second);
return &(i->second); }
} ZT_INLINE void set(const K &key, const V &value) { (*this)[key] = value; }
ZT_INLINE void set(const K &key, const V &value)
{ (*this)[key] = value; }
}; };
template< typename V > template< typename V >
class Vector : public std::vector< V, Utils::Mallocator < V > class Vector : public std::vector< V, Utils::Mallocator < V > >
>
{ {
public: public:
ZT_INLINE Vector() ZT_INLINE Vector() {}
{} template< typename I >
ZT_INLINE Vector(I begin,I end) : std::vector< V, Utils::Mallocator < V > >(begin,end) {}
template< typename I >
ZT_INLINE Vector(I
begin,
I end
) : std::vector< V, Utils::Mallocator < V > >(begin,end) {
}
}; };
template< typename V > template< typename V >
class List : public std::list< V, Utils::Mallocator < V > class List : public std::list< V, Utils::Mallocator < V > >
>
{ {
}; };
template< typename V > template< typename V >
class Set : public std::set< V, std::less< V >, Utils::Mallocator < V > class Set : public std::set< V, std::less< V >, Utils::Mallocator < V > >
>
{ {
}; };
class String : public std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > class String : public std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >
>
{ {
public: public:
ZT_INLINE String() ZT_INLINE String() {}
{} ZT_INLINE String(const String &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s.c_str()) {}
ZT_INLINE String(const std::string &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s.c_str()) {}
ZT_INLINE String(const String &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > ZT_INLINE String(const char *const s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char > >(s) {}
ZT_INLINE String &operator=(const char *const s) { assign(s); return *this; }
>(s. ZT_INLINE String &operator=(const std::string &s) { assign(s.c_str()); return *this; }
c_str()
) {
}
ZT_INLINE String(const std::string &s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char >
>(s.
c_str()
) {
}
ZT_INLINE String(const char *const s) : std::basic_string< char, std::char_traits< char >, Utils::Mallocator < char >
>(s) {
}
ZT_INLINE String &operator=(const char *const s)
{
assign(s);
return *this;
}
ZT_INLINE String &operator=(const std::string &s)
{
assign(s.c_str());
return *this;
}
}; };
} // ZeroTier } // ZeroTier

View file

@ -14,11 +14,11 @@
#include "Constants.hpp" #include "Constants.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Credential.hpp" #include "Credential.hpp"
#include "Capability.hpp" #include "CapabilityCredential.hpp"
#include "Tag.hpp" #include "TagCredential.hpp"
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
#include "CertificateOfOwnership.hpp" #include "OwnershipCredential.hpp"
#include "Revocation.hpp" #include "RevocationCredential.hpp"
#include "Network.hpp" #include "Network.hpp"
#include "Topology.hpp" #include "Topology.hpp"
@ -66,12 +66,12 @@ static ZT_INLINE Credential::VerifyResult _credVerify(const RuntimeEnvironment *
return Credential::VERIFY_BAD_SIGNATURE; return Credential::VERIFY_BAD_SIGNATURE;
} }
Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const Revocation &credential) const { return _credVerify(RR,tPtr,credential); } Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const RevocationCredential &credential) const { return _credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const Tag &credential) const { return _credVerify(RR,tPtr,credential); } Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const TagCredential &credential) const { return _credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const Capability &credential) const { return _credVerify(RR,tPtr,credential); } Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const CapabilityCredential &credential) const { return _credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const CertificateOfOwnership &credential) const { return _credVerify(RR,tPtr,credential); } Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const OwnershipCredential &credential) const { return _credVerify(RR, tPtr, credential); }
Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const CertificateOfMembership &credential) const Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,void *tPtr,const MembershipCredential &credential) const
{ {
// Sanity check network ID. // Sanity check network ID.
if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId))) if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))

View file

@ -23,11 +23,11 @@
namespace ZeroTier { namespace ZeroTier {
class Capability; class CapabilityCredential;
class Revocation; class RevocationCredential;
class Tag; class TagCredential;
class CertificateOfMembership; class MembershipCredential;
class CertificateOfOwnership; class OwnershipCredential;
class RuntimeEnvironment; class RuntimeEnvironment;
/** /**
@ -52,11 +52,11 @@ public:
}; };
protected: protected:
VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const CertificateOfMembership &credential) const; VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const MembershipCredential &credential) const;
VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Revocation &credential) const; VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const RevocationCredential &credential) const;
VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Tag &credential) const; VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const TagCredential &credential) const;
VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const CertificateOfOwnership &credential) const; VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const OwnershipCredential &credential) const;
VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const Capability &credential) const; VerifyResult _verify(const RuntimeEnvironment *RR,void *tPtr,const CapabilityCredential &credential) const;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -431,7 +431,10 @@ private:
return buf; return buf;
} }
SortedMap <String, Vector< uint8_t >> m_entries; // Dictionary maps need to be sorted so that they always encode in the same order
// to yield blobs that can be hashed and signed reproducibly. Other than for areas
// where dictionaries are signed and verified the order doesn't matter.
SortedMap < String, Vector< uint8_t > > m_entries;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -49,9 +49,7 @@ public:
* @param now Current time * @param now Current time
*/ */
ZT_INLINE void sending(const uint64_t packetId, const int64_t now) noexcept ZT_INLINE void sending(const uint64_t packetId, const int64_t now) noexcept
{ { m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].store((uint32_t)(now / ZT_EXPECT_TTL)); }
m_packetIdSent[Utils::hash64(packetId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].store((uint32_t)(now / ZT_EXPECT_TTL));
}
/** /**
* Check if an OK is expected and if so reset the corresponding bucket. * Check if an OK is expected and if so reset the corresponding bucket.
@ -64,9 +62,7 @@ public:
* @return True if we're expecting a reply (and a reset occurred) * @return True if we're expecting a reply (and a reset occurred)
*/ */
ZT_INLINE bool expecting(const uint64_t inRePacketId, const int64_t now) noexcept ZT_INLINE bool expecting(const uint64_t inRePacketId, const int64_t now) noexcept
{ { return (((now / ZT_EXPECT_TTL) - (int64_t)m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1); }
return (((now / ZT_EXPECT_TTL) - (int64_t)m_packetIdSent[(unsigned long)Utils::hash64(inRePacketId ^ Utils::s_mapNonce) % ZT_EXPECT_BUCKETS].exchange(0)) <= 1);
}
private: private:
// Each bucket contains a timestamp in units of the max expect duration. // Each bucket contains a timestamp in units of the max expect duration.

View file

@ -222,27 +222,20 @@ public:
ZT_INLINE bool operator==(const Identity &id) const noexcept ZT_INLINE bool operator==(const Identity &id) const noexcept
{ return (m_fp == id.m_fp); } { return (m_fp == id.m_fp); }
ZT_INLINE bool operator!=(const Identity &id) const noexcept ZT_INLINE bool operator!=(const Identity &id) const noexcept
{ return !(*this == id); } { return !(*this == id); }
ZT_INLINE bool operator<(const Identity &id) const noexcept ZT_INLINE bool operator<(const Identity &id) const noexcept
{ return (m_fp < id.m_fp); } { return (m_fp < id.m_fp); }
ZT_INLINE bool operator>(const Identity &id) const noexcept ZT_INLINE bool operator>(const Identity &id) const noexcept
{ return (id < *this); } { return (id < *this); }
ZT_INLINE bool operator<=(const Identity &id) const noexcept ZT_INLINE bool operator<=(const Identity &id) const noexcept
{ return !(id < *this); } { return !(id < *this); }
ZT_INLINE bool operator>=(const Identity &id) const noexcept ZT_INLINE bool operator>=(const Identity &id) const noexcept
{ return !(*this < id); } { return !(*this < id); }
static constexpr int marshalSizeMax() noexcept static constexpr int marshalSizeMax() noexcept
{ return ZT_IDENTITY_MARSHAL_SIZE_MAX; } { return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], bool includePrivate = false) const noexcept; int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], bool includePrivate = false) const noexcept;
int unmarshal(const uint8_t *data, int len) noexcept; int unmarshal(const uint8_t *data, int len) noexcept;
private: private:

View file

@ -62,9 +62,7 @@ public:
* @param len Length, must be >= 6 or result is zero * @param len Length, must be >= 6 or result is zero
*/ */
ZT_INLINE void setTo(const uint8_t b[6]) noexcept ZT_INLINE void setTo(const uint8_t b[6]) noexcept
{ { m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5]; }
m_mac = ((uint64_t)b[0] << 40U) | ((uint64_t)b[1] << 32U) | ((uint64_t)b[2] << 24U) | ((uint64_t)b[3] << 16U) | ((uint64_t)b[4] << 8U) | (uint64_t)b[5];
}
/** /**
* @param buf Destination buffer for MAC in big-endian byte order * @param buf Destination buffer for MAC in big-endian byte order
@ -221,44 +219,30 @@ public:
} }
ZT_INLINE MAC &operator=(const uint64_t m) noexcept ZT_INLINE MAC &operator=(const uint64_t m) noexcept
{ { m_mac = m; return *this; }
m_mac = m;
return *this;
}
ZT_INLINE bool operator==(const MAC &m) const noexcept ZT_INLINE bool operator==(const MAC &m) const noexcept
{ return (m_mac == m.m_mac); } { return (m_mac == m.m_mac); }
ZT_INLINE bool operator!=(const MAC &m) const noexcept ZT_INLINE bool operator!=(const MAC &m) const noexcept
{ return (m_mac != m.m_mac); } { return (m_mac != m.m_mac); }
ZT_INLINE bool operator<(const MAC &m) const noexcept ZT_INLINE bool operator<(const MAC &m) const noexcept
{ return (m_mac < m.m_mac); } { return (m_mac < m.m_mac); }
ZT_INLINE bool operator<=(const MAC &m) const noexcept ZT_INLINE bool operator<=(const MAC &m) const noexcept
{ return (m_mac <= m.m_mac); } { return (m_mac <= m.m_mac); }
ZT_INLINE bool operator>(const MAC &m) const noexcept ZT_INLINE bool operator>(const MAC &m) const noexcept
{ return (m_mac > m.m_mac); } { return (m_mac > m.m_mac); }
ZT_INLINE bool operator>=(const MAC &m) const noexcept ZT_INLINE bool operator>=(const MAC &m) const noexcept
{ return (m_mac >= m.m_mac); } { return (m_mac >= m.m_mac); }
ZT_INLINE bool operator==(const uint64_t m) const noexcept ZT_INLINE bool operator==(const uint64_t m) const noexcept
{ return (m_mac == m); } { return (m_mac == m); }
ZT_INLINE bool operator!=(const uint64_t m) const noexcept ZT_INLINE bool operator!=(const uint64_t m) const noexcept
{ return (m_mac != m); } { return (m_mac != m); }
ZT_INLINE bool operator<(const uint64_t m) const noexcept ZT_INLINE bool operator<(const uint64_t m) const noexcept
{ return (m_mac < m); } { return (m_mac < m); }
ZT_INLINE bool operator<=(const uint64_t m) const noexcept ZT_INLINE bool operator<=(const uint64_t m) const noexcept
{ return (m_mac <= m); } { return (m_mac <= m); }
ZT_INLINE bool operator>(const uint64_t m) const noexcept ZT_INLINE bool operator>(const uint64_t m) const noexcept
{ return (m_mac > m); } { return (m_mac > m); }
ZT_INLINE bool operator>=(const uint64_t m) const noexcept ZT_INLINE bool operator>=(const uint64_t m) const noexcept
{ return (m_mac >= m); } { return (m_mac >= m); }

View file

@ -13,14 +13,14 @@
#include <algorithm> #include <algorithm>
#include "Membership.hpp" #include "Member.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Peer.hpp" #include "Peer.hpp"
#include "Topology.hpp" #include "Topology.hpp"
namespace ZeroTier { namespace ZeroTier {
Membership::Membership() : Member::Member() :
m_comRevocationThreshold(0), m_comRevocationThreshold(0),
m_lastPushedCredentials(0), m_lastPushedCredentials(0),
m_comAgreementLocalTimestamp(0), m_comAgreementLocalTimestamp(0),
@ -28,14 +28,14 @@ Membership::Membership() :
{ {
} }
void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const SharedPtr<Peer> &to,const NetworkConfig &nconf) void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int64_t now, const SharedPtr<Peer> &to, const NetworkConfig &nconf)
{ {
if (!nconf.com) // sanity check if (!nconf.com) // sanity check
return; return;
#if 0 #if 0
SharedPtr<Buf> outp(new Buf()); SharedPtr<Buf> outp(new Buf());
Protocol::Header &ph = outp->as<Protocol::Header>(); // NOLINT(hicpp-use-auto,modernize-use-auto) Protocol::Header &ph = outp->as<Protocol::Header>();
unsigned int capPtr = 0,tagPtr = 0,cooPtr = 0; unsigned int capPtr = 0,tagPtr = 0,cooPtr = 0;
bool sendCom = true; bool sendCom = true;
@ -115,14 +115,14 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
m_lastPushedCredentials = now; m_lastPushedCredentials = now;
} }
void Membership::clean(const int64_t now,const NetworkConfig &nconf) void Member::clean(const int64_t now, const NetworkConfig &nconf)
{ {
m_cleanCredImpl<Tag>(nconf, m_remoteTags); m_cleanCredImpl<TagCredential>(nconf, m_remoteTags);
m_cleanCredImpl<Capability>(nconf, m_remoteCaps); m_cleanCredImpl<CapabilityCredential>(nconf, m_remoteCaps);
m_cleanCredImpl<CertificateOfOwnership>(nconf, m_remoteCoos); m_cleanCredImpl<OwnershipCredential>(nconf, m_remoteCoos);
} }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfMembership &com) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com)
{ {
const int64_t newts = com.timestamp(); const int64_t newts = com.timestamp();
if (newts <= m_comRevocationThreshold) { if (newts <= m_comRevocationThreshold) {
@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
switch(com.verify(RR,tPtr)) { switch(com.verify(RR,tPtr)) {
default: default:
RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(tPtr,0x0f198241,com.networkId(),sourcePeerIdentity,com.id(),com.timestamp(),ZT_CREDENTIAL_TYPE_COM,ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
case Credential::VERIFY_OK: case Credential::VERIFY_OK:
m_com = com; m_com = com;
return ADD_ACCEPTED_NEW; return ADD_ACCEPTED_NEW;
@ -155,7 +155,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
// 3/5 of the credential types have identical addCredential() code // 3/5 of the credential types have identical addCredential() code
template<typename C> template<typename C>
static ZT_INLINE Membership::AddCredentialResult _addCredImpl( static ZT_INLINE Member::AddCredentialResult _addCredImpl(
Map<uint32_t,C> &remoteCreds, Map<uint32_t,C> &remoteCreds,
const Map<uint64_t,int64_t> &revocations, const Map<uint64_t,int64_t> &revocations,
const RuntimeEnvironment *const RR, const RuntimeEnvironment *const RR,
@ -168,36 +168,36 @@ static ZT_INLINE Membership::AddCredentialResult _addCredImpl(
if (rc) { if (rc) {
if (rc->timestamp() > cred.timestamp()) { if (rc->timestamp() > cred.timestamp()) {
RR->t->credentialRejected(tPtr,0x40000001,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); RR->t->credentialRejected(tPtr,0x40000001,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST);
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
} }
if (*rc == cred) if (*rc == cred)
return Membership::ADD_ACCEPTED_REDUNDANT; return Member::ADD_ACCEPTED_REDUNDANT;
} }
const int64_t *const rt = revocations.get(Membership::credentialKey(C::credentialType(),cred.id())); const int64_t *const rt = revocations.get(Member::credentialKey(C::credentialType(), cred.id()));
if ((rt)&&(*rt >= cred.timestamp())) { if ((rt)&&(*rt >= cred.timestamp())) {
RR->t->credentialRejected(tPtr,0x24248124,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); RR->t->credentialRejected(tPtr,0x24248124,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED);
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
} }
switch(cred.verify(RR,tPtr)) { switch(cred.verify(RR,tPtr)) {
default: default:
RR->t->credentialRejected(tPtr,0x01feba012,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); RR->t->credentialRejected(tPtr,0x01feba012,nconf.networkId,sourcePeerIdentity,cred.id(),cred.timestamp(),C::credentialType(),ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID);
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
case 0: case 0:
if (!rc) if (!rc)
rc = &(remoteCreds[cred.id()]); rc = &(remoteCreds[cred.id()]);
*rc = cred; *rc = cred;
return Membership::ADD_ACCEPTED_NEW; return Member::ADD_ACCEPTED_NEW;
case 1: case 1:
return Membership::ADD_DEFERRED_FOR_WHOIS; return Member::ADD_DEFERRED_FOR_WHOIS;
} }
} }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag) { return _addCredImpl<Tag>(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); } Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag) { return _addCredImpl<TagCredential>(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap) { return _addCredImpl<Capability>(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); } Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap) { return _addCredImpl<CapabilityCredential>(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo) { return _addCredImpl<CertificateOfOwnership>(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); } Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo) { return _addCredImpl<OwnershipCredential>(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); }
Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Revocation &rev) Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev)
{ {
int64_t *rt; int64_t *rt;
switch(rev.verify(RR,tPtr)) { switch(rev.verify(RR,tPtr)) {
@ -233,7 +233,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
} }
} }
bool Membership::m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept bool Member::m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept
{ {
if ((ip.isV6())&&(nconf.ndpEmulation())) { if ((ip.isV6())&&(nconf.ndpEmulation())) {
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt())); const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));

View file

@ -17,10 +17,10 @@
#include "Constants.hpp" #include "Constants.hpp"
#include "Credential.hpp" #include "Credential.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
#include "Capability.hpp" #include "CapabilityCredential.hpp"
#include "Tag.hpp" #include "TagCredential.hpp"
#include "Revocation.hpp" #include "RevocationCredential.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -35,7 +35,7 @@ class Network;
* *
* This class is not thread safe. It must be locked externally. * This class is not thread safe. It must be locked externally.
*/ */
class Membership class Member
{ {
public: public:
enum AddCredentialResult enum AddCredentialResult
@ -46,7 +46,7 @@ public:
ADD_DEFERRED_FOR_WHOIS ADD_DEFERRED_FOR_WHOIS
}; };
Membership(); Member();
/** /**
* Send COM and other credentials to this peer * Send COM and other credentials to this peer
@ -71,10 +71,10 @@ public:
* @param id Tag ID * @param id Tag ID
* @return Pointer to tag or NULL if not found * @return Pointer to tag or NULL if not found
*/ */
ZT_INLINE const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const noexcept ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept
{ {
const Tag *const t = m_remoteTags.get(id); const TagCredential *const t = m_remoteTags.get(id);
return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (Tag *)0); return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (TagCredential *)0);
} }
/** /**
@ -103,7 +103,7 @@ public:
{ {
if (m_isUnspoofableAddress(nconf, r)) if (m_isUnspoofableAddress(nconf, r))
return true; return true;
for(Map< uint32_t,CertificateOfOwnership >::const_iterator i(m_remoteCoos.begin());i != m_remoteCoos.end();++i) { for(Map< uint32_t,OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) {
if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r))) if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r)))
return true; return true;
} }
@ -115,7 +115,7 @@ public:
* *
* @param localCom * @param localCom
*/ */
ZT_INLINE bool certificateOfMembershipAgress(const CertificateOfMembership &localCom,const Identity &remoteIdentity) ZT_INLINE bool certificateOfMembershipAgress(const MembershipCredential &localCom, const Identity &remoteIdentity)
{ {
if ((m_comAgreementLocalTimestamp == localCom.timestamp()) && (m_comAgreementRemoteTimestamp == m_com.timestamp())) if ((m_comAgreementLocalTimestamp == localCom.timestamp()) && (m_comAgreementRemoteTimestamp == m_com.timestamp()))
return true; return true;
@ -146,11 +146,11 @@ public:
return false; return false;
} }
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfMembership &com); AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const MembershipCredential &com);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Tag &tag); AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const TagCredential &tag);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Capability &cap); AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CapabilityCredential &cap);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CertificateOfOwnership &coo); AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const OwnershipCredential &coo);
AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const Revocation &rev); AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const RevocationCredential &rev);
private: private:
// This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT // This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT
@ -192,31 +192,31 @@ private:
int64_t m_comAgreementLocalTimestamp,m_comAgreementRemoteTimestamp; int64_t m_comAgreementLocalTimestamp,m_comAgreementRemoteTimestamp;
// Remote member's latest network COM // Remote member's latest network COM
CertificateOfMembership m_com; MembershipCredential m_com;
// Revocations by credentialKey() // Revocations by credentialKey()
Map<uint64_t,int64_t> m_revocations; Map<uint64_t,int64_t> m_revocations;
// Remote credentials that we have received from this member (and that are valid) // Remote credentials that we have received from this member (and that are valid)
Map<uint32_t,Tag> m_remoteTags; Map<uint32_t,TagCredential> m_remoteTags;
Map<uint32_t,Capability> m_remoteCaps; Map<uint32_t,CapabilityCredential> m_remoteCaps;
Map<uint32_t,CertificateOfOwnership> m_remoteCoos; Map<uint32_t,OwnershipCredential> m_remoteCoos;
public: public:
class CapabilityIterator class CapabilityIterator
{ {
public: public:
ZT_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) noexcept : ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept :
m_hti(m.m_remoteCaps.begin()), m_hti(m.m_remoteCaps.begin()),
m_parent(m), m_parent(m),
m_nconf(nconf) m_nconf(nconf)
{ {
} }
ZT_INLINE Capability *next() noexcept ZT_INLINE CapabilityCredential *next() noexcept
{ {
while (m_hti != m_parent.m_remoteCaps.end()) { while (m_hti != m_parent.m_remoteCaps.end()) {
Map< uint32_t,Capability >::iterator i(m_hti++); // NOLINT(hicpp-use-auto,modernize-use-auto) Map< uint32_t,CapabilityCredential >::iterator i(m_hti++);
if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second)) if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second))
return &(i->second); return &(i->second);
} }
@ -224,8 +224,8 @@ public:
} }
private: private:
Map< uint32_t,Capability >::iterator m_hti; Map< uint32_t,CapabilityCredential >::iterator m_hti;
Membership &m_parent; Member &m_parent;
const NetworkConfig &m_nconf; const NetworkConfig &m_nconf;
}; };
}; };

View file

@ -11,11 +11,11 @@
*/ */
/****/ /****/
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
namespace ZeroTier { namespace ZeroTier {
CertificateOfMembership::CertificateOfMembership(const int64_t timestamp, const int64_t timestampMaxDelta, const uint64_t nwid, const Identity &issuedTo) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) MembershipCredential::MembershipCredential(const int64_t timestamp, const int64_t timestampMaxDelta, const uint64_t nwid, const Identity &issuedTo) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
m_timestamp(timestamp), m_timestamp(timestamp),
m_timestampMaxDelta(timestampMaxDelta), m_timestampMaxDelta(timestampMaxDelta),
m_networkId(nwid), m_networkId(nwid),
@ -23,7 +23,7 @@ CertificateOfMembership::CertificateOfMembership(const int64_t timestamp, const
m_signatureLength(0) m_signatureLength(0)
{} {}
bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const noexcept bool MembershipCredential::agreesWith(const MembershipCredential &other) const noexcept
{ {
// NOTE: we always do explicit absolute value with an if() since llabs() can have overflow // NOTE: we always do explicit absolute value with an if() since llabs() can have overflow
// conditions that could introduce a vulnerability. // conditions that could introduce a vulnerability.
@ -85,7 +85,7 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c
return (other.m_networkId == m_networkId) && (m_networkId != 0) && (other.m_issuedTo.address != m_issuedTo.address); return (other.m_networkId == m_networkId) && (m_networkId != 0) && (other.m_issuedTo.address != m_issuedTo.address);
} }
bool CertificateOfMembership::sign(const Identity &with) noexcept bool MembershipCredential::sign(const Identity &with) noexcept
{ {
m_signedBy = with.address(); m_signedBy = with.address();
uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8]; uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8];
@ -94,7 +94,7 @@ bool CertificateOfMembership::sign(const Identity &with) noexcept
return m_signatureLength > 0; return m_signatureLength > 0;
} }
int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX], const bool v2) const noexcept int MembershipCredential::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX], const bool v2) const noexcept
{ {
data[0] = v2 ? 2 : 1; data[0] = v2 ? 2 : 1;
@ -156,7 +156,7 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR
return p; return p;
} }
int CertificateOfMembership::unmarshal(const uint8_t *data, int len) noexcept int MembershipCredential::unmarshal(const uint8_t *data, int len) noexcept
{ {
if (len < (1 + 2 + 72)) if (len < (1 + 2 + 72))
return -1; return -1;
@ -241,7 +241,7 @@ int CertificateOfMembership::unmarshal(const uint8_t *data, int len) noexcept
return -1; return -1;
} }
unsigned int CertificateOfMembership::m_fillSigningBuf(uint64_t *buf) const noexcept unsigned int MembershipCredential::m_fillSigningBuf(uint64_t *buf) const noexcept
{ {
const uint64_t informational = 0xffffffffffffffffULL; const uint64_t informational = 0xffffffffffffffffULL;

View file

@ -101,7 +101,7 @@ class RuntimeEnvironment;
* order with the fingerprint hash being packed into tuple IDs 3-8 and this buffer is * order with the fingerprint hash being packed into tuple IDs 3-8 and this buffer is
* then signed. * then signed.
*/ */
class CertificateOfMembership : public Credential class MembershipCredential : public Credential
{ {
friend class Credential; friend class Credential;
@ -111,7 +111,7 @@ public:
/** /**
* Create an empty certificate of membership * Create an empty certificate of membership
*/ */
ZT_INLINE CertificateOfMembership() noexcept { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE MembershipCredential() noexcept { memoryZero(this); }
/** /**
* Create from required fields common to all networks * Create from required fields common to all networks
@ -121,12 +121,12 @@ public:
* @param nwid Network ID * @param nwid Network ID
* @param issuedTo Certificate recipient * @param issuedTo Certificate recipient
*/ */
CertificateOfMembership(int64_t timestamp,int64_t timestampMaxDelta,uint64_t nwid,const Identity &issuedTo) noexcept; MembershipCredential(int64_t timestamp, int64_t timestampMaxDelta, uint64_t nwid, const Identity &issuedTo) noexcept;
/** /**
* @return True if there's something here * @return True if there's something here
*/ */
ZT_INLINE operator bool() const noexcept { return (m_networkId != 0); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) ZT_INLINE operator bool() const noexcept { return (m_networkId != 0); }
/** /**
* @return Credential ID, always 0 for COMs * @return Credential ID, always 0 for COMs
@ -166,7 +166,7 @@ public:
* @param other Cert to compare with * @param other Cert to compare with
* @return True if certs agree and 'other' may be communicated with * @return True if certs agree and 'other' may be communicated with
*/ */
bool agreesWith(const CertificateOfMembership &other) const noexcept; bool agreesWith(const MembershipCredential &other) const noexcept;
/** /**
* Sign this certificate * Sign this certificate

View file

@ -74,7 +74,7 @@ _doZtFilterResult _doZtFilter(
const RuntimeEnvironment *RR, const RuntimeEnvironment *RR,
Trace::RuleResultLog &rrl, Trace::RuleResultLog &rrl,
const NetworkConfig &nconf, const NetworkConfig &nconf,
const Membership *membership, // can be NULL const Member *membership, // can be NULL
const bool inbound, const bool inbound,
const Address &ztSource, const Address &ztSource,
Address &ztDest, // MUTABLE -- is changed on REDIRECT actions Address &ztDest, // MUTABLE -- is changed on REDIRECT actions
@ -420,9 +420,9 @@ _doZtFilterResult _doZtFilter(
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR: case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR: case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL: { case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL: {
const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate()); const TagCredential *const localTag = std::lower_bound(&(nconf.tags[0]), &(nconf.tags[nconf.tagCount]), rules[rn].v.tag.id, TagCredential::IdComparePredicate());
if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) { if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0); const TagCredential *const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const TagCredential *)0);
if (remoteTag) { if (remoteTag) {
const uint32_t ltv = localTag->value(); const uint32_t ltv = localTag->value();
const uint32_t rtv = remoteTag->value(); const uint32_t rtv = remoteTag->value();
@ -461,7 +461,7 @@ _doZtFilterResult _doZtFilter(
if (superAccept) { if (superAccept) {
thisRuleMatches = 1; thisRuleMatches = 1;
} else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) { } else if ( ((rt == ZT_NETWORK_RULE_MATCH_TAG_SENDER)&&(inbound)) || ((rt == ZT_NETWORK_RULE_MATCH_TAG_RECEIVER)&&(!inbound)) ) {
const Tag *const remoteTag = ((membership) ? membership->getTag(nconf,rules[rn].v.tag.id) : (const Tag *)0); const TagCredential *const remoteTag = ((membership) ? membership->getTag(nconf, rules[rn].v.tag.id) : (const TagCredential *)0);
if (remoteTag) { if (remoteTag) {
thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value);
} else { } else {
@ -474,7 +474,7 @@ _doZtFilterResult _doZtFilter(
} }
} }
} else { // sender and outbound or receiver and inbound } else { // sender and outbound or receiver and inbound
const Tag *const localTag = std::lower_bound(&(nconf.tags[0]),&(nconf.tags[nconf.tagCount]),rules[rn].v.tag.id,Tag::IdComparePredicate()); const TagCredential *const localTag = std::lower_bound(&(nconf.tags[0]), &(nconf.tags[nconf.tagCount]), rules[rn].v.tag.id, TagCredential::IdComparePredicate());
if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) { if ((localTag != &(nconf.tags[nconf.tagCount]))&&(localTag->id() == rules[rn].v.tag.id)) {
thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value); thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value);
} else { } else {
@ -626,7 +626,7 @@ bool Network::filterOutgoingPacket(
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
Mutex::Lock l2(m_config_l); Mutex::Lock l2(m_config_l);
Membership *const membership = (ztDest) ? m_memberships.get(ztDest) : nullptr; Member *const membership = (ztDest) ? m_memberships.get(ztDest) : nullptr;
switch(_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch(_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
@ -719,7 +719,7 @@ bool Network::filterOutgoingPacket(
} }
if (localCapabilityIndex >= 0) { if (localCapabilityIndex >= 0) {
const Capability &cap = m_config.capabilities[localCapabilityIndex]; const CapabilityCredential &cap = m_config.capabilities[localCapabilityIndex];
RR->t->networkFilter(tPtr, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); RR->t->networkFilter(tPtr, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
} else { } else {
RR->t->networkFilter(tPtr, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); RR->t->networkFilter(tPtr, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept);
@ -745,19 +745,19 @@ int Network::filterIncomingPacket(
Address cc; Address cc;
unsigned int ccLength = 0; unsigned int ccLength = 0;
bool ccWatch = false; bool ccWatch = false;
const Capability *c = nullptr; const CapabilityCredential *c = nullptr;
uint8_t qosBucket = 255; // For incoming packets this is a dummy value uint8_t qosBucket = 255; // For incoming packets this is a dummy value
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
Mutex::Lock l2(m_config_l); Mutex::Lock l2(m_config_l);
Membership &membership = m_memberships[sourcePeer->address()]; Member &membership = m_memberships[sourcePeer->address()];
switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) {
case DOZTFILTER_NO_MATCH: { case DOZTFILTER_NO_MATCH: {
Membership::CapabilityIterator mci(membership, m_config); Member::CapabilityIterator mci(membership, m_config);
while ((c = mci.next())) { while ((c = mci.next())) {
ztFinalDest = ztDest; // sanity check, should be unmodified if there was no match ztFinalDest = ztDest; // sanity check, should be unmodified if there was no match
Address cc2; Address cc2;
@ -1074,7 +1074,7 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) noexcept
try { try {
Mutex::Lock l(m_memberships_l); Mutex::Lock l(m_memberships_l);
Membership *m = m_memberships.get(peer->address()); Member *m = m_memberships.get(peer->address());
if (m) { if (m) {
// SECURITY: this method in CertificateOfMembership does a full fingerprint check as well as // SECURITY: this method in CertificateOfMembership does a full fingerprint check as well as
// checking certificate agreement. See Membership.hpp. // checking certificate agreement. See Membership.hpp.
@ -1099,7 +1099,7 @@ void Network::doPeriodicTasks(void *tPtr,const int64_t now)
{ {
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
for(Map<Address,Membership>::iterator i(m_memberships.begin());i != m_memberships.end();++i) for(Map<Address,Member>::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i)
i->second.clean(now, m_config); i->second.clean(now, m_config);
{ {
@ -1150,41 +1150,41 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
} }
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfMembership &com) Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com)
{ {
if (com.networkId() != m_id) if (com.networkId() != m_id)
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[com.issuedTo().address].addCredential(RR, tPtr, sourcePeerIdentity, m_config, com); return m_memberships[com.issuedTo().address].addCredential(RR, tPtr, sourcePeerIdentity, m_config, com);
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Capability &cap) Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap)
{ {
if (cap.networkId() != m_id) if (cap.networkId() != m_id)
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[cap.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, cap); return m_memberships[cap.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, cap);
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Tag &tag) Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag)
{ {
if (tag.networkId() != m_id) if (tag.networkId() != m_id)
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[tag.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, tag); return m_memberships[tag.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, tag);
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Revocation &rev) Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev)
{ {
if (rev.networkId() != m_id) if (rev.networkId() != m_id)
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock l1(m_memberships_l); Mutex::Lock l1(m_memberships_l);
Membership &m = m_memberships[rev.target()]; Member &m = m_memberships[rev.target()];
const Membership::AddCredentialResult result = m.addCredential(RR, tPtr, sourcePeerIdentity, m_config, rev); const Member::AddCredentialResult result = m.addCredential(RR, tPtr, sourcePeerIdentity, m_config, rev);
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) { if ((result == Member::ADD_ACCEPTED_NEW) && (rev.fastPropagate())) {
// TODO // TODO
/* /*
Address *a = nullptr; Address *a = nullptr;
@ -1208,10 +1208,10 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity
return result; return result;
} }
Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfOwnership &coo) Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo)
{ {
if (coo.networkId() != m_id) if (coo.networkId() != m_id)
return Membership::ADD_REJECTED; return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo); return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo);
} }
@ -1220,7 +1220,7 @@ void Network::pushCredentials(void *tPtr,const SharedPtr<Peer> &to,const int64_t
{ {
const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta()); const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta());
Mutex::Lock _l(m_memberships_l); Mutex::Lock _l(m_memberships_l);
Membership &m = m_memberships[to->address()]; Member &m = m_memberships[to->address()];
if (((now - m.lastPushedCredentials()) + 5000) >= tout) { if (((now - m.lastPushedCredentials()) + 5000) >= tout) {
m.pushCredentials(RR, tPtr, now, to, m_config); m.pushCredentials(RR, tPtr, now, to, m_config);
} }

View file

@ -22,9 +22,9 @@
#include "MAC.hpp" #include "MAC.hpp"
#include "Buf.hpp" #include "Buf.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Membership.hpp" #include "Member.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
#include "Containers.hpp" #include "Containers.hpp"
#define ZT_NETWORK_MAX_INCOMING_UPDATES 3 #define ZT_NETWORK_MAX_INCOMING_UPDATES 3
@ -265,27 +265,27 @@ public:
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfMembership &com); Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Capability &cap); Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Tag &tag); Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const Revocation &rev); Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev);
/** /**
* Validate a credential and learn it if it passes certificate and other checks * Validate a credential and learn it if it passes certificate and other checks
*/ */
Membership::AddCredentialResult addCredential(void *tPtr,const Identity &sourcePeerIdentity,const CertificateOfOwnership &coo); Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo);
/** /**
* Push credentials to a peer if timeouts indicate that we should do so * Push credentials to a peer if timeouts indicate that we should do so
@ -320,7 +320,7 @@ public:
ZT_INLINE void eachMember(F f) ZT_INLINE void eachMember(F f)
{ {
Mutex::Lock ml(m_memberships_l); Mutex::Lock ml(m_memberships_l);
for(Map<Address,Membership>::iterator i(m_memberships.begin());i != m_memberships.end();++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto) for(Map<Address,Member>::iterator i(m_memberships.begin()); i != m_memberships.end(); ++i) { // NOLINT(modernize-loop-convert,hicpp-use-auto,modernize-use-auto)
if (!f(i->first,i->second)) if (!f(i->first,i->second))
break; break;
} }
@ -361,7 +361,7 @@ private:
NETCONF_FAILURE_INIT_FAILED NETCONF_FAILURE_INIT_FAILED
} _netconfFailure; } _netconfFailure;
Map<Address,Membership> m_memberships; Map<Address,Member> m_memberships;
Mutex m_myMulticastGroups_l; Mutex m_myMulticastGroups_l;
Mutex m_remoteBridgeRoutes_l; Mutex m_remoteBridgeRoutes_l;

View file

@ -96,7 +96,7 @@ bool NetworkConfig::toDictionary(Dictionary &d) const
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]); blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]);
if (this->ruleCount) { if (this->ruleCount) {
blob->resize(ruleCount * ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX); blob->resize(ruleCount * ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX);
int l = Capability::marshalVirtualNetworkRules(blob->data(),rules,ruleCount); int l = CapabilityCredential::marshalVirtualNetworkRules(blob->data(), rules, ruleCount);
if (l > 0) if (l > 0)
blob->resize(l); blob->resize(l);
} }
@ -154,7 +154,7 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
try { try {
unsigned int p = 0; unsigned int p = 0;
while (p < blob->size()) { while (p < blob->size()) {
Capability cap; CapabilityCredential cap;
int l = cap.unmarshal(blob->data() + p,(int)(blob->size() - p)); int l = cap.unmarshal(blob->data() + p,(int)(blob->size() - p));
if (l < 0) if (l < 0)
return false; return false;
@ -171,7 +171,7 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
try { try {
unsigned int p = 0; unsigned int p = 0;
while (p < blob->size()) { while (p < blob->size()) {
Tag tag; TagCredential tag;
int l = tag.unmarshal(blob->data() + p,(int)(blob->size() - p)); int l = tag.unmarshal(blob->data() + p,(int)(blob->size() - p));
if (l < 0) if (l < 0)
return false; return false;
@ -188,7 +188,7 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
try { try {
unsigned int p = 0; unsigned int p = 0;
while (p < blob->size()) { while (p < blob->size()) {
CertificateOfOwnership coo; OwnershipCredential coo;
int l = coo.unmarshal(blob->data() + p,(int)(blob->size() - p)); int l = coo.unmarshal(blob->data() + p,(int)(blob->size() - p));
if (l < 0) if (l < 0)
return false; return false;
@ -246,7 +246,7 @@ bool NetworkConfig::fromDictionary(const Dictionary &d)
blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]); blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_RULES]);
if (!blob->empty()) { if (!blob->empty()) {
this->ruleCount = 0; this->ruleCount = 0;
if (Capability::unmarshalVirtualNetworkRules(blob->data(),(int)blob->size(),this->rules,this->ruleCount,ZT_MAX_NETWORK_RULES) < 0) if (CapabilityCredential::unmarshalVirtualNetworkRules(blob->data(), (int)blob->size(), this->rules, this->ruleCount, ZT_MAX_NETWORK_RULES) < 0)
return false; return false;
} }
} }

View file

@ -18,10 +18,10 @@
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "MulticastGroup.hpp" #include "MulticastGroup.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
#include "CertificateOfOwnership.hpp" #include "OwnershipCredential.hpp"
#include "Capability.hpp" #include "CapabilityCredential.hpp"
#include "Tag.hpp" #include "TagCredential.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "Identity.hpp" #include "Identity.hpp"
#include "Utils.hpp" #include "Utils.hpp"
@ -222,7 +222,7 @@ struct NetworkConfig : TriviallyCopyable
*/ */
bool addSpecialist(const Address &a, uint64_t f) noexcept; bool addSpecialist(const Address &a, uint64_t f) noexcept;
ZT_INLINE const Capability *capability(const uint32_t id) const ZT_INLINE const CapabilityCredential *capability(const uint32_t id) const
{ {
for (unsigned int i = 0;i < capabilityCount;++i) { for (unsigned int i = 0;i < capabilityCount;++i) {
if (capabilities[i].id() == id) if (capabilities[i].id() == id)
@ -231,7 +231,7 @@ struct NetworkConfig : TriviallyCopyable
return nullptr; return nullptr;
} }
ZT_INLINE const Tag *tag(const uint32_t id) const ZT_INLINE const TagCredential *tag(const uint32_t id) const
{ {
for (unsigned int i = 0;i < tagCount;++i) { for (unsigned int i = 0;i < tagCount;++i) {
if (tags[i].id() == id) if (tags[i].id() == id)
@ -349,17 +349,17 @@ struct NetworkConfig : TriviallyCopyable
/** /**
* Capabilities for this node on this network, in ascending order of capability ID * Capabilities for this node on this network, in ascending order of capability ID
*/ */
Capability capabilities[ZT_MAX_NETWORK_CAPABILITIES]; CapabilityCredential capabilities[ZT_MAX_NETWORK_CAPABILITIES];
/** /**
* Tags for this node on this network, in ascending order of tag ID * Tags for this node on this network, in ascending order of tag ID
*/ */
Tag tags[ZT_MAX_NETWORK_TAGS]; TagCredential tags[ZT_MAX_NETWORK_TAGS];
/** /**
* Certificates of ownership for this network member * Certificates of ownership for this network member
*/ */
CertificateOfOwnership certificatesOfOwnership[ZT_MAX_CERTIFICATES_OF_OWNERSHIP]; OwnershipCredential certificatesOfOwnership[ZT_MAX_CERTIFICATES_OF_OWNERSHIP];
/** /**
* Network type (currently just public or private) * Network type (currently just public or private)
@ -374,7 +374,7 @@ struct NetworkConfig : TriviallyCopyable
/** /**
* Certificate of membership (for private networks) * Certificate of membership (for private networks)
*/ */
CertificateOfMembership com; MembershipCredential com;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -17,7 +17,7 @@
#include "Constants.hpp" #include "Constants.hpp"
#include "Dictionary.hpp" #include "Dictionary.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "Revocation.hpp" #include "RevocationCredential.hpp"
#include "Address.hpp" #include "Address.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -62,7 +62,7 @@ public:
* @param destination Destination node address * @param destination Destination node address
* @param rev Revocation to send * @param rev Revocation to send
*/ */
virtual void ncSendRevocation(const Address &destination,const Revocation &rev) = 0; virtual void ncSendRevocation(const Address &destination,const RevocationCredential &rev) = 0;
/** /**
* Send a network configuration request error * Send a network configuration request error

View file

@ -743,7 +743,7 @@ void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &
} }
} }
void Node::ncSendRevocation(const Address &destination, const Revocation &rev) void Node::ncSendRevocation(const Address &destination, const RevocationCredential &rev)
{ {
if (destination == RR->identity.address()) { if (destination == RR->identity.address()) {
SharedPtr< Network > n(network(rev.networkId())); SharedPtr< Network > n(network(rev.networkId()));

View file

@ -358,7 +358,7 @@ public:
// Implementation of NetworkController::Sender interface // Implementation of NetworkController::Sender interface
virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig); virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig);
virtual void ncSendRevocation(const Address &destination, const Revocation &rev); virtual void ncSendRevocation(const Address &destination, const RevocationCredential &rev);
virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode); virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode);

View file

@ -11,11 +11,11 @@
*/ */
/****/ /****/
#include "CertificateOfOwnership.hpp" #include "OwnershipCredential.hpp"
namespace ZeroTier { namespace ZeroTier {
void CertificateOfOwnership::addThing(const InetAddress &ip) void OwnershipCredential::addThing(const InetAddress &ip)
{ {
if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
return; return;
@ -30,7 +30,7 @@ void CertificateOfOwnership::addThing(const InetAddress &ip)
} }
} }
void CertificateOfOwnership::addThing(const MAC &mac) void OwnershipCredential::addThing(const MAC &mac)
{ {
if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS)
return; return;
@ -39,7 +39,7 @@ void CertificateOfOwnership::addThing(const MAC &mac)
++m_thingCount; ++m_thingCount;
} }
bool CertificateOfOwnership::sign(const Identity &signer) bool OwnershipCredential::sign(const Identity &signer)
{ {
uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16]; uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16];
if (signer.hasPrivate()) { if (signer.hasPrivate()) {
@ -50,7 +50,7 @@ bool CertificateOfOwnership::sign(const Identity &signer)
return false; return false;
} }
int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign) const noexcept int OwnershipCredential::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign) const noexcept
{ {
int p = 0; int p = 0;
if (forSign) { if (forSign) {
@ -88,7 +88,7 @@ int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSH
return p; return p;
} }
int CertificateOfOwnership::unmarshal(const uint8_t *data, int len) noexcept int OwnershipCredential::unmarshal(const uint8_t *data, int len) noexcept
{ {
if (len < 30) if (len < 30)
return -1; return -1;

View file

@ -45,7 +45,7 @@ class RuntimeEnvironment;
* These are used in conjunction with the rules engine to make IP addresses and * These are used in conjunction with the rules engine to make IP addresses and
* other identifiers un-spoofable. * other identifiers un-spoofable.
*/ */
class CertificateOfOwnership : public Credential class OwnershipCredential : public Credential
{ {
friend class Credential; friend class Credential;
@ -60,9 +60,9 @@ public:
THING_IPV6_ADDRESS = 3 THING_IPV6_ADDRESS = 3
}; };
ZT_INLINE CertificateOfOwnership() noexcept { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE OwnershipCredential() noexcept { memoryZero(this); }
ZT_INLINE CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) noexcept // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept
{ {
memoryZero(this); memoryZero(this);
m_networkId = nwid; m_networkId = nwid;
@ -139,10 +139,10 @@ public:
int unmarshal(const uint8_t *data,int len) noexcept; int unmarshal(const uint8_t *data,int len) noexcept;
// Provides natural sort order by ID // Provides natural sort order by ID
ZT_INLINE bool operator<(const CertificateOfOwnership &coo) const noexcept { return (m_id < coo.m_id); } ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept { return (m_id < coo.m_id); }
ZT_INLINE bool operator==(const CertificateOfOwnership &coo) const noexcept { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) == 0); } ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); }
ZT_INLINE bool operator!=(const CertificateOfOwnership &coo) const noexcept { return (memcmp(this,&coo,sizeof(CertificateOfOwnership)) != 0); } ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); }
private: private:
ZT_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const noexcept ZT_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const noexcept

View file

@ -11,11 +11,11 @@
*/ */
/****/ /****/
#include "Revocation.hpp" #include "RevocationCredential.hpp"
namespace ZeroTier { namespace ZeroTier {
bool Revocation::sign(const Identity &signer) noexcept bool RevocationCredential::sign(const Identity &signer) noexcept
{ {
uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX + 32]; uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX + 32];
if (signer.hasPrivate()) { if (signer.hasPrivate()) {
@ -26,7 +26,7 @@ bool Revocation::sign(const Identity &signer) noexcept
return false; return false;
} }
int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSign) const noexcept int RevocationCredential::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSign) const noexcept
{ {
int p = 0; int p = 0;
if (forSign) { if (forSign) {
@ -67,7 +67,7 @@ int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSi
return p; return p;
} }
int Revocation::unmarshal(const uint8_t *restrict data, const int len) noexcept int RevocationCredential::unmarshal(const uint8_t *restrict data, const int len) noexcept
{ {
if (len < 54) if (len < 54)
return -1; return -1;

View file

@ -35,7 +35,7 @@ class RuntimeEnvironment;
/** /**
* Revocation certificate to instantaneously revoke a COM, capability, or tag * Revocation certificate to instantaneously revoke a COM, capability, or tag
*/ */
class Revocation : public Credential class RevocationCredential : public Credential
{ {
friend class Credential; friend class Credential;
@ -43,7 +43,7 @@ public:
static constexpr ZT_CredentialType credentialType() noexcept static constexpr ZT_CredentialType credentialType() noexcept
{ return ZT_CREDENTIAL_TYPE_REVOCATION; } { return ZT_CREDENTIAL_TYPE_REVOCATION; }
ZT_INLINE Revocation() noexcept ZT_INLINE RevocationCredential() noexcept
{ memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) { memoryZero(this); } // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
/** /**
@ -55,7 +55,7 @@ public:
* @param tgt Target node whose credential(s) are being revoked * @param tgt Target node whose credential(s) are being revoked
* @param ct Credential type being revoked * @param ct Credential type being revoked
*/ */
ZT_INLINE Revocation(const uint32_t i, const uint64_t nwid, const uint32_t cid, const uint64_t thr, const uint64_t fl, const Address &tgt, const ZT_CredentialType ct) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) ZT_INLINE RevocationCredential(const uint32_t i, const uint64_t nwid, const uint32_t cid, const uint64_t thr, const uint64_t fl, const Address &tgt, const ZT_CredentialType ct) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
m_id(i), m_id(i),
m_credentialId(cid), m_credentialId(cid),
m_networkId(nwid), m_networkId(nwid),

View file

@ -11,11 +11,11 @@
*/ */
/****/ /****/
#include "Tag.hpp" #include "TagCredential.hpp"
namespace ZeroTier { namespace ZeroTier {
bool Tag::sign(const Identity &signer) noexcept bool TagCredential::sign(const Identity &signer) noexcept
{ {
uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX]; uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX];
if (signer.hasPrivate()) { if (signer.hasPrivate()) {
@ -26,7 +26,7 @@ bool Tag::sign(const Identity &signer) noexcept
return false; return false;
} }
int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign) const noexcept int TagCredential::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign) const noexcept
{ {
int p = 0; int p = 0;
if (forSign) { if (forSign) {
@ -61,7 +61,7 @@ int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign) const noex
return p; return p;
} }
int Tag::unmarshal(const uint8_t *data, int len) noexcept int TagCredential::unmarshal(const uint8_t *data, int len) noexcept
{ {
if (len < 37) if (len < 37)
return -1; return -1;

View file

@ -43,7 +43,7 @@ class RuntimeEnvironment;
* Unlike capabilities tags are signed only by the issuer and are never * Unlike capabilities tags are signed only by the issuer and are never
* transferable. * transferable.
*/ */
class Tag : public Credential class TagCredential : public Credential
{ {
friend class Credential; friend class Credential;
@ -51,7 +51,7 @@ public:
static constexpr ZT_CredentialType credentialType() noexcept static constexpr ZT_CredentialType credentialType() noexcept
{ return ZT_CREDENTIAL_TYPE_TAG; } { return ZT_CREDENTIAL_TYPE_TAG; }
ZT_INLINE Tag() noexcept ZT_INLINE TagCredential() noexcept
{ memoryZero(this); } { memoryZero(this); }
/** /**
@ -61,7 +61,7 @@ public:
* @param id Tag ID * @param id Tag ID
* @param value Tag value * @param value Tag value
*/ */
ZT_INLINE Tag(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id, const uint32_t value) noexcept: ZT_INLINE TagCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id, const uint32_t value) noexcept:
m_id(id), m_id(id),
m_value(value), m_value(value),
m_networkId(nwid), m_networkId(nwid),
@ -121,40 +121,40 @@ public:
int unmarshal(const uint8_t *data, int len) noexcept; int unmarshal(const uint8_t *data, int len) noexcept;
// Provides natural sort order by ID // Provides natural sort order by ID
ZT_INLINE bool operator<(const Tag &t) const noexcept ZT_INLINE bool operator<(const TagCredential &t) const noexcept
{ return (m_id < t.m_id); } { return (m_id < t.m_id); }
ZT_INLINE bool operator==(const Tag &t) const noexcept ZT_INLINE bool operator==(const TagCredential &t) const noexcept
{ return (memcmp(this, &t, sizeof(Tag)) == 0); } { return (memcmp(this, &t, sizeof(TagCredential)) == 0); }
ZT_INLINE bool operator!=(const Tag &t) const noexcept ZT_INLINE bool operator!=(const TagCredential &t) const noexcept
{ return (memcmp(this, &t, sizeof(Tag)) != 0); } { return (memcmp(this, &t, sizeof(TagCredential)) != 0); }
// For searching sorted arrays or lists of Tags by ID // For searching sorted arrays or lists of Tags by ID
struct IdComparePredicate struct IdComparePredicate
{ {
ZT_INLINE bool operator()(const Tag &a, const Tag &b) const noexcept ZT_INLINE bool operator()(const TagCredential &a, const TagCredential &b) const noexcept
{ return (a.id() < b.id()); } { return (a.id() < b.id()); }
ZT_INLINE bool operator()(const uint32_t a, const Tag &b) const noexcept ZT_INLINE bool operator()(const uint32_t a, const TagCredential &b) const noexcept
{ return (a < b.id()); } { return (a < b.id()); }
ZT_INLINE bool operator()(const Tag &a, const uint32_t b) const noexcept ZT_INLINE bool operator()(const TagCredential &a, const uint32_t b) const noexcept
{ return (a.id() < b); } { return (a.id() < b); }
ZT_INLINE bool operator()(const Tag *a, const Tag *b) const noexcept ZT_INLINE bool operator()(const TagCredential *a, const TagCredential *b) const noexcept
{ return (a->id() < b->id()); } { return (a->id() < b->id()); }
ZT_INLINE bool operator()(const Tag *a, const Tag &b) const noexcept ZT_INLINE bool operator()(const TagCredential *a, const TagCredential &b) const noexcept
{ return (a->id() < b.id()); } { return (a->id() < b.id()); }
ZT_INLINE bool operator()(const Tag &a, const Tag *b) const noexcept ZT_INLINE bool operator()(const TagCredential &a, const TagCredential *b) const noexcept
{ return (a.id() < b->id()); } { return (a.id() < b->id()); }
ZT_INLINE bool operator()(const uint32_t a, const Tag *b) const noexcept ZT_INLINE bool operator()(const uint32_t a, const TagCredential *b) const noexcept
{ return (a < b->id()); } { return (a < b->id()); }
ZT_INLINE bool operator()(const Tag *a, const uint32_t b) const noexcept ZT_INLINE bool operator()(const TagCredential *a, const uint32_t b) const noexcept
{ return (a->id() < b); } { return (a->id() < b); }
ZT_INLINE bool operator()(const uint32_t a, const uint32_t b) const noexcept ZT_INLINE bool operator()(const uint32_t a, const uint32_t b) const noexcept

View file

@ -29,11 +29,11 @@
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Endpoint.hpp" #include "Endpoint.hpp"
#include "Locator.hpp" #include "Locator.hpp"
#include "CertificateOfMembership.hpp" #include "MembershipCredential.hpp"
#include "CertificateOfOwnership.hpp" #include "OwnershipCredential.hpp"
#include "Revocation.hpp" #include "RevocationCredential.hpp"
#include "Tag.hpp" #include "TagCredential.hpp"
#include "Capability.hpp" #include "CapabilityCredential.hpp"
#include "NetworkConfig.hpp" #include "NetworkConfig.hpp"
#include "FCV.hpp" #include "FCV.hpp"
#include "SHA512.hpp" #include "SHA512.hpp"

View file

@ -39,18 +39,6 @@ SharedPtr< Peer > Topology::add(void *tPtr, const SharedPtr< Peer > &peer)
return peer; return peer;
} }
struct p_RootSortComparisonOperator
{
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
{
// Sort in inverse order of latency with lowest latency first (and -1 last).
const int bb = b->latency();
if (bb < 0)
return true;
return bb < a->latency();
}
};
SharedPtr< Peer > Topology::addRoot(void *const tPtr, const Identity &id) SharedPtr< Peer > Topology::addRoot(void *const tPtr, const Identity &id)
{ {
if ((id != RR->identity) && id.locallyValidate()) { if ((id != RR->identity) && id.locallyValidate()) {
@ -69,6 +57,10 @@ SharedPtr< Peer > Topology::addRoot(void *const tPtr, const Identity &id)
return SharedPtr< Peer >(); return SharedPtr< Peer >();
} }
ZT_CertificateError addRootSet(void *tPtr, const Certificate &cert)
{
}
bool Topology::removeRoot(void *const tPtr, Address address) bool Topology::removeRoot(void *const tPtr, Address address)
{ {
RWMutex::Lock l1(m_peers_l); RWMutex::Lock l1(m_peers_l);
@ -76,10 +68,22 @@ bool Topology::removeRoot(void *const tPtr, Address address)
return true; return true;
} }
struct p_RootRankingComparisonOperator
{
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
{
// Sort in inverse order of latency with lowest latency first (and -1 last).
const int bb = b->latency();
if (bb < 0)
return true;
return bb < a->latency();
}
};
void Topology::rankRoots() void Topology::rankRoots()
{ {
RWMutex::Lock l1(m_peers_l); RWMutex::Lock l1(m_peers_l);
std::sort(m_rootPeers.begin(), m_rootPeers.end(), p_RootSortComparisonOperator()); std::sort(m_rootPeers.begin(), m_rootPeers.end(), p_RootRankingComparisonOperator());
} }
void Topology::doPeriodicTasks(void *tPtr, const int64_t now) void Topology::doPeriodicTasks(void *tPtr, const int64_t now)

View file

@ -25,7 +25,7 @@
#include "ScopedPtr.hpp" #include "ScopedPtr.hpp"
#include "Fingerprint.hpp" #include "Fingerprint.hpp"
#include "Blob.hpp" #include "Blob.hpp"
#include "IdentificationCertificate.hpp" #include "Certificate.hpp"
#include "Containers.hpp" #include "Containers.hpp"
namespace ZeroTier { namespace ZeroTier {
@ -182,6 +182,20 @@ public:
*/ */
SharedPtr< Peer > addRoot(void *tPtr, const Identity &id); SharedPtr< Peer > addRoot(void *tPtr, const Identity &id);
/**
* Add or update a root set
*
* This does not check the certificate's validity. That must be done
* first. It may however return a certificate error if something is
* missing or wrong that prevents the certificate from being used
* as a root set.
*
* @param tPtr Thread pointer
* @param cert Certificate whose subject enumerates root identities
* @return Zero on success or an error code
*/
ZT_CertificateError addRootSet(void *tPtr, const Certificate &cert);
/** /**
* Remove a root server's identity from the root server set * Remove a root server's identity from the root server set
* *
@ -239,7 +253,8 @@ private:
RWMutex m_peers_l; // locks m_peers, m_roots, and m_rootPeers RWMutex m_peers_l; // locks m_peers, m_roots, and m_rootPeers
Map< uint64_t, SharedPtr< Path > > m_paths; Map< uint64_t, SharedPtr< Path > > m_paths;
Map< Address, SharedPtr< Peer > > m_peers; Map< Address, SharedPtr< Peer > > m_peers;
Map< Identity, Set< IdentificationCertificate > > m_roots; Map< Identity, Set< Blob<ZT_SHA384_DIGEST_SIZE> > > m_roots;
Map< String, Certificate > m_rootSets;
Vector< SharedPtr< Peer > > m_rootPeers; Vector< SharedPtr< Peer > > m_rootPeers;
}; };

View file

@ -35,11 +35,11 @@ class Identity;
class Peer; class Peer;
class Path; class Path;
class Network; class Network;
class CertificateOfMembership; class MembershipCredential;
class CertificateOfOwnership; class OwnershipCredential;
class Revocation; class RevocationCredential;
class Tag; class TagCredential;
class Capability; class CapabilityCredential;
struct NetworkConfig; struct NetworkConfig;
/** /**

View file

@ -32,9 +32,7 @@ namespace ZeroTier {
namespace { namespace {
ZT_INLINE const Identity &identityFromPeerPtr(const SharedPtr< Peer > &p) ZT_INLINE const Identity &identityFromPeerPtr(const SharedPtr< Peer > &p)
{ { return (p) ? p->identity() : Identity::NIL; }
return (p) ? p->identity() : Identity::NIL;
}
struct p_SalsaPolyCopyFunction struct p_SalsaPolyCopyFunction
{ {
@ -100,8 +98,7 @@ struct p_PolyCopyFunction
VL1::VL1(const RuntimeEnvironment *renv) : VL1::VL1(const RuntimeEnvironment *renv) :
RR(renv) RR(renv)
{ {}
}
void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept
{ {

View file

@ -294,40 +294,81 @@ typedef struct
} ZT_Fingerprint; } ZT_Fingerprint;
/** /**
* Maximum length of string fields in identification certificates * Maximum length of string fields in certificates
*/ */
#define ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH 127 #define ZT_CERTIFICATE_MAX_STRING_LENGTH 63
/** /**
* Maximum length of a signature * Maximum length of a signature
*/ */
#define ZT_IDENTIFICATION_CERTIFICATE_MAX_SIGNATURE_SIZE 256 #define ZT_CERTIFICATE_MAX_SIGNATURE_SIZE 96
/** /**
* Flag indicating that the nodes in the subject are a set of roots * Flag indicating that the nodes in the subject are a set of roots
*/ */
#define ZT_IDENTIFICATION_CERTIFICATE_FLAG_ROOT_SET 0x0000000000000001ULL #define ZT_CERTIFICATE_FLAG_CERTIFICATE_USE_ROOT_SET 0x0000000000000001ULL
/**
* Errors returned by functions that verify or handle certificates.
*/
enum ZT_CertificateError
{
/**
* No error (certificate is valid or operation was successful)
*/
ZT_CERTIFICATE_ERROR_NONE = 0,
/**
* Certificate format is invalid or required fields are missing
*/
ZT_CERTIFICATE_ERROR_INVALID_FORMAT = 1,
/**
* One or more identities in the certificate are invalid or fail consistency check
*/
ZT_CERTIFICATE_ERROR_INVALID_IDENTITY = 2,
/**
* Certificate primary signature is invalid
*/
ZT_CERTIFICATE_ERROR_INVALID_PRIMARY_SIGNATURE = 3,
/**
* Full chain validation of certificate failed
*/
ZT_CERTIFICATE_ERROR_INVALID_CHAIN = 4,
/**
* One or more signed components (e.g. a Locator) has an invalid signature.
*/
ZT_CERTIFICATE_ERROR_INVALID_COMPONENT_SIGNATURE = 5,
/**
* Certificate is not appropriate for this use
*/
ZT_CERTIFICATE_ERROR_INAPPROPRIATE_FOR_USE = 6
};
/** /**
* Information about a real world entity. * Information about a real world entity.
*/ */
typedef struct typedef struct
{ {
char country[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char country[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char organization[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char organization[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char unit[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char unit[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char locality[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char locality[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char province[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char province[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char streetAddress[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char streetAddress[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char postalCode[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char postalCode[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char commonName[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char commonName[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char serialNo[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char serialNo[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char email[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char email[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char url[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1]; char url[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
} ZT_IdentificationCertificate_Name; } ZT_Certificate_Name;
/** /**
* Identity and optional locator for a node * Identity and optional locator to help find a node on physical networks.
*/ */
typedef struct typedef struct
{ {
@ -337,10 +378,10 @@ typedef struct
const ZT_Identity *identity; const ZT_Identity *identity;
/** /**
* Locator or NULL if not specified * Locator, or NULL if none
*/ */
const ZT_Locator *locator; const ZT_Locator *locator;
} ZT_IdentificationCertificate_Node; } ZT_Certificate_Identity;
/** /**
* ID and primary controller for a network * ID and primary controller for a network
@ -356,7 +397,7 @@ typedef struct
* Full fingerprint of primary controller * Full fingerprint of primary controller
*/ */
ZT_Fingerprint controller; ZT_Fingerprint controller;
} ZT_IdentificationCertificate_Network; } ZT_Certificate_Network;
/** /**
* Identification certificate subject * Identification certificate subject
@ -366,36 +407,48 @@ typedef struct
/** /**
* Identities and optional locators of nodes * Identities and optional locators of nodes
*/ */
ZT_IdentificationCertificate_Node *nodes; ZT_Certificate_Identity *identities;
/** /**
* Networks owned by this entity * Networks owned by this entity
*/ */
ZT_IdentificationCertificate_Network *networks; ZT_Certificate_Network *networks;
/** /**
* Number of nodes * Serial numbers of other certificates being signed (each is 48 bytes / 384 bits)
*/ */
unsigned int nodeCount; const uint8_t *const *certificates;
/**
* Number of identities
*/
unsigned int identityCount;
/** /**
* Number of networks * Number of networks
*/ */
unsigned int networkCount; unsigned int networkCount;
/**
* Number of certificates
*/
unsigned int certificateCount;
/** /**
* Information about owner of items. * Information about owner of items.
*/ */
ZT_IdentificationCertificate_Name name; ZT_Certificate_Name name;
} ZT_IdentificationCertificate_Subject; } ZT_Certificate_Subject;
/** /**
* Identification certificate * Certificate
* *
* This is designed so it could be converted to/from an X509 format * This is designed to be compatible with x509 certificate interfaces,
* for interoperability with X509 systems. OCSP could be implemented * presenting similar concepts and fields.
* too, though it would probably require the development of an OCSP *
* proxy server that queried the issuer via the ZeroTier protocol. * It's not X509 because we want to keep ZeroTier clean, as simple as
* possible, small, and secure. X509 is both bloated and a security
* disaster as it's very hard to implement correctly.
*/ */
typedef struct typedef struct
{ {
@ -404,20 +457,6 @@ typedef struct
*/ */
uint8_t serialNo[48]; uint8_t serialNo[48];
/**
* Certificate version
*/
unsigned int version;
/**
* Maximum path length from this certificate toward further certificates.
*
* Subjects may sign other certificates whose path lengths are less than
* this value. A value of zero indicates that no identification certificates
* may be signed (not a CA).
*/
unsigned int maxPathLength;
/** /**
* Flags indicating certificate usage and any other attributes. * Flags indicating certificate usage and any other attributes.
*/ */
@ -434,7 +473,7 @@ typedef struct
/** /**
* Subject of certificate * Subject of certificate
*/ */
ZT_IdentificationCertificate_Subject subject; ZT_Certificate_Subject subject;
/** /**
* Issuer node identity and public key(s). * Issuer node identity and public key(s).
@ -444,7 +483,7 @@ typedef struct
/** /**
* Issuer information * Issuer information
*/ */
ZT_IdentificationCertificate_Name issuerName; ZT_Certificate_Name issuerName;
/** /**
* URLs that can be consulted for updates to this certificate. * URLs that can be consulted for updates to this certificate.
@ -456,6 +495,15 @@ typedef struct
*/ */
unsigned int updateUrlCount; unsigned int updateUrlCount;
/**
* Maximum path length from this certificate toward further certificates.
*
* Subjects may sign other certificates whose path lengths are less than
* this value. A value of zero indicates that no identification certificates
* may be signed (not a CA).
*/
unsigned int maxPathLength;
/** /**
* Size of signature in bytes. * Size of signature in bytes.
*/ */
@ -464,8 +512,8 @@ typedef struct
/** /**
* Signature by issuer (algorithm determined by identity type). * Signature by issuer (algorithm determined by identity type).
*/ */
uint8_t signature[ZT_IDENTIFICATION_CERTIFICATE_MAX_SIGNATURE_SIZE]; uint8_t signature[ZT_CERTIFICATE_MAX_SIGNATURE_SIZE];
} ZT_IdentificationCertificate; } ZT_Certificate;
/** /**
* Credential type IDs * Credential type IDs