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)
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)
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)
@ -64,10 +62,25 @@ endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(WIN32)
message("++ Setting Windows Compiler Flags ${CMAKE_BUILD_TYPE}")
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
-a
-trimpath
-ldflags '-w'
)
else(WIN32)
@ -77,6 +90,8 @@ else(WIN32)
-buildmode=pie
)
set(MACOS_VERSION_MIN "10.12")
if(APPLE)
message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
@ -85,7 +100,7 @@ else(WIN32)
-Wall
-Wno-deprecated
-Wno-unused-function
-mmacosx-version-min=10.12
-mmacosx-version-min=${MACOS_VERSION_MIN}
$<$<CONFIG:DEBUG>:-g>
$<$<CONFIG:DEBUG>:-O0>
$<$<CONFIG:RELEASE>:-Ofast>
@ -98,7 +113,7 @@ else(WIN32)
)
add_link_options(
-mmacosx-version-min=10.12
-mmacosx-version-min=${MACOS_VERSION_MIN}
$<$<CONFIG:RELEASE>:-flto>
)
@ -111,6 +126,7 @@ else(WIN32)
else(APPLE)
message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
add_compile_options(
-Wall
-Wno-deprecated
@ -186,7 +202,8 @@ add_subdirectory(serviceiocore)
file(GLOB go_src
${CMAKE_SOURCE_DIR}/cmd/*.go
${CMAKE_SOURCE_DIR}/cmd/cmd/*.go
${CMAKE_SOURCE_DIR}/pkg/zerotier/*.go)
${CMAKE_SOURCE_DIR}/pkg/zerotier/*.go
)
if(WIN32)
set(GO_EXE_NAME "zerotier.exe")

View file

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

View file

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

View file

@ -54,17 +54,16 @@ Commands:
peer <address> [command] [option] - Peer management commands
show Show peer details (default)
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
port <port> Primary P2P port
secondaryport <port/0> Secondary P2P port (0 to disable)
blacklist cidr <IP/bits> <boolean> Toggle physical path blacklisting
blacklist if <prefix> <boolean> Toggle interface prefix blacklisting
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
networks List networks run by local controller
new Create a new network
@ -80,6 +79,7 @@ Commands:
validate <identity> Locally validate an identity
sign <identity> <file> Sign a file with an identity's key
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
fingerprint containing both an address and a SHA384 hash, or an identity.

View file

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

View file

@ -43,12 +43,40 @@ func getAuthTokenPaths(basePath string) (p []string) {
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 {
fmt.Println("FATAL: unable to read API authorization token from command line or any filesystem location.")
os.Exit(1)
}
return authToken
}
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
// in pushing a lot of packets around. If that ever changes this should be adjusted.
runtime.GOMAXPROCS(1)
debug.SetGCPercent(20)
debug.SetGCPercent(15)
globalOpts := flag.NewFlagSet("global", flag.ContinueOnError)
hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities
@ -80,89 +108,43 @@ func main() {
if len(args) > 1 {
cmdArgs = args[1:]
}
basePath := zerotier.PlatformDefaultHomePath
if len(*pflag) > 0 {
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] {
case "help":
default:
//case "help":
cli.Help()
os.Exit(0)
case "version":
fmt.Printf("%d.%d.%d\n", zerotier.CoreVersionMajor, zerotier.CoreVersionMinor, zerotier.CoreVersionRevision)
os.Exit(0)
case "service":
cli.Service(basePath, authToken, cmdArgs)
cli.Service(basePath, cmdArgs)
case "status", "info":
authTokenRequired(authToken)
cli.Status(basePath, authToken, cmdArgs, *jflag)
cli.Status(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
case "join":
authTokenRequired(authToken)
cli.Join(basePath, authToken, cmdArgs)
cli.Join(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
case "leave":
authTokenRequired(authToken)
cli.Leave(basePath, authToken, cmdArgs)
cli.Leave(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
case "networks", "listnetworks":
authTokenRequired(authToken)
cli.Networks(basePath, authToken, cmdArgs, *jflag)
cli.Networks(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
case "network":
authTokenRequired(authToken)
cli.Network(basePath, authToken, cmdArgs, *jflag)
cli.Network(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
case "peers", "listpeers", "lspeers":
authTokenRequired(authToken)
cli.Peers(basePath, authToken, cmdArgs, *jflag, false)
cli.Peers(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag, false)
case "peer":
authTokenRequired(authToken)
authTokenRequired(basePath, *tflag, *tTflag)
case "roots":
authTokenRequired(authToken)
cli.Peers(basePath, authToken, cmdArgs, *jflag, true)
cli.Peers(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag, true)
case "root":
authTokenRequired(authToken)
cli.Root(basePath, authToken, cmdArgs, *jflag)
cli.Root(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
case "set":
authTokenRequired(authToken)
cli.Set(basePath, authToken, cmdArgs)
cli.Set(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs)
case "controller":
authTokenRequired(authToken)
cli.Controller(basePath, authToken, cmdArgs, *jflag)
cli.Controller(basePath, authTokenRequired(basePath, *tflag, *tTflag), cmdArgs, *jflag)
case "identity":
cli.Identity(cmdArgs)
}
// 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)
os.Exit(0)
}

View file

@ -23,7 +23,7 @@
#include "../core/Constants.hpp"
#include "../core/Node.hpp"
#include "../core/CertificateOfMembership.hpp"
#include "../core/MembershipCredential.hpp"
#include "../core/NetworkConfig.hpp"
#include "../core/Dictionary.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)
{
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);
{
std::lock_guard<std::mutex> l(_memberStatus_l);
@ -1370,7 +1370,7 @@ void EmbeddedNetworkController::_request(
++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()))
++nc->capabilityCount;
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) {
if (nc->tagCount >= ZT_MAX_NETWORK_TAGS)
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))
++nc->tagCount;
}
@ -1609,14 +1609,14 @@ void EmbeddedNetworkController::_request(
// Issue a certificate of ownership for all static IPs
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)
nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]);
nc->certificatesOfOwnership[0].sign(_signingId);
nc->certificateOfOwnershipCount = 1;
}
CertificateOfMembership com(now,credentialtmd,nwid,identity);
MembershipCredential com(now, credentialtmd, nwid, identity);
if (com.sign(_signingId)) {
nc->com = com;
} else {

View file

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

View file

@ -29,7 +29,10 @@ struct Blob
{
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); }

View file

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

View file

@ -11,14 +11,14 @@
*/
/****/
#include "Capability.hpp"
#include "CapabilityCredential.hpp"
#include "Utils.hpp"
#include "Constants.hpp"
#include "MAC.hpp"
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];
m_issuedTo = to;
@ -27,7 +27,7 @@ bool Capability::sign(const Identity &from, const Address &to) noexcept
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;
@ -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);
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
// 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;
}
int Capability::unmarshal(const uint8_t *data, int len) noexcept
int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept
{
if (len < 22)
return -1;
@ -138,7 +138,7 @@ int Capability::unmarshal(const uint8_t *data, int len) noexcept
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;
for (unsigned int i = 0;i < ruleCount;++i) {
@ -273,7 +273,7 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetwor
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;
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
* network scope rules do not deliver an explicit match.
*/
class Capability : public Credential
class CapabilityCredential : public Credential
{
friend class Credential;
public:
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
@ -67,7 +67,7 @@ public:
* @param rules Network flow rules for this capability
* @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_ts(ts),
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;
// 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 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 CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); }
private:
uint64_t m_nwid;

View file

@ -11,118 +11,177 @@
*/
/****/
#include "IdentificationCertificate.hpp"
#include "Certificate.hpp"
#include "SHA512.hpp"
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_locators.clear();
m_strings.clear();
m_nodes.clear();
m_networks.clear();
m_serials.clear();
m_subjectIdentities.clear();
m_subjectNetworks.clear();
m_updateUrls.clear();
m_subjectCertificates.clear();
}
IdentificationCertificate &IdentificationCertificate::operator=(const ZT_IdentificationCertificate &apiCert)
Certificate &Certificate::operator=(const ZT_Certificate &apiCert)
{
clear();
Utils::copy< sizeof(ZT_IdentificationCertificate) >((ZT_IdentificationCertificate *)this, &apiCert);
Utils::copy< sizeof(ZT_Certificate) >((ZT_Certificate *)this, &apiCert);
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.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) {
m_identities.push_back(*reinterpret_cast<const Identity *>(cert.issuer));
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) {
for (unsigned int i = 0; i < cert.updateUrlCount; ++i)
addUpdateUrl(cert.updateUrls[i]);
for (unsigned int i = 0; i < cert.updateUrlCount; ++i) {
if (cert.updateUrls[i])
addUpdateUrl(cert.updateUrls[i]);
}
}
return *this;
}
ZT_IdentificationCertificate_Node *IdentificationCertificate::addSubjectNode(const Identity &id)
ZT_Certificate_Identity *Certificate::addSubjectNode(const Identity &id)
{
m_nodes.resize(++this->subject.nodeCount);
this->subject.nodes = m_nodes.data();
// Enlarge array of ZT_Certificate_Identity structs and set pointer to potentially reallocated array.
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_nodes.back().identity = reinterpret_cast<ZT_Identity *>(&(m_identities.back()));
m_nodes.back().locator = nullptr;
return &(m_nodes.back());
// Set ZT_Certificate_Identity struct fields to point to local copy of identity.
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);
// Set pointer to stored local copy of locator.
n->locator = reinterpret_cast<ZT_Locator *>(&(m_locators.back()));
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);
this->subject.networks = m_networks.data();
m_networks.back().id = id;
Utils::copy< sizeof(ZT_Fingerprint) >(&(m_networks.back().controller), &controller);
return &(m_networks.back());
// Enlarge array of ZT_Certificate_Network and set pointer to potentially reallocated array.
m_subjectNetworks.resize(++this->subject.networkCount);
this->subject.networks = m_subjectNetworks.data();
// 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);
// 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());
this->updateUrls = m_updateUrls.data();
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];
Vector< uint8_t > enc;
Dictionary d;
d.add("v", (uint64_t)this->version);
d.add("mP", (uint64_t)this->maxPathLength);
// A Dictionary is used to encode certificates as it's a common and extensible
// format. Custom packed formats are used for credentials as these are smaller
// and faster to marshal/unmarshal.
d.add("f", this->flags);
d.add("v0", this->validity[0]);
d.add("v1", this->validity[1]);
d.add("mP", (uint64_t)this->maxPathLength);
d.add("s.n[]", (uint64_t)this->subject.nodeCount);
for (unsigned int i = 0; i < this->subject.nodeCount; ++i) {
d.addO(Dictionary::arraySubscript(tmp, "s.n[].i", i), *reinterpret_cast<const Identity *>(this->subject.nodes[i].identity));
if (this->subject.nodes[i].locator)
d.addO(Dictionary::arraySubscript(tmp, "s.n[].l", i), *reinterpret_cast<const Locator *>(this->subject.nodes[i].locator));
d.add("s.i$", (uint64_t)this->subject.identityCount);
for (unsigned int i = 0; i < this->subject.identityCount; ++i) {
if (this->subject.identities[i].identity)
d.addO(Dictionary::arraySubscript(tmp, "s.i$.i", i), *reinterpret_cast<const Identity *>(this->subject.identities[i].identity));
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) {
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);
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);
@ -152,10 +211,10 @@ Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) co
d.add("iN.e", this->issuerName.email);
d.add("iN.ur", this->issuerName.url);
d.add("uU[]", (uint64_t)this->updateUrlCount);
d.add("u$", (uint64_t)this->updateUrlCount);
if (this->updateUrls) {
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)))
@ -165,9 +224,9 @@ Vector< uint8_t > IdentificationCertificate::encode(const bool omitSignature) co
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();
@ -175,21 +234,20 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
if (!d.decode(data.data(), (unsigned int)data.size()))
return false;
this->version = (unsigned int)d.getUI("v");
this->maxPathLength = (unsigned int)d.getUI("mP");
this->flags = d.getUI("f");
this->validity[0] = (int64_t)d.getUI("v0");
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) {
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())
return false;
Identity id;
if (id.unmarshal(identityData.data(), (unsigned int)identityData.size()) <= 0)
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()) {
Locator loc;
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) {
const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.nw[].i", i));
if (nwid == 0)
return false;
const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.nw[].c", i)];
if (fingerprintData.empty())
const uint64_t nwid = d.getUI(Dictionary::arraySubscript(tmp, "s.n$.i", i));
const Vector< uint8_t > &fingerprintData = d[Dictionary::arraySubscript(tmp, "s.n$.c", i)];
if ((nwid == 0) || (fingerprintData.empty()))
return false;
Fingerprint fp;
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);
}
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.o", this->subject.name.organization, sizeof(this->subject.name.organization));
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.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) {
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)
addUpdateUrl(tmp2);
else return false;
@ -267,19 +331,21 @@ bool IdentificationCertificate::decode(const Vector< uint8_t > &data)
return true;
}
bool IdentificationCertificate::sign(const Identity &issuer)
bool Certificate::sign(const Identity &issuer)
{
Vector< uint8_t > enc(encode(true));
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;
}
bool IdentificationCertificate::verify() const
bool Certificate::verify() const
{
if (this->issuer) {
Vector< uint8_t > enc(encode(true));
return reinterpret_cast<const Identity *>(this->issuer)->verify(enc.data(), (unsigned int)enc.size(), this->signature, this->signatureSize);
}
try {
if (this->issuer) {
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;
}

View file

@ -11,8 +11,8 @@
*/
/****/
#ifndef ZT_IDENTIFICATIONCERTIFICATE_HPP
#define ZT_IDENTIFICATIONCERTIFICATE_HPP
#ifndef ZT_CERTIFICATE_HPP
#define ZT_CERTIFICATE_HPP
#include "Constants.hpp"
#include "SHA512.hpp"
@ -23,12 +23,13 @@
#include "Locator.hpp"
#include "Dictionary.hpp"
#include "Utils.hpp"
#include "Blob.hpp"
#include "Containers.hpp"
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
* 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
* called.
*/
class IdentificationCertificate : public ZT_IdentificationCertificate
class Certificate : public ZT_Certificate
{
public:
ZT_INLINE IdentificationCertificate() noexcept
ZT_INLINE Certificate() noexcept
{ this->clear(); }
ZT_INLINE IdentificationCertificate(const ZT_IdentificationCertificate &apiCert)
ZT_INLINE Certificate(const ZT_Certificate &apiCert)
{ *this = apiCert; }
ZT_INLINE IdentificationCertificate(const IdentificationCertificate &cert)
ZT_INLINE Certificate(const Certificate &cert)
{ *this = cert; }
/**
@ -61,9 +62,9 @@ public:
*/
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
@ -71,7 +72,7 @@ public:
* @param id Identity
* @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
@ -80,7 +81,7 @@ public:
* @param loc Locator signed by identity (signature is NOT checked here)
* @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
@ -89,7 +90,14 @@ public:
* @param controller Network controller's full fingerprint
* @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
@ -135,22 +143,22 @@ public:
ZT_INLINE unsigned long hashCode() const noexcept
{ 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; }
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; }
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; }
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; }
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; }
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; }
private:
@ -160,10 +168,12 @@ private:
List< Identity > m_identities;
List< Locator > m_locators;
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.
Vector< ZT_IdentificationCertificate_Node > m_nodes;
Vector< ZT_IdentificationCertificate_Network > m_networks;
Vector< ZT_Certificate_Identity > m_subjectIdentities;
Vector< ZT_Certificate_Network > m_subjectNetworks;
Vector< const uint8_t * > m_subjectCertificates;
Vector< const char * > m_updateUrls;
};

View file

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

View file

@ -14,11 +14,11 @@
#include "Constants.hpp"
#include "RuntimeEnvironment.hpp"
#include "Credential.hpp"
#include "Capability.hpp"
#include "Tag.hpp"
#include "CertificateOfMembership.hpp"
#include "CertificateOfOwnership.hpp"
#include "Revocation.hpp"
#include "CapabilityCredential.hpp"
#include "TagCredential.hpp"
#include "MembershipCredential.hpp"
#include "OwnershipCredential.hpp"
#include "RevocationCredential.hpp"
#include "Network.hpp"
#include "Topology.hpp"
@ -66,12 +66,12 @@ static ZT_INLINE Credential::VerifyResult _credVerify(const RuntimeEnvironment *
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 Tag &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 CertificateOfOwnership &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 TagCredential &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 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.
if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId)))

View file

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

View file

@ -431,7 +431,10 @@ private:
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

View file

@ -49,9 +49,7 @@ public:
* @param now Current time
*/
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.
@ -64,9 +62,7 @@ public:
* @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
{
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:
// 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
{ return (m_fp == id.m_fp); }
ZT_INLINE bool operator!=(const Identity &id) const noexcept
{ return !(*this == id); }
ZT_INLINE bool operator<(const Identity &id) const noexcept
{ return (m_fp < id.m_fp); }
ZT_INLINE bool operator>(const Identity &id) const noexcept
{ return (id < *this); }
ZT_INLINE bool operator<=(const Identity &id) const noexcept
{ return !(id < *this); }
ZT_INLINE bool operator>=(const Identity &id) const noexcept
{ return !(*this < id); }
static constexpr int marshalSizeMax() noexcept
{ return ZT_IDENTITY_MARSHAL_SIZE_MAX; }
int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX], bool includePrivate = false) const noexcept;
int unmarshal(const uint8_t *data, int len) noexcept;
private:

View file

@ -62,9 +62,7 @@ public:
* @param len Length, must be >= 6 or result is zero
*/
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
@ -221,44 +219,30 @@ public:
}
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
{ return (m_mac == m.m_mac); }
ZT_INLINE bool operator!=(const MAC &m) const noexcept
{ return (m_mac != m.m_mac); }
ZT_INLINE bool operator<(const MAC &m) const noexcept
{ return (m_mac < m.m_mac); }
ZT_INLINE bool operator<=(const MAC &m) const noexcept
{ return (m_mac <= m.m_mac); }
ZT_INLINE bool operator>(const MAC &m) const noexcept
{ return (m_mac > m.m_mac); }
ZT_INLINE bool operator>=(const MAC &m) const noexcept
{ return (m_mac >= m.m_mac); }
ZT_INLINE bool operator==(const uint64_t m) const noexcept
{ return (m_mac == m); }
ZT_INLINE bool operator!=(const uint64_t m) const noexcept
{ return (m_mac != m); }
ZT_INLINE bool operator<(const uint64_t m) const noexcept
{ return (m_mac < m); }
ZT_INLINE bool operator<=(const uint64_t m) const noexcept
{ return (m_mac <= m); }
ZT_INLINE bool operator>(const uint64_t m) const noexcept
{ return (m_mac > m); }
ZT_INLINE bool operator>=(const uint64_t m) const noexcept
{ return (m_mac >= m); }

View file

@ -13,14 +13,14 @@
#include <algorithm>
#include "Membership.hpp"
#include "Member.hpp"
#include "RuntimeEnvironment.hpp"
#include "Peer.hpp"
#include "Topology.hpp"
namespace ZeroTier {
Membership::Membership() :
Member::Member() :
m_comRevocationThreshold(0),
m_lastPushedCredentials(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
return;
#if 0
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;
bool sendCom = true;
@ -115,14 +115,14 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const i
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<Capability>(nconf, m_remoteCaps);
m_cleanCredImpl<CertificateOfOwnership>(nconf, m_remoteCoos);
m_cleanCredImpl<TagCredential>(nconf, m_remoteTags);
m_cleanCredImpl<CapabilityCredential>(nconf, m_remoteCaps);
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();
if (newts <= m_comRevocationThreshold) {
@ -141,7 +141,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
switch(com.verify(RR,tPtr)) {
default:
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:
m_com = com;
return ADD_ACCEPTED_NEW;
@ -155,7 +155,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
// 3/5 of the credential types have identical addCredential() code
template<typename C>
static ZT_INLINE Membership::AddCredentialResult _addCredImpl(
static ZT_INLINE Member::AddCredentialResult _addCredImpl(
Map<uint32_t,C> &remoteCreds,
const Map<uint64_t,int64_t> &revocations,
const RuntimeEnvironment *const RR,
@ -168,36 +168,36 @@ static ZT_INLINE Membership::AddCredentialResult _addCredImpl(
if (rc) {
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);
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
}
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())) {
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)) {
default:
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:
if (!rc)
rc = &(remoteCreds[cred.id()]);
*rc = cred;
return Membership::ADD_ACCEPTED_NEW;
return Member::ADD_ACCEPTED_NEW;
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); }
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); }
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 TagCredential &tag) { return _addCredImpl<TagCredential>(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 CapabilityCredential &cap) { return _addCredImpl<CapabilityCredential>(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 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;
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())) {
const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt()));

View file

@ -17,10 +17,10 @@
#include "Constants.hpp"
#include "Credential.hpp"
#include "Containers.hpp"
#include "CertificateOfMembership.hpp"
#include "Capability.hpp"
#include "Tag.hpp"
#include "Revocation.hpp"
#include "MembershipCredential.hpp"
#include "CapabilityCredential.hpp"
#include "TagCredential.hpp"
#include "RevocationCredential.hpp"
#include "NetworkConfig.hpp"
namespace ZeroTier {
@ -35,7 +35,7 @@ class Network;
*
* This class is not thread safe. It must be locked externally.
*/
class Membership
class Member
{
public:
enum AddCredentialResult
@ -46,7 +46,7 @@ public:
ADD_DEFERRED_FOR_WHOIS
};
Membership();
Member();
/**
* Send COM and other credentials to this peer
@ -71,10 +71,10 @@ public:
* @param id Tag ID
* @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);
return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (Tag *)0);
const TagCredential *const t = m_remoteTags.get(id);
return (((t)&&(m_isCredentialTimestampValid(nconf, *t))) ? t : (TagCredential *)0);
}
/**
@ -103,7 +103,7 @@ public:
{
if (m_isUnspoofableAddress(nconf, r))
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)))
return true;
}
@ -115,7 +115,7 @@ public:
*
* @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()))
return true;
@ -146,11 +146,11 @@ public:
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 Tag &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 CertificateOfOwnership &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 MembershipCredential &com);
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 CapabilityCredential &cap);
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 RevocationCredential &rev);
private:
// 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;
// Remote member's latest network COM
CertificateOfMembership m_com;
MembershipCredential m_com;
// Revocations by credentialKey()
Map<uint64_t,int64_t> m_revocations;
// Remote credentials that we have received from this member (and that are valid)
Map<uint32_t,Tag> m_remoteTags;
Map<uint32_t,Capability> m_remoteCaps;
Map<uint32_t,CertificateOfOwnership> m_remoteCoos;
Map<uint32_t,TagCredential> m_remoteTags;
Map<uint32_t,CapabilityCredential> m_remoteCaps;
Map<uint32_t,OwnershipCredential> m_remoteCoos;
public:
class CapabilityIterator
{
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_parent(m),
m_nconf(nconf)
{
}
ZT_INLINE Capability *next() noexcept
ZT_INLINE CapabilityCredential *next() noexcept
{
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))
return &(i->second);
}
@ -224,8 +224,8 @@ public:
}
private:
Map< uint32_t,Capability >::iterator m_hti;
Membership &m_parent;
Map< uint32_t,CapabilityCredential >::iterator m_hti;
Member &m_parent;
const NetworkConfig &m_nconf;
};
};

View file

@ -11,11 +11,11 @@
*/
/****/
#include "CertificateOfMembership.hpp"
#include "MembershipCredential.hpp"
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_timestampMaxDelta(timestampMaxDelta),
m_networkId(nwid),
@ -23,7 +23,7 @@ CertificateOfMembership::CertificateOfMembership(const int64_t timestamp, const
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
// 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);
}
bool CertificateOfMembership::sign(const Identity &with) noexcept
bool MembershipCredential::sign(const Identity &with) noexcept
{
m_signedBy = with.address();
uint64_t buf[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX / 8];
@ -94,7 +94,7 @@ bool CertificateOfMembership::sign(const Identity &with) noexcept
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;
@ -156,7 +156,7 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR
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))
return -1;
@ -241,7 +241,7 @@ int CertificateOfMembership::unmarshal(const uint8_t *data, int len) noexcept
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;

View file

@ -101,7 +101,7 @@ class RuntimeEnvironment;
* order with the fingerprint hash being packed into tuple IDs 3-8 and this buffer is
* then signed.
*/
class CertificateOfMembership : public Credential
class MembershipCredential : public Credential
{
friend class Credential;
@ -111,7 +111,7 @@ public:
/**
* 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
@ -121,12 +121,12 @@ public:
* @param nwid Network ID
* @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
*/
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
@ -166,7 +166,7 @@ public:
* @param other Cert to compare 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

View file

@ -74,7 +74,7 @@ _doZtFilterResult _doZtFilter(
const RuntimeEnvironment *RR,
Trace::RuleResultLog &rrl,
const NetworkConfig &nconf,
const Membership *membership, // can be NULL
const Member *membership, // can be NULL
const bool inbound,
const Address &ztSource,
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_XOR:
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)) {
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) {
const uint32_t ltv = localTag->value();
const uint32_t rtv = remoteTag->value();
@ -461,7 +461,7 @@ _doZtFilterResult _doZtFilter(
if (superAccept) {
thisRuleMatches = 1;
} 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) {
thisRuleMatches = (uint8_t)(remoteTag->value() == rules[rn].v.tag.value);
} else {
@ -474,7 +474,7 @@ _doZtFilterResult _doZtFilter(
}
}
} 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)) {
thisRuleMatches = (uint8_t)(localTag->value() == rules[rn].v.tag.value);
} else {
@ -626,7 +626,7 @@ bool Network::filterOutgoingPacket(
Mutex::Lock l1(m_memberships_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)) {
@ -719,7 +719,7 @@ bool Network::filterOutgoingPacket(
}
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);
} 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);
@ -745,19 +745,19 @@ int Network::filterIncomingPacket(
Address cc;
unsigned int ccLength = 0;
bool ccWatch = false;
const Capability *c = nullptr;
const CapabilityCredential *c = nullptr;
uint8_t qosBucket = 255; // For incoming packets this is a dummy value
Mutex::Lock l1(m_memberships_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)) {
case DOZTFILTER_NO_MATCH: {
Membership::CapabilityIterator mci(membership, m_config);
Member::CapabilityIterator mci(membership, m_config);
while ((c = mci.next())) {
ztFinalDest = ztDest; // sanity check, should be unmodified if there was no match
Address cc2;
@ -1074,7 +1074,7 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer) noexcept
try {
Mutex::Lock l(m_memberships_l);
Membership *m = m_memberships.get(peer->address());
Member *m = m_memberships.get(peer->address());
if (m) {
// SECURITY: this method in CertificateOfMembership does a full fingerprint check as well as
// 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);
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);
{
@ -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)
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l);
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)
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l);
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)
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l);
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)
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
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
/*
Address *a = nullptr;
@ -1208,10 +1208,10 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity
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)
return Membership::ADD_REJECTED;
return Member::ADD_REJECTED;
Mutex::Lock _l(m_memberships_l);
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());
Mutex::Lock _l(m_memberships_l);
Membership &m = m_memberships[to->address()];
Member &m = m_memberships[to->address()];
if (((now - m.lastPushedCredentials()) + 5000) >= tout) {
m.pushCredentials(RR, tPtr, now, to, m_config);
}

View file

@ -22,9 +22,9 @@
#include "MAC.hpp"
#include "Buf.hpp"
#include "Dictionary.hpp"
#include "Membership.hpp"
#include "Member.hpp"
#include "NetworkConfig.hpp"
#include "CertificateOfMembership.hpp"
#include "MembershipCredential.hpp"
#include "Containers.hpp"
#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
*/
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
*/
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
*/
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
*/
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
*/
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
@ -320,7 +320,7 @@ public:
ZT_INLINE void eachMember(F f)
{
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))
break;
}
@ -361,7 +361,7 @@ private:
NETCONF_FAILURE_INIT_FAILED
} _netconfFailure;
Map<Address,Membership> m_memberships;
Map<Address,Member> m_memberships;
Mutex m_myMulticastGroups_l;
Mutex m_remoteBridgeRoutes_l;

View file

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

View file

@ -18,10 +18,10 @@
#include "InetAddress.hpp"
#include "MulticastGroup.hpp"
#include "Address.hpp"
#include "CertificateOfMembership.hpp"
#include "CertificateOfOwnership.hpp"
#include "Capability.hpp"
#include "Tag.hpp"
#include "MembershipCredential.hpp"
#include "OwnershipCredential.hpp"
#include "CapabilityCredential.hpp"
#include "TagCredential.hpp"
#include "Dictionary.hpp"
#include "Identity.hpp"
#include "Utils.hpp"
@ -222,7 +222,7 @@ struct NetworkConfig : TriviallyCopyable
*/
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) {
if (capabilities[i].id() == id)
@ -231,7 +231,7 @@ struct NetworkConfig : TriviallyCopyable
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) {
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
*/
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
*/
Tag tags[ZT_MAX_NETWORK_TAGS];
TagCredential tags[ZT_MAX_NETWORK_TAGS];
/**
* 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)
@ -374,7 +374,7 @@ struct NetworkConfig : TriviallyCopyable
/**
* Certificate of membership (for private networks)
*/
CertificateOfMembership com;
MembershipCredential com;
};
} // namespace ZeroTier

View file

@ -17,7 +17,7 @@
#include "Constants.hpp"
#include "Dictionary.hpp"
#include "NetworkConfig.hpp"
#include "Revocation.hpp"
#include "RevocationCredential.hpp"
#include "Address.hpp"
namespace ZeroTier {
@ -62,7 +62,7 @@ public:
* @param destination Destination node address
* @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

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()) {
SharedPtr< Network > n(network(rev.networkId()));

View file

@ -358,7 +358,7 @@ public:
// Implementation of NetworkController::Sender interface
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);

View file

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

View file

@ -45,7 +45,7 @@ class RuntimeEnvironment;
* These are used in conjunction with the rules engine to make IP addresses and
* other identifiers un-spoofable.
*/
class CertificateOfOwnership : public Credential
class OwnershipCredential : public Credential
{
friend class Credential;
@ -60,9 +60,9 @@ public:
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);
m_networkId = nwid;
@ -139,10 +139,10 @@ public:
int unmarshal(const uint8_t *data,int len) noexcept;
// 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 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 OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); }
private:
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 {
bool Revocation::sign(const Identity &signer) noexcept
bool RevocationCredential::sign(const Identity &signer) noexcept
{
uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX + 32];
if (signer.hasPrivate()) {
@ -26,7 +26,7 @@ bool Revocation::sign(const Identity &signer) noexcept
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;
if (forSign) {
@ -67,7 +67,7 @@ int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSi
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)
return -1;

View file

@ -35,7 +35,7 @@ class RuntimeEnvironment;
/**
* Revocation certificate to instantaneously revoke a COM, capability, or tag
*/
class Revocation : public Credential
class RevocationCredential : public Credential
{
friend class Credential;
@ -43,7 +43,7 @@ public:
static constexpr ZT_CredentialType credentialType() noexcept
{ return ZT_CREDENTIAL_TYPE_REVOCATION; }
ZT_INLINE Revocation() noexcept
ZT_INLINE RevocationCredential() noexcept
{ 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 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_credentialId(cid),
m_networkId(nwid),

View file

@ -11,11 +11,11 @@
*/
/****/
#include "Tag.hpp"
#include "TagCredential.hpp"
namespace ZeroTier {
bool Tag::sign(const Identity &signer) noexcept
bool TagCredential::sign(const Identity &signer) noexcept
{
uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX];
if (signer.hasPrivate()) {
@ -26,7 +26,7 @@ bool Tag::sign(const Identity &signer) noexcept
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;
if (forSign) {
@ -61,7 +61,7 @@ int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign) const noex
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)
return -1;

View file

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

View file

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

View file

@ -39,18 +39,6 @@ SharedPtr< Peer > Topology::add(void *tPtr, const SharedPtr< Peer > &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)
{
if ((id != RR->identity) && id.locallyValidate()) {
@ -69,6 +57,10 @@ SharedPtr< Peer > Topology::addRoot(void *const tPtr, const Identity &id)
return SharedPtr< Peer >();
}
ZT_CertificateError addRootSet(void *tPtr, const Certificate &cert)
{
}
bool Topology::removeRoot(void *const tPtr, Address address)
{
RWMutex::Lock l1(m_peers_l);
@ -76,10 +68,22 @@ bool Topology::removeRoot(void *const tPtr, Address address)
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()
{
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)

View file

@ -25,7 +25,7 @@
#include "ScopedPtr.hpp"
#include "Fingerprint.hpp"
#include "Blob.hpp"
#include "IdentificationCertificate.hpp"
#include "Certificate.hpp"
#include "Containers.hpp"
namespace ZeroTier {
@ -182,6 +182,20 @@ public:
*/
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
*
@ -239,7 +253,8 @@ private:
RWMutex m_peers_l; // locks m_peers, m_roots, and m_rootPeers
Map< uint64_t, SharedPtr< Path > > m_paths;
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;
};

View file

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

View file

@ -32,9 +32,7 @@ namespace ZeroTier {
namespace {
ZT_INLINE const Identity &identityFromPeerPtr(const SharedPtr< Peer > &p)
{
return (p) ? p->identity() : Identity::NIL;
}
{ return (p) ? p->identity() : Identity::NIL; }
struct p_SalsaPolyCopyFunction
{
@ -100,8 +98,7 @@ struct p_PolyCopyFunction
VL1::VL1(const RuntimeEnvironment *renv) :
RR(renv)
{
}
{}
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;
/**
* 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
*/
#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
*/
#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.
*/
typedef struct
{
char country[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char organization[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char unit[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char locality[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char province[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char streetAddress[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char postalCode[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char commonName[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char serialNo[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char email[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
char url[ZT_IDENTIFICATION_CERTIFICATE_MAX_STRING_LENGTH + 1];
} ZT_IdentificationCertificate_Name;
char country[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char organization[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char unit[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char locality[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char province[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char streetAddress[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char postalCode[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char commonName[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char serialNo[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char email[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
char url[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
} ZT_Certificate_Name;
/**
* Identity and optional locator for a node
* Identity and optional locator to help find a node on physical networks.
*/
typedef struct
{
@ -337,10 +378,10 @@ typedef struct
const ZT_Identity *identity;
/**
* Locator or NULL if not specified
* Locator, or NULL if none
*/
const ZT_Locator *locator;
} ZT_IdentificationCertificate_Node;
} ZT_Certificate_Identity;
/**
* ID and primary controller for a network
@ -356,7 +397,7 @@ typedef struct
* Full fingerprint of primary controller
*/
ZT_Fingerprint controller;
} ZT_IdentificationCertificate_Network;
} ZT_Certificate_Network;
/**
* Identification certificate subject
@ -366,36 +407,48 @@ typedef struct
/**
* Identities and optional locators of nodes
*/
ZT_IdentificationCertificate_Node *nodes;
ZT_Certificate_Identity *identities;
/**
* 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
*/
unsigned int networkCount;
/**
* Number of certificates
*/
unsigned int certificateCount;
/**
* Information about owner of items.
*/
ZT_IdentificationCertificate_Name name;
} ZT_IdentificationCertificate_Subject;
ZT_Certificate_Name name;
} ZT_Certificate_Subject;
/**
* Identification certificate
* Certificate
*
* This is designed so it could be converted to/from an X509 format
* for interoperability with X509 systems. OCSP could be implemented
* too, though it would probably require the development of an OCSP
* proxy server that queried the issuer via the ZeroTier protocol.
* This is designed to be compatible with x509 certificate interfaces,
* presenting similar concepts and fields.
*
* 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
{
@ -404,20 +457,6 @@ typedef struct
*/
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.
*/
@ -434,7 +473,7 @@ typedef struct
/**
* Subject of certificate
*/
ZT_IdentificationCertificate_Subject subject;
ZT_Certificate_Subject subject;
/**
* Issuer node identity and public key(s).
@ -444,7 +483,7 @@ typedef struct
/**
* Issuer information
*/
ZT_IdentificationCertificate_Name issuerName;
ZT_Certificate_Name issuerName;
/**
* URLs that can be consulted for updates to this certificate.
@ -456,6 +495,15 @@ typedef struct
*/
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.
*/
@ -464,8 +512,8 @@ typedef struct
/**
* Signature by issuer (algorithm determined by identity type).
*/
uint8_t signature[ZT_IDENTIFICATION_CERTIFICATE_MAX_SIGNATURE_SIZE];
} ZT_IdentificationCertificate;
uint8_t signature[ZT_CERTIFICATE_MAX_SIGNATURE_SIZE];
} ZT_Certificate;
/**
* Credential type IDs