Add prototype key management API

This commit is contained in:
Joseph Henry
2021-01-30 13:53:49 -08:00
parent 026d91dedf
commit 3544eab41d
5 changed files with 571 additions and 29 deletions

View File

@@ -1,10 +1,10 @@
/*
* Copyright (c)2013-2020 ZeroTier, Inc.
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2024-01-01
* Change Date: 2025-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -14,7 +14,7 @@
/**
* @file
*
* Network control interface
* Node / Network control interface
*/
#include <inttypes.h>
@@ -50,6 +50,7 @@ namespace ZeroTier
extern uint8_t allowNetworkCaching;
extern uint8_t allowPeerCaching;
extern uint8_t allowLocalConf;
extern uint8_t disableLocalStorage; // Off by default
#ifdef SDK_JNI
// References to JNI objects and VM kept for future callbacks
@@ -63,6 +64,134 @@ namespace ZeroTier
extern "C" {
#endif
int zts_generate_orphan_identity(char *key_pair_str, uint16_t *key_buf_len)
{
if (*key_buf_len < ZT_IDENTITY_STRING_BUFFER_LENGTH || key_pair_str == NULL) {
return ZTS_ERR_ARG;
}
Identity id;
id.generate();
char idtmp[1024];
std::string idser = id.toString(true,idtmp);
uint16_t key_pair_len = idser.length();
if (key_pair_len > *key_buf_len) {
return ZTS_ERR_ARG;
}
memcpy(key_pair_str, idser.c_str(), key_pair_len);
*key_buf_len = key_pair_len;
return ZTS_ERR_OK;
}
int zts_verify_identity(const char *key_pair_str)
{
if (key_pair_str == NULL || strlen(key_pair_str) > ZT_IDENTITY_STRING_BUFFER_LENGTH) {
return false;
}
Identity id;
if ((strlen(key_pair_str) > 32) && (key_pair_str[10] == ':')) {
if (id.fromString(key_pair_str)) {
return true;
}
}
return false;
}
int zts_get_node_identity(char *key_pair_str, uint16_t *key_buf_len)
{
Mutex::Lock _l(serviceLock);
if (*key_buf_len == 0 || key_pair_str == NULL) {
return ZTS_ERR_ARG;
}
if (!service) {
return ZTS_ERR_SERVICE;
}
service->getIdentity(key_pair_str, key_buf_len);
return *key_buf_len > 0 ? ZTS_ERR_OK : ZTS_ERR_GENERAL;
}
// TODO: This logic should be further generalized in the next API redesign
#ifdef ZTS_PINVOKE
int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
CppCallback callback, uint16_t port)
#else
int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
void (*callback)(void *), uint16_t port)
#endif
{
if (!zts_verify_identity(key_pair_str)) {
return ZTS_ERR_ARG;
}
Mutex::Lock _l(serviceLock);
_lwip_driver_init();
if (service || _getState(ZTS_STATE_NODE_RUNNING)) {
// Service is already initialized
return ZTS_ERR_SERVICE;
}
if (_getState(ZTS_STATE_FREE_CALLED)) {
// Stack (presumably lwIP) has been dismantled,
// an application restart is required now
return ZTS_ERR_SERVICE;
}
if (port < 0 || port > 0xFFFF) {
return ZTS_ERR_ARG;
}
serviceParameters *params = new serviceParameters();
params->port = port;
params->path = "";
Identity id;
if ((strlen(key_pair_str) > 32) && (key_pair_str[10] == ':')) {
if (id.fromString(key_pair_str)) {
id.toString(false, params->publicIdentityStr);
id.toString(true, params->secretIdentityStr);
}
}
if (!id) {
return ZTS_ERR_ARG;
}
#ifdef SDK_JNI
_userEventCallbackFunc = callback;
#else
_userEventCallbackFunc = callback;
#endif
if (!_isCallbackRegistered()) {
// Must have a callback
return ZTS_ERR_ARG;
}
int err;
int retval = ZTS_ERR_OK;
_setState(ZTS_STATE_CALLBACKS_RUNNING);
_setState(ZTS_STATE_NODE_RUNNING);
// Start the ZT service thread
#if defined(__WINDOWS__)
WSAStartup(MAKEWORD(2, 2), &wsaData);
HANDLE serviceThread = CreateThread(NULL, 0, _runNodeService, (void*)params, 0, NULL);
HANDLE callbackThread = CreateThread(NULL, 0, _runCallbacks, NULL, 0, NULL);
#else
pthread_t service_thread;
pthread_t callback_thread;
if ((err = pthread_create(&service_thread, NULL, _runNodeService, (void*)params)) != 0) {
retval = err;
}
if ((err = pthread_create(&callback_thread, NULL, _runCallbacks, NULL)) != 0) {
retval = err;
}
#endif
#if defined(__linux__)
pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME);
pthread_setname_np(callback_thread, ZTS_EVENT_CALLBACK_THREAD_NAME);
#endif
if (retval != ZTS_ERR_OK) {
_clrState(ZTS_STATE_CALLBACKS_RUNNING);
_clrState(ZTS_STATE_NODE_RUNNING);
_clearRegisteredCallback();
//delete params;
}
return retval;
}
int zts_allow_network_caching(uint8_t allowed = 1)
{
Mutex::Lock _l(serviceLock);
@@ -93,6 +222,16 @@ int zts_allow_local_conf(uint8_t allowed = 1)
return ZTS_ERR_SERVICE;
}
int zts_disable_local_storage(uint8_t disabled)
{
Mutex::Lock _l(serviceLock);
if(!service) {
disableLocalStorage = disabled;
return ZTS_ERR_OK;
}
return ZTS_ERR_SERVICE;
}
#ifdef ZTS_PINVOKE
int zts_start(const char *path, CppCallback callback, uint16_t port)
#else

View File

@@ -1,10 +1,10 @@
/*
* Copyright (c)2013-2020 ZeroTier, Inc.
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2024-01-01
* Change Date: 2025-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -63,6 +63,7 @@ namespace ZeroTier {
uint8_t allowNetworkCaching;
uint8_t allowPeerCaching;
uint8_t allowLocalConf;
uint8_t disableLocalStorage; // Off by default
typedef VirtualTap EthernetTap;
@@ -937,6 +938,21 @@ public:
_node->leave(nwid, NULL, NULL);
}
inline void getIdentity(char *key_pair_str, uint16_t *key_buf_len)
{
if (key_pair_str == NULL || *key_buf_len < ZT_IDENTITY_STRING_BUFFER_LENGTH) {
return;
}
uint16_t keylen = strlen(_userProvidedSecretIdentity);
if (*key_buf_len < keylen) {
*key_buf_len = 0;
return;
}
memcpy(key_pair_str, _userProvidedSecretIdentity, keylen);
*key_buf_len = keylen;
}
// TODO: This logic should be further generalized in the next API redesign
inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{
char p[1024];
@@ -947,30 +963,52 @@ public:
switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
memcpy(_userProvidedPublicIdentity, data, len);
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
}
break;
case ZT_STATE_OBJECT_IDENTITY_SECRET:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
memcpy(_userProvidedSecretIdentity, data, len);
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
}
secure = true;
break;
case ZT_STATE_OBJECT_PLANET:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
}
break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
if (allowNetworkCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str());
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
secure = true;
} else {
if (disableLocalStorage) {
return;
} else {
if (allowNetworkCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str());
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
secure = true;
} else {
return;
}
}
break;
case ZT_STATE_OBJECT_PEER:
if (allowPeerCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str());
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.10llx.peer",dirname,(unsigned long long)id[0]);
if (disableLocalStorage) {
return;
} else {
return; // Do nothing
if (allowPeerCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str());
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.10llx.peer",dirname,(unsigned long long)id[0]);
} else {
return; // Do nothing
}
}
break;
default:
@@ -1009,25 +1047,57 @@ public:
}
}
// TODO: This logic should be further generalized in the next API redesign
inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen)
{
char p[4096];
int keylen = 0;
switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
if (disableLocalStorage) {
keylen = strlen(_userProvidedPublicIdentity);
if (keylen > maxlen) {
return -1;
}
if (keylen > 0) {
memcpy(data, _userProvidedPublicIdentity, keylen);
return keylen;
}
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
}
break;
case ZT_STATE_OBJECT_IDENTITY_SECRET:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
if (disableLocalStorage) {
keylen = strlen(_userProvidedSecretIdentity);
if (keylen > maxlen) {
return -1;
}
if (keylen > 0) {
memcpy(data, _userProvidedSecretIdentity, keylen);
return keylen;
}
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
}
break;
case ZT_STATE_OBJECT_PLANET:
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
if (disableLocalStorage) {
return -1;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
}
break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
if (allowNetworkCaching) {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
}
else {
if (disableLocalStorage) {
return -1;
} else {
if (allowNetworkCaching) {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
}
else {
return -1;
}
}
break;
case ZT_STATE_OBJECT_PEER:
@@ -1312,6 +1382,11 @@ void *_runNodeService(void *arg)
service = NodeService::newInstance(params->path.c_str(),params->port);
service->_userProvidedPort = params->port;
service->_userProvidedPath = params->path;
if (strlen(params->publicIdentityStr) > 0 && strlen(params->secretIdentityStr) > 0 && params->path.length() == 0) {
memcpy(service->_userProvidedPublicIdentity, params->publicIdentityStr, strlen(params->publicIdentityStr));
memcpy(service->_userProvidedSecretIdentity, params->secretIdentityStr, strlen(params->secretIdentityStr));
}
serviceLock.unlock();
switch(service->run()) {
case NodeService::ONE_STILL_RUNNING:

View File

@@ -1,10 +1,10 @@
/*
* Copyright (c)2013-2020 ZeroTier, Inc.
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2024-01-01
* Change Date: 2025-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -54,6 +54,8 @@ public:
uint16_t _userProvidedPort;
std::string _userProvidedPath;
char _userProvidedPublicIdentity[ZT_IDENTITY_STRING_BUFFER_LENGTH];
char _userProvidedSecretIdentity[ZT_IDENTITY_STRING_BUFFER_LENGTH];
/**
* Returned by node main if/when it terminates
@@ -171,6 +173,7 @@ public:
virtual void join(uint64_t nwid) = 0;
virtual void leave(uint64_t nwid) = 0;
virtual void getIdentity(char *key_pair_str, uint16_t *key_buf_len) = 0;
/**
* Terminate background service (can be called from other threads)
@@ -203,6 +206,8 @@ struct serviceParameters
{
int port;
std::string path;
char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
};
#ifdef __WINDOWS__