Add prototype key management API
This commit is contained in:
118
examples/cpp/keymanagement.cpp
Normal file
118
examples/cpp/keymanagement.cpp
Normal 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;
|
||||||
|
}
|
||||||
@@ -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 user’s 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);
|
||||||
|
|||||||
145
src/Controls.cpp
145
src/Controls.cpp
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
Reference in New Issue
Block a user