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

@@ -0,0 +1,118 @@
/**
* libzt API example
*
* Demonstrates how to manage ZeroTier node identities (public/secret keypairs) without
* local storage. In this mode you are responsible for saving keys.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ZeroTierSockets.h"
struct Node
{
Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {}
bool online;
bool joinedAtLeastOneNetwork;
uint64_t id;
// etc
} myNode;
/* Callback handler, you should return control from this function as quickly as you can
to ensure timely receipt of future events. You should not call libzt API functions from
this function unless it's something trivial like zts_inet_ntop() or similar that has
no state-change implications. */
void on_zts_event(void *msgPtr)
{
struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr;
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) {
printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address);
myNode.id = msg->node->address;
myNode.online = true;
}
if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) {
printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n");
myNode.online = false;
}
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) {
printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n",
msg->network->nwid);
myNode.joinedAtLeastOneNetwork = true;
}
}
#define KEY_BUF_LEN 2048
int main(int argc, char **argv)
{
if (argc != 3) {
printf("\nlibzt example\n");
printf("earthtest <config_file_path> <ztServicePort>\n");
exit(0);
}
int ztServicePort = atoi(argv[2]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994)
int err = ZTS_ERR_OK;
// BEGIN key handling
// Do not allow ZT to write anything to disk
zts_disable_local_storage(1);
// Buffer used to store identity keypair (if someone can read this, they can impersonate your node!)
char keypair[KEY_BUF_LEN];
memset(keypair, 0, KEY_BUF_LEN);
printf("\n\nGenerating new identity...\n");
uint16_t keypair_len = KEY_BUF_LEN;
zts_generate_orphan_identity(keypair, &keypair_len);
printf("keypair(len=%d) = [%s]\n", keypair_len, keypair);
// Verification is not necessary, but could be useful after reading identities from
// your custom data store.
printf("\n\nVerifying ident...\n");
if (zts_verify_identity(keypair)) {
printf("\tIdentity is valid\n");
} else {
printf("\tIdentity is invalid\n");
}
printf("\n\nStarting node with generated identity...\n");
zts_start_with_identity(keypair, keypair_len, &on_zts_event, ztServicePort);
printf("\n\nWaiting for node to come online...\n");
while (!myNode.online) { zts_delay_ms(50); }
printf("\n\nAs a test, copy node's identity keypair back into buffer...\n");
memset(keypair, 0, KEY_BUF_LEN);
keypair_len = KEY_BUF_LEN;
zts_get_node_identity(keypair, &keypair_len);
printf("keypair(len=%d) = [%s]\n", keypair_len, keypair);
// END key handling
uint64_t nwid = 0x8056c2e21c000001;
if((err = zts_join(nwid)) != ZTS_ERR_OK) {
printf("Unable to join network, error = %d. Exiting.\n", err);
exit(1);
}
printf("Joining network %llx\n", nwid);
while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); }
// Idle and just show callback events, stack statistics, etc
printf("Node will now idle...\n");
while (true) { zts_delay_ms(1000); }
// Shut down service and stack threads
zts_stop();
return 0;
}

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 * Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory. * 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 * 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. * of this software will be governed by version 2.0 of the Apache License.
@@ -840,6 +840,201 @@ struct zts_peer_list
#define ZTCALL #define ZTCALL
#endif #endif
//////////////////////////////////////////////////////////////////////////////
// Central API //
//////////////////////////////////////////////////////////////////////////////
#ifndef NO_CENTRAL_API
#define CENTRAL_API_DEFAULT_URL "https://my.zerotier.com"
#define CENRTAL_API_MAX_URL_LEN 128
#define CENTRAL_API_TOKEN_LEN 32
#define CENTRAL_API_RESP_BUF_DEFAULT_SZ (128*1024)
#define HTTP_GET 0
#define HTTP_POST 1
#define HTTP_DELETE 2
#define ZTS_CENTRAL_NODE_AUTH_FALSE 0
#define ZTS_CENTRAL_NODE_AUTH_TRUE 1
#define ZTS_CENTRAL_READ 1
#define ZTS_CENTRAL_WRITE 2
/**
* @brief Enables read/write capability. Default before calling this is
* read-only (ZTS_CENTRAL_READ.)
*
* @param modes Whether the API allows read, write, or both
*/
ZTS_API void ZTCALL zts_central_api_set_access(int8_t modes);
/**
* @brief Enables or disables libcurl verbosity
*
* @param is_verbose Whether debug information is desired
*/
ZTS_API void ZTCALL zts_central_api_set_verbose(int8_t is_verbose);
ZTS_API void ZTCALL zts_central_api_clear_response_buffer();
/**
* @brief Set the Central API URL and user API token.
*
* @param url_str The URL to the Central API server
* @param token_str User API token
* @param response_buffer Destination buffer for raw JSON output
* @param buffer_len Size of buffer for server response (specify 0 for default size)
* @return ZTS_ERR_OK on success. ZTS_ERR_ARG if invalid arguments provided.
*/
ZTS_API int ZTCALL zts_central_api_init(const char *url_str, const char *token_str, char *response_buffer, uint32_t buffer_len);
ZTS_API void ZTCALL zts_central_api_cleanup();
/**
* @brief Copies the JSON-formatted string buffer from the last request into a user-provided buffer.
*
* @param dest_buffer User-provided destination buffer
* @param dest_buffer_len Length of aforementioned buffer
* @return ZTS_ERR_OK if all contents were copied successfully. ZTS_ERR_ARG if provided buffer was too small.
*/
ZTS_API int ZTCALL zts_get_last_response_buffer(char *dest_buffer, int dest_buffer_len);
/**
* @brief Get the status of the Central API server.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_status(int *http_response_code);
/**
* @brief Get the currently authenticated users user record.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_self(int *http_response_code);
/**
* @brief Retrieve a Network.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_network(int *http_response_code, int64_t nwid);
/**
* @brief Update or create a Network.
*
* Only fields marked as [rw] can be directly modified. If other fields are
* present in the posted request they are ignored. New networks can be created by POSTing
* to /api/network with no networkId parameter. The server will create a random unused
* network ID and return the new network record.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_update_network(int *http_response_code, int64_t nwid);
/**
* @brief Delete a Network.
*
* Delete a network and all its related information permanently.
* Use extreme caution as this cannot be undone!
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_delete_network(int *http_response_code, int64_t nwid);
/**
* @brief Get All Viewable Networks.
*
* Get all networks for which you have at least read access.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_networks(int *http_response_code);
/**
* @brief Retrieve a Member.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_member(int *http_response_code, int64_t nwid, int64_t nodeid);
/**
* @brief Update or add a Member.
*
* New members can be added to a network by POSTing them.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_update_member(int *http_response_code, int64_t nwid, int64_t nodeid, char *post_data);
/**
* @brief Authorize or (De)authorize a node on a network. This operation is idempotent.
*
* @param nwid The network ID
* @param nodeid The node ID
* @param is_authed Boolean value for whether this node should be authorized
* @return Standard HTTP response codes. ZTS_ERR_ARG invalid argument specified.
*/
ZTS_API int ZTCALL zts_set_node_auth(int *http_response_code, int64_t nwid, int64_t nodeid, int8_t is_authed);
/**
* @brief Get All Members of a Network.
*
* Get all members of a network for which you have at least read access.
*
* @return Standard HTTP response codes.
*/
ZTS_API int ZTCALL zts_central_api_get_members_of_network(int *http_response_code, int64_t nwid);
#endif // NO_CENTRAL_API
//////////////////////////////////////////////////////////////////////////////
// Identity Management //
//////////////////////////////////////////////////////////////////////////////
/**
* @brief Generates a node identity (public/secret keypair) and stores it in a user-provided buffer.
*
* @param key_pair_str User-provided destination buffer
* @param key_buf_len Length of user-provided destination buffer. Will be set to number of bytes copied.
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
*/
ZTS_API int ZTCALL zts_generate_orphan_identity(char *key_pair_str, uint16_t *key_buf_len);
/**
* @brief Verifies that a keypair is valid for use.
*
* @param key_pair_str Buffer containing keypair
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
*/
ZTS_API int ZTCALL zts_verify_identity(const char *key_pair_str);
/**
* @brief Copies the current node's identity into a buffer
*
* @param key_pair_str User-provided destination buffer
* @param key_buf_len Length of user-provided destination buffer. Will be set to number of bytes copied.
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
*/
ZTS_API int ZTCALL zts_get_node_identity(char *key_pair_str, uint16_t *key_buf_len);
/**
* @brief Starts the ZeroTier service and notifies user application of events via callback. This
* variant will assign a user-provided identity to the node.
*
* @param path path directory where configuration files are stored
* @param callback User-specified callback for ZTS_EVENT_* events
* @param port Port that the library should use for talking to other ZeroTier nodes
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure
*/
#ifdef ZTS_PINVOKE
ZTS_API int ZTCALL zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
CppCallback callback, uint16_t port);
#else
ZTS_API int ZTCALL zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
void (*callback)(void *), uint16_t port);
#endif
/** /**
* @brief Enable or disable whether the service will cache network details (enabled by default) * @brief Enable or disable whether the service will cache network details (enabled by default)
* *
@@ -882,14 +1077,24 @@ ZTS_API int ZTCALL zts_allow_peer_caching(uint8_t allowed);
*/ */
ZTS_API int ZTCALL zts_allow_local_conf(uint8_t allowed); ZTS_API int ZTCALL zts_allow_local_conf(uint8_t allowed);
/**
* @brief Enable or disable whether the service will read or write config data to local storage
*
* @usage Should be called before zts_start() if you intend on changing its state.
*
* @param enabled Whether or not this feature is enabled
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
*/
ZTS_API int ZTCALL zts_disable_local_storage(uint8_t disabled);
/** /**
* @brief Starts the ZeroTier service and notifies user application of events via callback * @brief Starts the ZeroTier service and notifies user application of events via callback
* *
* @param path path directory where configuration files are stored * @param path path directory where configuration files are stored
* @param callback User-specified callback for ZTS_EVENT_* events * @param callback User-specified callback for ZTS_EVENT_* events
* @param port Port that the library should use for talking to other ZeroTier nodes
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure * @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure
*/ */
#ifdef ZTS_PINVOKE #ifdef ZTS_PINVOKE
// Used by P/INVOKE wrappers // Used by P/INVOKE wrappers
typedef void (*CppCallback)(void *msg); typedef void (*CppCallback)(void *msg);

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 * Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory. * 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 * 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. * of this software will be governed by version 2.0 of the Apache License.
@@ -14,7 +14,7 @@
/** /**
* @file * @file
* *
* Network control interface * Node / Network control interface
*/ */
#include <inttypes.h> #include <inttypes.h>
@@ -50,6 +50,7 @@ namespace ZeroTier
extern uint8_t allowNetworkCaching; extern uint8_t allowNetworkCaching;
extern uint8_t allowPeerCaching; extern uint8_t allowPeerCaching;
extern uint8_t allowLocalConf; extern uint8_t allowLocalConf;
extern uint8_t disableLocalStorage; // Off by default
#ifdef SDK_JNI #ifdef SDK_JNI
// References to JNI objects and VM kept for future callbacks // References to JNI objects and VM kept for future callbacks
@@ -63,6 +64,134 @@ namespace ZeroTier
extern "C" { extern "C" {
#endif #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) int zts_allow_network_caching(uint8_t allowed = 1)
{ {
Mutex::Lock _l(serviceLock); Mutex::Lock _l(serviceLock);
@@ -93,6 +222,16 @@ int zts_allow_local_conf(uint8_t allowed = 1)
return ZTS_ERR_SERVICE; 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 #ifdef ZTS_PINVOKE
int zts_start(const char *path, CppCallback callback, uint16_t port) int zts_start(const char *path, CppCallback callback, uint16_t port)
#else #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 * Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory. * 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 * 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. * 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 allowNetworkCaching;
uint8_t allowPeerCaching; uint8_t allowPeerCaching;
uint8_t allowLocalConf; uint8_t allowLocalConf;
uint8_t disableLocalStorage; // Off by default
typedef VirtualTap EthernetTap; typedef VirtualTap EthernetTap;
@@ -937,6 +938,21 @@ public:
_node->leave(nwid, NULL, NULL); _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) inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{ {
char p[1024]; char p[1024];
@@ -947,16 +963,33 @@ public:
switch(type) { switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC: case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
memcpy(_userProvidedPublicIdentity, data, len);
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
}
break; break;
case ZT_STATE_OBJECT_IDENTITY_SECRET: case ZT_STATE_OBJECT_IDENTITY_SECRET:
memcpy(_userProvidedSecretIdentity, data, len);
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
}
secure = true; secure = true;
break; break;
case ZT_STATE_OBJECT_PLANET: case ZT_STATE_OBJECT_PLANET:
if (disableLocalStorage) {
return;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
}
break; break;
case ZT_STATE_OBJECT_NETWORK_CONFIG: case ZT_STATE_OBJECT_NETWORK_CONFIG:
if (disableLocalStorage) {
return;
} else {
if (allowNetworkCaching) { if (allowNetworkCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "networks.d",_homePath.c_str()); 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]); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.16llx.conf",dirname,(unsigned long long)id[0]);
@@ -964,14 +997,19 @@ public:
} else { } else {
return; return;
} }
}
break; break;
case ZT_STATE_OBJECT_PEER: case ZT_STATE_OBJECT_PEER:
if (disableLocalStorage) {
return;
} else {
if (allowPeerCaching) { if (allowPeerCaching) {
OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str()); 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]); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.10llx.peer",dirname,(unsigned long long)id[0]);
} else { } else {
return; // Do nothing return; // Do nothing
} }
}
break; break;
default: default:
return; return;
@@ -1009,26 +1047,58 @@ 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) inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen)
{ {
char p[4096]; char p[4096];
int keylen = 0;
switch(type) { switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC: case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
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()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
}
break; break;
case ZT_STATE_OBJECT_IDENTITY_SECRET: case ZT_STATE_OBJECT_IDENTITY_SECRET:
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()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
}
break; break;
case ZT_STATE_OBJECT_PLANET: case ZT_STATE_OBJECT_PLANET:
if (disableLocalStorage) {
return -1;
} else {
OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
}
break; break;
case ZT_STATE_OBJECT_NETWORK_CONFIG: case ZT_STATE_OBJECT_NETWORK_CONFIG:
if (disableLocalStorage) {
return -1;
} else {
if (allowNetworkCaching) { 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]); 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 { else {
return -1; return -1;
} }
}
break; break;
case ZT_STATE_OBJECT_PEER: case ZT_STATE_OBJECT_PEER:
if (allowPeerCaching) { if (allowPeerCaching) {
@@ -1312,6 +1382,11 @@ void *_runNodeService(void *arg)
service = NodeService::newInstance(params->path.c_str(),params->port); service = NodeService::newInstance(params->path.c_str(),params->port);
service->_userProvidedPort = params->port; service->_userProvidedPort = params->port;
service->_userProvidedPath = params->path; 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(); serviceLock.unlock();
switch(service->run()) { switch(service->run()) {
case NodeService::ONE_STILL_RUNNING: 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 * Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory. * 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 * 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. * of this software will be governed by version 2.0 of the Apache License.
@@ -54,6 +54,8 @@ public:
uint16_t _userProvidedPort; uint16_t _userProvidedPort;
std::string _userProvidedPath; 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 * Returned by node main if/when it terminates
@@ -171,6 +173,7 @@ public:
virtual void join(uint64_t nwid) = 0; virtual void join(uint64_t nwid) = 0;
virtual void leave(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) * Terminate background service (can be called from other threads)
@@ -203,6 +206,8 @@ struct serviceParameters
{ {
int port; int port;
std::string path; std::string path;
char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
}; };
#ifdef __WINDOWS__ #ifdef __WINDOWS__