1 /*
2 * Copyright (c)2019 ZeroTier, Inc.
3 *
4 * Use of this software is governed by the Business Source License included
5 * in the LICENSE.TXT file in the project's root directory.
6 *
7 * Change Date: 2025-01-01
8 *
9 * On the date above, in accordance with the Business Source License, use
10 * of this software will be governed by version 2.0 of the Apache License.
11 */
12 /****/
13
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19
20 #ifndef _WIN32
21 #include <sys/time.h>
22 #endif
23 #include <sys/types.h>
24
25 #include <algorithm>
26 #include <utility>
27 #include <stdexcept>
28 #include <map>
29 #include <thread>
30 #include <memory>
31 #include <iomanip>
32 #include <sstream>
33 #include <cctype>
34
35 #include "../include/ZeroTierOne.h"
36 #include "../version.h"
37
38 #include "EmbeddedNetworkController.hpp"
39 #include "LFDB.hpp"
40 #include "FileDB.hpp"
41 #ifdef ZT_CONTROLLER_USE_LIBPQ
42 #include "PostgreSQL.hpp"
43 #endif
44
45 #include "../node/Node.hpp"
46 #include "../node/CertificateOfMembership.hpp"
47 #include "../node/NetworkConfig.hpp"
48 #include "../node/Dictionary.hpp"
49 #include "../node/MAC.hpp"
50
51 using json = nlohmann::json;
52
53 // API version reported via JSON control plane
54 #define ZT_NETCONF_CONTROLLER_API_VERSION 4
55
56 // Min duration between requests for an address/nwid combo to prevent floods
57 #define ZT_NETCONF_MIN_REQUEST_PERIOD 1000
58
59 // Global maximum size of arrays in JSON objects
60 #define ZT_CONTROLLER_MAX_ARRAY_SIZE 16384
61
62 namespace ZeroTier {
63
64 namespace {
65
url_encode(const std::string & value)66 std::string url_encode(const std::string &value) {
67 std::ostringstream escaped;
68 escaped.fill('0');
69 escaped << std::hex;
70
71 for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
72 std::string::value_type c = (*i);
73
74 // Keep alphanumeric and other accepted characters intact
75 if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
76 escaped << c;
77 continue;
78 }
79
80 // Any other characters are percent-encoded
81 escaped << std::uppercase;
82 escaped << '%' << std::setw(2) << int((unsigned char) c);
83 escaped << std::nouppercase;
84 }
85
86 return escaped.str();
87 }
88
_renderRule(ZT_VirtualNetworkRule & rule)89 static json _renderRule(ZT_VirtualNetworkRule &rule)
90 {
91 char tmp[128];
92 json r = json::object();
93 const ZT_VirtualNetworkRuleType rt = (ZT_VirtualNetworkRuleType)(rule.t & 0x3f);
94
95 switch(rt) {
96 case ZT_NETWORK_RULE_ACTION_DROP:
97 r["type"] = "ACTION_DROP";
98 break;
99 case ZT_NETWORK_RULE_ACTION_ACCEPT:
100 r["type"] = "ACTION_ACCEPT";
101 break;
102 case ZT_NETWORK_RULE_ACTION_TEE:
103 r["type"] = "ACTION_TEE";
104 r["address"] = Address(rule.v.fwd.address).toString(tmp);
105 r["flags"] = (unsigned int)rule.v.fwd.flags;
106 r["length"] = (unsigned int)rule.v.fwd.length;
107 break;
108 case ZT_NETWORK_RULE_ACTION_WATCH:
109 r["type"] = "ACTION_WATCH";
110 r["address"] = Address(rule.v.fwd.address).toString(tmp);
111 r["flags"] = (unsigned int)rule.v.fwd.flags;
112 r["length"] = (unsigned int)rule.v.fwd.length;
113 break;
114 case ZT_NETWORK_RULE_ACTION_REDIRECT:
115 r["type"] = "ACTION_REDIRECT";
116 r["address"] = Address(rule.v.fwd.address).toString(tmp);
117 r["flags"] = (unsigned int)rule.v.fwd.flags;
118 break;
119 case ZT_NETWORK_RULE_ACTION_BREAK:
120 r["type"] = "ACTION_BREAK";
121 break;
122 default:
123 break;
124 }
125
126 if (r.empty()) {
127 switch(rt) {
128 case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS:
129 r["type"] = "MATCH_SOURCE_ZEROTIER_ADDRESS";
130 r["zt"] = Address(rule.v.zt).toString(tmp);
131 break;
132 case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS:
133 r["type"] = "MATCH_DEST_ZEROTIER_ADDRESS";
134 r["zt"] = Address(rule.v.zt).toString(tmp);
135 break;
136 case ZT_NETWORK_RULE_MATCH_VLAN_ID:
137 r["type"] = "MATCH_VLAN_ID";
138 r["vlanId"] = (unsigned int)rule.v.vlanId;
139 break;
140 case ZT_NETWORK_RULE_MATCH_VLAN_PCP:
141 r["type"] = "MATCH_VLAN_PCP";
142 r["vlanPcp"] = (unsigned int)rule.v.vlanPcp;
143 break;
144 case ZT_NETWORK_RULE_MATCH_VLAN_DEI:
145 r["type"] = "MATCH_VLAN_DEI";
146 r["vlanDei"] = (unsigned int)rule.v.vlanDei;
147 break;
148 case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
149 r["type"] = "MATCH_MAC_SOURCE";
150 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
151 r["mac"] = tmp;
152 break;
153 case ZT_NETWORK_RULE_MATCH_MAC_DEST:
154 r["type"] = "MATCH_MAC_DEST";
155 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
156 r["mac"] = tmp;
157 break;
158 case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
159 r["type"] = "MATCH_IPV4_SOURCE";
160 r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp);
161 break;
162 case ZT_NETWORK_RULE_MATCH_IPV4_DEST:
163 r["type"] = "MATCH_IPV4_DEST";
164 r["ip"] = InetAddress(&(rule.v.ipv4.ip),4,(unsigned int)rule.v.ipv4.mask).toString(tmp);
165 break;
166 case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE:
167 r["type"] = "MATCH_IPV6_SOURCE";
168 r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp);
169 break;
170 case ZT_NETWORK_RULE_MATCH_IPV6_DEST:
171 r["type"] = "MATCH_IPV6_DEST";
172 r["ip"] = InetAddress(rule.v.ipv6.ip,16,(unsigned int)rule.v.ipv6.mask).toString(tmp);
173 break;
174 case ZT_NETWORK_RULE_MATCH_IP_TOS:
175 r["type"] = "MATCH_IP_TOS";
176 r["mask"] = (unsigned int)rule.v.ipTos.mask;
177 r["start"] = (unsigned int)rule.v.ipTos.value[0];
178 r["end"] = (unsigned int)rule.v.ipTos.value[1];
179 break;
180 case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL:
181 r["type"] = "MATCH_IP_PROTOCOL";
182 r["ipProtocol"] = (unsigned int)rule.v.ipProtocol;
183 break;
184 case ZT_NETWORK_RULE_MATCH_ETHERTYPE:
185 r["type"] = "MATCH_ETHERTYPE";
186 r["etherType"] = (unsigned int)rule.v.etherType;
187 break;
188 case ZT_NETWORK_RULE_MATCH_ICMP:
189 r["type"] = "MATCH_ICMP";
190 r["icmpType"] = (unsigned int)rule.v.icmp.type;
191 if ((rule.v.icmp.flags & 0x01) != 0)
192 r["icmpCode"] = (unsigned int)rule.v.icmp.code;
193 else r["icmpCode"] = json();
194 break;
195 case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE:
196 r["type"] = "MATCH_IP_SOURCE_PORT_RANGE";
197 r["start"] = (unsigned int)rule.v.port[0];
198 r["end"] = (unsigned int)rule.v.port[1];
199 break;
200 case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE:
201 r["type"] = "MATCH_IP_DEST_PORT_RANGE";
202 r["start"] = (unsigned int)rule.v.port[0];
203 r["end"] = (unsigned int)rule.v.port[1];
204 break;
205 case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
206 r["type"] = "MATCH_CHARACTERISTICS";
207 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics);
208 r["mask"] = tmp;
209 break;
210 case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
211 r["type"] = "MATCH_FRAME_SIZE_RANGE";
212 r["start"] = (unsigned int)rule.v.frameSize[0];
213 r["end"] = (unsigned int)rule.v.frameSize[1];
214 break;
215 case ZT_NETWORK_RULE_MATCH_RANDOM:
216 r["type"] = "MATCH_RANDOM";
217 r["probability"] = (unsigned long)rule.v.randomProbability;
218 break;
219 case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE:
220 r["type"] = "MATCH_TAGS_DIFFERENCE";
221 r["id"] = rule.v.tag.id;
222 r["value"] = rule.v.tag.value;
223 break;
224 case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND:
225 r["type"] = "MATCH_TAGS_BITWISE_AND";
226 r["id"] = rule.v.tag.id;
227 r["value"] = rule.v.tag.value;
228 break;
229 case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR:
230 r["type"] = "MATCH_TAGS_BITWISE_OR";
231 r["id"] = rule.v.tag.id;
232 r["value"] = rule.v.tag.value;
233 break;
234 case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR:
235 r["type"] = "MATCH_TAGS_BITWISE_XOR";
236 r["id"] = rule.v.tag.id;
237 r["value"] = rule.v.tag.value;
238 break;
239 case ZT_NETWORK_RULE_MATCH_TAGS_EQUAL:
240 r["type"] = "MATCH_TAGS_EQUAL";
241 r["id"] = rule.v.tag.id;
242 r["value"] = rule.v.tag.value;
243 break;
244 case ZT_NETWORK_RULE_MATCH_TAG_SENDER:
245 r["type"] = "MATCH_TAG_SENDER";
246 r["id"] = rule.v.tag.id;
247 r["value"] = rule.v.tag.value;
248 break;
249 case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER:
250 r["type"] = "MATCH_TAG_RECEIVER";
251 r["id"] = rule.v.tag.id;
252 r["value"] = rule.v.tag.value;
253 break;
254 case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE:
255 r["type"] = "INTEGER_RANGE";
256 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.intRange.start);
257 r["start"] = tmp;
258 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.intRange.start + (uint64_t)rule.v.intRange.end);
259 r["end"] = tmp;
260 r["idx"] = rule.v.intRange.idx;
261 r["little"] = ((rule.v.intRange.format & 0x80) != 0);
262 r["bits"] = (rule.v.intRange.format & 63) + 1;
263 break;
264 default:
265 break;
266 }
267
268 if (!r.empty()) {
269 r["not"] = ((rule.t & 0x80) != 0);
270 r["or"] = ((rule.t & 0x40) != 0);
271 }
272 }
273
274 return r;
275 }
276
_parseRule(json & r,ZT_VirtualNetworkRule & rule)277 static bool _parseRule(json &r,ZT_VirtualNetworkRule &rule)
278 {
279 if (!r.is_object())
280 return false;
281
282 const std::string t(OSUtils::jsonString(r["type"],""));
283 memset(&rule,0,sizeof(ZT_VirtualNetworkRule));
284
285 if (OSUtils::jsonBool(r["not"],false))
286 rule.t = 0x80;
287 else rule.t = 0x00;
288 if (OSUtils::jsonBool(r["or"],false))
289 rule.t |= 0x40;
290
291 bool tag = false;
292 if (t == "ACTION_DROP") {
293 rule.t |= ZT_NETWORK_RULE_ACTION_DROP;
294 return true;
295 } else if (t == "ACTION_ACCEPT") {
296 rule.t |= ZT_NETWORK_RULE_ACTION_ACCEPT;
297 return true;
298 } else if (t == "ACTION_TEE") {
299 rule.t |= ZT_NETWORK_RULE_ACTION_TEE;
300 rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL;
301 rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL);
302 rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"],0ULL) & 0xffffULL);
303 return true;
304 } else if (t == "ACTION_WATCH") {
305 rule.t |= ZT_NETWORK_RULE_ACTION_WATCH;
306 rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL;
307 rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL);
308 rule.v.fwd.length = (uint16_t)(OSUtils::jsonInt(r["length"],0ULL) & 0xffffULL);
309 return true;
310 } else if (t == "ACTION_REDIRECT") {
311 rule.t |= ZT_NETWORK_RULE_ACTION_REDIRECT;
312 rule.v.fwd.address = Utils::hexStrToU64(OSUtils::jsonString(r["address"],"0").c_str()) & 0xffffffffffULL;
313 rule.v.fwd.flags = (uint32_t)(OSUtils::jsonInt(r["flags"],0ULL) & 0xffffffffULL);
314 return true;
315 } else if (t == "ACTION_BREAK") {
316 rule.t |= ZT_NETWORK_RULE_ACTION_BREAK;
317 return true;
318 } else if (t == "MATCH_SOURCE_ZEROTIER_ADDRESS") {
319 rule.t |= ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS;
320 rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"],"0").c_str()) & 0xffffffffffULL;
321 return true;
322 } else if (t == "MATCH_DEST_ZEROTIER_ADDRESS") {
323 rule.t |= ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS;
324 rule.v.zt = Utils::hexStrToU64(OSUtils::jsonString(r["zt"],"0").c_str()) & 0xffffffffffULL;
325 return true;
326 } else if (t == "MATCH_VLAN_ID") {
327 rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_ID;
328 rule.v.vlanId = (uint16_t)(OSUtils::jsonInt(r["vlanId"],0ULL) & 0xffffULL);
329 return true;
330 } else if (t == "MATCH_VLAN_PCP") {
331 rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_PCP;
332 rule.v.vlanPcp = (uint8_t)(OSUtils::jsonInt(r["vlanPcp"],0ULL) & 0xffULL);
333 return true;
334 } else if (t == "MATCH_VLAN_DEI") {
335 rule.t |= ZT_NETWORK_RULE_MATCH_VLAN_DEI;
336 rule.v.vlanDei = (uint8_t)(OSUtils::jsonInt(r["vlanDei"],0ULL) & 0xffULL);
337 return true;
338 } else if (t == "MATCH_MAC_SOURCE") {
339 rule.t |= ZT_NETWORK_RULE_MATCH_MAC_SOURCE;
340 const std::string mac(OSUtils::jsonString(r["mac"],"0"));
341 Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6);
342 return true;
343 } else if (t == "MATCH_MAC_DEST") {
344 rule.t |= ZT_NETWORK_RULE_MATCH_MAC_DEST;
345 const std::string mac(OSUtils::jsonString(r["mac"],"0"));
346 Utils::unhex(mac.c_str(),(unsigned int)mac.length(),rule.v.mac,6);
347 return true;
348 } else if (t == "MATCH_IPV4_SOURCE") {
349 rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_SOURCE;
350 InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str());
351 rule.v.ipv4.ip = reinterpret_cast<struct sockaddr_in *>(&ip)->sin_addr.s_addr;
352 rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast<struct sockaddr_in *>(&ip)->sin_port) & 0xff;
353 if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32;
354 return true;
355 } else if (t == "MATCH_IPV4_DEST") {
356 rule.t |= ZT_NETWORK_RULE_MATCH_IPV4_DEST;
357 InetAddress ip(OSUtils::jsonString(r["ip"],"0.0.0.0").c_str());
358 rule.v.ipv4.ip = reinterpret_cast<struct sockaddr_in *>(&ip)->sin_addr.s_addr;
359 rule.v.ipv4.mask = Utils::ntoh(reinterpret_cast<struct sockaddr_in *>(&ip)->sin_port) & 0xff;
360 if (rule.v.ipv4.mask > 32) rule.v.ipv4.mask = 32;
361 return true;
362 } else if (t == "MATCH_IPV6_SOURCE") {
363 rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_SOURCE;
364 InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str());
365 memcpy(rule.v.ipv6.ip,reinterpret_cast<struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
366 rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast<struct sockaddr_in6 *>(&ip)->sin6_port) & 0xff;
367 if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128;
368 return true;
369 } else if (t == "MATCH_IPV6_DEST") {
370 rule.t |= ZT_NETWORK_RULE_MATCH_IPV6_DEST;
371 InetAddress ip(OSUtils::jsonString(r["ip"],"::0").c_str());
372 memcpy(rule.v.ipv6.ip,reinterpret_cast<struct sockaddr_in6 *>(&ip)->sin6_addr.s6_addr,16);
373 rule.v.ipv6.mask = Utils::ntoh(reinterpret_cast<struct sockaddr_in6 *>(&ip)->sin6_port) & 0xff;
374 if (rule.v.ipv6.mask > 128) rule.v.ipv6.mask = 128;
375 return true;
376 } else if (t == "MATCH_IP_TOS") {
377 rule.t |= ZT_NETWORK_RULE_MATCH_IP_TOS;
378 rule.v.ipTos.mask = (uint8_t)(OSUtils::jsonInt(r["mask"],0ULL) & 0xffULL);
379 rule.v.ipTos.value[0] = (uint8_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffULL);
380 rule.v.ipTos.value[1] = (uint8_t)(OSUtils::jsonInt(r["end"],0ULL) & 0xffULL);
381 return true;
382 } else if (t == "MATCH_IP_PROTOCOL") {
383 rule.t |= ZT_NETWORK_RULE_MATCH_IP_PROTOCOL;
384 rule.v.ipProtocol = (uint8_t)(OSUtils::jsonInt(r["ipProtocol"],0ULL) & 0xffULL);
385 return true;
386 } else if (t == "MATCH_ETHERTYPE") {
387 rule.t |= ZT_NETWORK_RULE_MATCH_ETHERTYPE;
388 rule.v.etherType = (uint16_t)(OSUtils::jsonInt(r["etherType"],0ULL) & 0xffffULL);
389 return true;
390 } else if (t == "MATCH_ICMP") {
391 rule.t |= ZT_NETWORK_RULE_MATCH_ICMP;
392 rule.v.icmp.type = (uint8_t)(OSUtils::jsonInt(r["icmpType"],0ULL) & 0xffULL);
393 json &code = r["icmpCode"];
394 if (code.is_null()) {
395 rule.v.icmp.code = 0;
396 rule.v.icmp.flags = 0x00;
397 } else {
398 rule.v.icmp.code = (uint8_t)(OSUtils::jsonInt(code,0ULL) & 0xffULL);
399 rule.v.icmp.flags = 0x01;
400 }
401 return true;
402 } else if (t == "MATCH_IP_SOURCE_PORT_RANGE") {
403 rule.t |= ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE;
404 rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL);
405 rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL);
406 return true;
407 } else if (t == "MATCH_IP_DEST_PORT_RANGE") {
408 rule.t |= ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE;
409 rule.v.port[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL);
410 rule.v.port[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.port[0]) & 0xffffULL);
411 return true;
412 } else if (t == "MATCH_CHARACTERISTICS") {
413 rule.t |= ZT_NETWORK_RULE_MATCH_CHARACTERISTICS;
414 if (r.count("mask")) {
415 json &v = r["mask"];
416 if (v.is_number()) {
417 rule.v.characteristics = v;
418 } else {
419 std::string tmp = v;
420 rule.v.characteristics = Utils::hexStrToU64(tmp.c_str());
421 }
422 }
423 return true;
424 } else if (t == "MATCH_FRAME_SIZE_RANGE") {
425 rule.t |= ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE;
426 rule.v.frameSize[0] = (uint16_t)(OSUtils::jsonInt(r["start"],0ULL) & 0xffffULL);
427 rule.v.frameSize[1] = (uint16_t)(OSUtils::jsonInt(r["end"],(uint64_t)rule.v.frameSize[0]) & 0xffffULL);
428 return true;
429 } else if (t == "MATCH_RANDOM") {
430 rule.t |= ZT_NETWORK_RULE_MATCH_RANDOM;
431 rule.v.randomProbability = (uint32_t)(OSUtils::jsonInt(r["probability"],0ULL) & 0xffffffffULL);
432 return true;
433 } else if (t == "MATCH_TAGS_DIFFERENCE") {
434 rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE;
435 tag = true;
436 } else if (t == "MATCH_TAGS_BITWISE_AND") {
437 rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND;
438 tag = true;
439 } else if (t == "MATCH_TAGS_BITWISE_OR") {
440 rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_OR;
441 tag = true;
442 } else if (t == "MATCH_TAGS_BITWISE_XOR") {
443 rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_XOR;
444 tag = true;
445 } else if (t == "MATCH_TAGS_EQUAL") {
446 rule.t |= ZT_NETWORK_RULE_MATCH_TAGS_EQUAL;
447 tag = true;
448 } else if (t == "MATCH_TAG_SENDER") {
449 rule.t |= ZT_NETWORK_RULE_MATCH_TAG_SENDER;
450 tag = true;
451 } else if (t == "MATCH_TAG_RECEIVER") {
452 rule.t |= ZT_NETWORK_RULE_MATCH_TAG_RECEIVER;
453 tag = true;
454 } else if (t == "INTEGER_RANGE") {
455 json &s = r["start"];
456 if (s.is_string()) {
457 std::string tmp = s;
458 rule.v.intRange.start = Utils::hexStrToU64(tmp.c_str());
459 } else {
460 rule.v.intRange.start = OSUtils::jsonInt(s,0ULL);
461 }
462 json &e = r["end"];
463 if (e.is_string()) {
464 std::string tmp = e;
465 rule.v.intRange.end = (uint32_t)(Utils::hexStrToU64(tmp.c_str()) - rule.v.intRange.start);
466 } else {
467 rule.v.intRange.end = (uint32_t)(OSUtils::jsonInt(e,0ULL) - rule.v.intRange.start);
468 }
469 rule.v.intRange.idx = (uint16_t)OSUtils::jsonInt(r["idx"],0ULL);
470 rule.v.intRange.format = (OSUtils::jsonBool(r["little"],false)) ? 0x80 : 0x00;
471 rule.v.intRange.format |= (uint8_t)((OSUtils::jsonInt(r["bits"],1ULL) - 1) & 63);
472 }
473
474 if (tag) {
475 rule.v.tag.id = (uint32_t)(OSUtils::jsonInt(r["id"],0ULL) & 0xffffffffULL);
476 rule.v.tag.value = (uint32_t)(OSUtils::jsonInt(r["value"],0ULL) & 0xffffffffULL);
477 return true;
478 }
479
480 return false;
481 }
482
483 } // anonymous namespace
484
EmbeddedNetworkController(Node * node,const char * ztPath,const char * dbPath,int listenPort,RedisConfig * rc)485 EmbeddedNetworkController::EmbeddedNetworkController(Node *node,const char *ztPath,const char *dbPath, int listenPort, RedisConfig *rc) :
486 _startTime(OSUtils::now()),
487 _listenPort(listenPort),
488 _node(node),
489 _ztPath(ztPath),
490 _path(dbPath),
491 _sender((NetworkController::Sender *)0),
492 _db(this),
493 _rc(rc)
494 {
495 }
496
~EmbeddedNetworkController()497 EmbeddedNetworkController::~EmbeddedNetworkController()
498 {
499 std::lock_guard<std::mutex> l(_threads_l);
500 _queue.stop();
501 for(auto t=_threads.begin();t!=_threads.end();++t)
502 t->join();
503 }
504
setSSORedirectURL(const std::string & url)505 void EmbeddedNetworkController::setSSORedirectURL(const std::string &url) {
506 _ssoRedirectURL = url_encode(url);
507 }
508
init(const Identity & signingId,Sender * sender)509 void EmbeddedNetworkController::init(const Identity &signingId,Sender *sender)
510 {
511 char tmp[64];
512 _signingId = signingId;
513 _sender = sender;
514 _signingIdAddressString = signingId.address().toString(tmp);
515
516 #ifdef ZT_CONTROLLER_USE_LIBPQ
517 if ((_path.length() > 9)&&(_path.substr(0,9) == "postgres:")) {
518 _db.addDB(std::shared_ptr<DB>(new PostgreSQL(_signingId,_path.substr(9).c_str(), _listenPort, _rc)));
519 } else {
520 #endif
521 _db.addDB(std::shared_ptr<DB>(new FileDB(_path.c_str())));
522 #ifdef ZT_CONTROLLER_USE_LIBPQ
523 }
524 #endif
525
526 std::string lfJSON;
527 OSUtils::readFile((_ztPath + ZT_PATH_SEPARATOR_S "local.conf").c_str(),lfJSON);
528 if (lfJSON.length() > 0) {
529 nlohmann::json lfConfig(OSUtils::jsonParse(lfJSON));
530 nlohmann::json &settings = lfConfig["settings"];
531 if (settings.is_object()) {
532 nlohmann::json &controllerDb = settings["controllerDb"];
533 if (controllerDb.is_object()) {
534 std::string type = controllerDb["type"];
535 if (type == "lf") {
536 std::string lfOwner = controllerDb["owner"];
537 std::string lfHost = controllerDb["host"];
538 int lfPort = controllerDb["port"];
539 bool storeOnlineState = controllerDb["storeOnlineState"];
540 if ((lfOwner.length())&&(lfHost.length())&&(lfPort > 0)&&(lfPort < 65536)) {
541 std::size_t pubHdrLoc = lfOwner.find("Public: ");
542 if ((pubHdrLoc > 0)&&((pubHdrLoc + 8) < lfOwner.length())) {
543 std::string lfOwnerPublic = lfOwner.substr(pubHdrLoc + 8);
544 std::size_t pubHdrEnd = lfOwnerPublic.find_first_of("\n\r\t ");
545 if (pubHdrEnd != std::string::npos) {
546 lfOwnerPublic = lfOwnerPublic.substr(0,pubHdrEnd);
547 _db.addDB(std::shared_ptr<DB>(new LFDB(_signingId,_path.c_str(),lfOwner.c_str(),lfOwnerPublic.c_str(),lfHost.c_str(),lfPort,storeOnlineState)));
548 }
549 }
550 }
551 }
552 }
553 }
554 }
555
556 _db.waitForReady();
557 }
558
request(uint64_t nwid,const InetAddress & fromAddr,uint64_t requestPacketId,const Identity & identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> & metaData)559 void EmbeddedNetworkController::request(
560 uint64_t nwid,
561 const InetAddress &fromAddr,
562 uint64_t requestPacketId,
563 const Identity &identity,
564 const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData)
565 {
566 if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender))
567 return;
568 _startThreads();
569 _RQEntry *qe = new _RQEntry;
570 qe->nwid = nwid;
571 qe->requestPacketId = requestPacketId;
572 qe->fromAddr = fromAddr;
573 qe->identity = identity;
574 qe->metaData = metaData;
575 qe->type = _RQEntry::RQENTRY_TYPE_REQUEST;
576 _queue.post(qe);
577 }
578
handleControlPlaneHttpGET(const std::vector<std::string> & path,const std::map<std::string,std::string> & urlArgs,const std::map<std::string,std::string> & headers,const std::string & body,std::string & responseBody,std::string & responseContentType)579 unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
580 const std::vector<std::string> &path,
581 const std::map<std::string,std::string> &urlArgs,
582 const std::map<std::string,std::string> &headers,
583 const std::string &body,
584 std::string &responseBody,
585 std::string &responseContentType)
586 {
587 if ((!path.empty())&&(path[0] == "network")) {
588
589 if ((path.size() >= 2)&&(path[1].length() == 16)) {
590 const uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
591 json network;
592 if (!_db.get(nwid,network))
593 return 404;
594
595 if (path.size() >= 3) {
596
597 if (path[2] == "member") {
598
599 if (path.size() >= 4) {
600 // Get member
601
602 const uint64_t address = Utils::hexStrToU64(path[3].c_str());
603 json member;
604 if (!_db.get(nwid,network,address,member))
605 return 404;
606 responseBody = OSUtils::jsonDump(member);
607 responseContentType = "application/json";
608
609 } else {
610 // List members and their revisions
611
612 responseBody = "{";
613 std::vector<json> members;
614 if (_db.get(nwid,network,members)) {
615 responseBody.reserve((members.size() + 2) * 32);
616 std::string mid;
617 for(auto member=members.begin();member!=members.end();++member) {
618 mid = OSUtils::jsonString((*member)["id"], "");
619 char tmp[128];
620 OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s\"%s\":%llu",(responseBody.length() > 1) ? "," : "",mid.c_str(),(unsigned long long)OSUtils::jsonInt((*member)["revision"],0));
621 responseBody.append(tmp);
622 }
623 }
624 responseBody.push_back('}');
625 responseContentType = "application/json";
626
627 }
628 return 200;
629
630 } // else 404
631
632 } else {
633 // Get network
634
635 responseBody = OSUtils::jsonDump(network);
636 responseContentType = "application/json";
637 return 200;
638
639 }
640 } else if (path.size() == 1) {
641 // List networks
642
643 std::set<uint64_t> networkIds;
644 _db.networks(networkIds);
645 char tmp[64];
646 responseBody = "[";
647 responseBody.reserve((networkIds.size() + 1) * 24);
648 for(std::set<uint64_t>::const_iterator i(networkIds.begin());i!=networkIds.end();++i) {
649 if (responseBody.length() > 1)
650 responseBody.push_back(',');
651 OSUtils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i);
652 responseBody.append(tmp);
653 }
654 responseBody.push_back(']');
655 responseContentType = "application/json";
656
657 return 200;
658
659 } // else 404
660
661 } else {
662 // Controller status
663
664 char tmp[4096];
665 const bool dbOk = _db.isReady();
666 OSUtils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu,\n\t\"databaseReady\": %s\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now(),dbOk ? "true" : "false");
667 responseBody = tmp;
668 responseContentType = "application/json";
669 return dbOk ? 200 : 503;
670
671 }
672
673 return 404;
674 }
675
handleControlPlaneHttpPOST(const std::vector<std::string> & path,const std::map<std::string,std::string> & urlArgs,const std::map<std::string,std::string> & headers,const std::string & body,std::string & responseBody,std::string & responseContentType)676 unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
677 const std::vector<std::string> &path,
678 const std::map<std::string,std::string> &urlArgs,
679 const std::map<std::string,std::string> &headers,
680 const std::string &body,
681 std::string &responseBody,
682 std::string &responseContentType)
683 {
684 if (path.empty())
685 return 404;
686
687 json b;
688 try {
689 b = OSUtils::jsonParse(body);
690 if (!b.is_object()) {
691 responseBody = "{ \"message\": \"body is not a JSON object\" }";
692 responseContentType = "application/json";
693 return 400;
694 }
695 } catch ( ... ) {
696 responseBody = "{ \"message\": \"body JSON is invalid\" }";
697 responseContentType = "application/json";
698 return 400;
699 }
700 const int64_t now = OSUtils::now();
701
702 if (path[0] == "network") {
703
704 if ((path.size() >= 2)&&(path[1].length() == 16)) {
705 uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
706 char nwids[24];
707 OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
708
709 if (path.size() >= 3) {
710
711 if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
712 uint64_t address = Utils::hexStrToU64(path[3].c_str());
713 char addrs[24];
714 OSUtils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address);
715
716 json member,network;
717 _db.get(nwid,network,address,member);
718 DB::initMember(member);
719
720 try {
721 if (b.count("activeBridge")) member["activeBridge"] = OSUtils::jsonBool(b["activeBridge"], false);
722 if (b.count("noAutoAssignIps")) member["noAutoAssignIps"] = OSUtils::jsonBool(b["noAutoAssignIps"], false);
723 if (b.count("authenticationExpiryTime")) member["authenticationExpiryTime"] = (uint64_t)OSUtils::jsonInt(b["authenticationExpiryTime"], 0ULL);
724 if (b.count("authenticationURL")) member["authenticationURL"] = OSUtils::jsonString(b["authenticationURL"], "");
725
726 if (b.count("remoteTraceTarget")) {
727 const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"],""));
728 if (rtt.length() == 10) {
729 member["remoteTraceTarget"] = rtt;
730 } else {
731 member["remoteTraceTarget"] = json();
732 }
733 }
734 if (b.count("remoteTraceLevel")) member["remoteTraceLevel"] = OSUtils::jsonInt(b["remoteTraceLevel"],0ULL);
735
736 if (b.count("authorized")) {
737 const bool newAuth = OSUtils::jsonBool(b["authorized"],false);
738 if (newAuth != OSUtils::jsonBool(member["authorized"],false)) {
739 member["authorized"] = newAuth;
740 member[((newAuth) ? "lastAuthorizedTime" : "lastDeauthorizedTime")] = now;
741 if (newAuth) {
742 member["lastAuthorizedCredentialType"] = "api";
743 member["lastAuthorizedCredential"] = json();
744 }
745 }
746 }
747
748 if (b.count("ipAssignments")) {
749 json &ipa = b["ipAssignments"];
750 if (ipa.is_array()) {
751 json mipa(json::array());
752 for(unsigned long i=0;i<ipa.size();++i) {
753 std::string ips = ipa[i];
754 InetAddress ip(ips.c_str());
755 if ((ip.ss_family == AF_INET)||(ip.ss_family == AF_INET6)) {
756 char tmpip[64];
757 mipa.push_back(ip.toIpString(tmpip));
758 if (mipa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
759 break;
760 }
761 }
762 member["ipAssignments"] = mipa;
763 }
764 }
765
766 if (b.count("tags")) {
767 json &tags = b["tags"];
768 if (tags.is_array()) {
769 std::map<uint64_t,uint64_t> mtags;
770 for(unsigned long i=0;i<tags.size();++i) {
771 json &tag = tags[i];
772 if ((tag.is_array())&&(tag.size() == 2))
773 mtags[OSUtils::jsonInt(tag[0],0ULL) & 0xffffffffULL] = OSUtils::jsonInt(tag[1],0ULL) & 0xffffffffULL;
774 }
775 json mtagsa = json::array();
776 for(std::map<uint64_t,uint64_t>::iterator t(mtags.begin());t!=mtags.end();++t) {
777 json ta = json::array();
778 ta.push_back(t->first);
779 ta.push_back(t->second);
780 mtagsa.push_back(ta);
781 if (mtagsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
782 break;
783 }
784 member["tags"] = mtagsa;
785 }
786 }
787
788 if (b.count("capabilities")) {
789 json &capabilities = b["capabilities"];
790 if (capabilities.is_array()) {
791 json mcaps = json::array();
792 for(unsigned long i=0;i<capabilities.size();++i) {
793 mcaps.push_back(OSUtils::jsonInt(capabilities[i],0ULL));
794 if (mcaps.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
795 break;
796 }
797 std::sort(mcaps.begin(),mcaps.end());
798 mcaps.erase(std::unique(mcaps.begin(),mcaps.end()),mcaps.end());
799 member["capabilities"] = mcaps;
800 }
801 }
802 } catch ( ... ) {
803 responseBody = "{ \"message\": \"exception while processing parameters in JSON body\" }";
804 responseContentType = "application/json";
805 return 400;
806 }
807
808 member["id"] = addrs;
809 member["address"] = addrs; // legacy
810 member["nwid"] = nwids;
811
812 DB::cleanMember(member);
813 _db.save(member,true);
814 responseBody = OSUtils::jsonDump(member);
815 responseContentType = "application/json";
816
817 return 200;
818 } // else 404
819
820 } else {
821 // POST to network ID
822
823 // Magic ID ending with ______ picks a random unused network ID
824 if (path[1].substr(10) == "______") {
825 nwid = 0;
826 uint64_t nwidPrefix = (Utils::hexStrToU64(path[1].substr(0,10).c_str()) << 24) & 0xffffffffff000000ULL;
827 uint64_t nwidPostfix = 0;
828 for(unsigned long k=0;k<100000;++k) { // sanity limit on trials
829 Utils::getSecureRandom(&nwidPostfix,sizeof(nwidPostfix));
830 uint64_t tryNwid = nwidPrefix | (nwidPostfix & 0xffffffULL);
831 if ((tryNwid & 0xffffffULL) == 0ULL) tryNwid |= 1ULL;
832 if (!_db.hasNetwork(tryNwid)) {
833 nwid = tryNwid;
834 break;
835 }
836 }
837 if (!nwid)
838 return 503;
839 }
840 OSUtils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
841
842 json network;
843 _db.get(nwid,network);
844 DB::initNetwork(network);
845
846 try {
847 if (b.count("name")) network["name"] = OSUtils::jsonString(b["name"],"");
848 if (b.count("private")) network["private"] = OSUtils::jsonBool(b["private"],true);
849 if (b.count("enableBroadcast")) network["enableBroadcast"] = OSUtils::jsonBool(b["enableBroadcast"],false);
850 if (b.count("multicastLimit")) network["multicastLimit"] = OSUtils::jsonInt(b["multicastLimit"],32ULL);
851 if (b.count("mtu")) network["mtu"] = std::max(std::min((unsigned int)OSUtils::jsonInt(b["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
852
853 if (b.count("remoteTraceTarget")) {
854 const std::string rtt(OSUtils::jsonString(b["remoteTraceTarget"],""));
855 if (rtt.length() == 10) {
856 network["remoteTraceTarget"] = rtt;
857 } else {
858 network["remoteTraceTarget"] = json();
859 }
860 }
861 if (b.count("remoteTraceLevel")) network["remoteTraceLevel"] = OSUtils::jsonInt(b["remoteTraceLevel"],0ULL);
862
863 if (b.count("v4AssignMode")) {
864 json nv4m;
865 json &v4m = b["v4AssignMode"];
866 if (v4m.is_string()) { // backward compatibility
867 nv4m["zt"] = (OSUtils::jsonString(v4m,"") == "zt");
868 } else if (v4m.is_object()) {
869 nv4m["zt"] = OSUtils::jsonBool(v4m["zt"],false);
870 } else nv4m["zt"] = false;
871 network["v4AssignMode"] = nv4m;
872 }
873
874 if (b.count("v6AssignMode")) {
875 json nv6m;
876 json &v6m = b["v6AssignMode"];
877 if (!nv6m.is_object()) nv6m = json::object();
878 if (v6m.is_string()) { // backward compatibility
879 std::vector<std::string> v6ms(OSUtils::split(OSUtils::jsonString(v6m,"").c_str(),",","",""));
880 std::sort(v6ms.begin(),v6ms.end());
881 v6ms.erase(std::unique(v6ms.begin(),v6ms.end()),v6ms.end());
882 nv6m["rfc4193"] = false;
883 nv6m["zt"] = false;
884 nv6m["6plane"] = false;
885 for(std::vector<std::string>::iterator i(v6ms.begin());i!=v6ms.end();++i) {
886 if (*i == "rfc4193")
887 nv6m["rfc4193"] = true;
888 else if (*i == "zt")
889 nv6m["zt"] = true;
890 else if (*i == "6plane")
891 nv6m["6plane"] = true;
892 }
893 } else if (v6m.is_object()) {
894 if (v6m.count("rfc4193")) nv6m["rfc4193"] = OSUtils::jsonBool(v6m["rfc4193"],false);
895 if (v6m.count("zt")) nv6m["zt"] = OSUtils::jsonBool(v6m["zt"],false);
896 if (v6m.count("6plane")) nv6m["6plane"] = OSUtils::jsonBool(v6m["6plane"],false);
897 } else {
898 nv6m["rfc4193"] = false;
899 nv6m["zt"] = false;
900 nv6m["6plane"] = false;
901 }
902 network["v6AssignMode"] = nv6m;
903 }
904
905 if (b.count("routes")) {
906 json &rts = b["routes"];
907 if (rts.is_array()) {
908 json nrts = json::array();
909 for(unsigned long i=0;i<rts.size();++i) {
910 json &rt = rts[i];
911 if (rt.is_object()) {
912 json &target = rt["target"];
913 json &via = rt["via"];
914 if (target.is_string()) {
915 InetAddress t(target.get<std::string>().c_str());
916 InetAddress v;
917 if (via.is_string()) v.fromString(via.get<std::string>().c_str());
918 if ( ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) && (t.netmaskBitsValid()) ) {
919 json tmp;
920 char tmp2[64];
921 tmp["target"] = t.toString(tmp2);
922 if (v.ss_family == t.ss_family)
923 tmp["via"] = v.toIpString(tmp2);
924 else tmp["via"] = json();
925 nrts.push_back(tmp);
926 if (nrts.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
927 break;
928 }
929 }
930 }
931 }
932 network["routes"] = nrts;
933 }
934 }
935
936 if (b.count("ipAssignmentPools")) {
937 json &ipp = b["ipAssignmentPools"];
938 if (ipp.is_array()) {
939 json nipp = json::array();
940 for(unsigned long i=0;i<ipp.size();++i) {
941 json &ip = ipp[i];
942 if ((ip.is_object())&&(ip.count("ipRangeStart"))&&(ip.count("ipRangeEnd"))) {
943 InetAddress f(OSUtils::jsonString(ip["ipRangeStart"],"").c_str());
944 InetAddress t(OSUtils::jsonString(ip["ipRangeEnd"],"").c_str());
945 if ( ((f.ss_family == AF_INET)||(f.ss_family == AF_INET6)) && (f.ss_family == t.ss_family) ) {
946 json tmp = json::object();
947 char tmp2[64];
948 tmp["ipRangeStart"] = f.toIpString(tmp2);
949 tmp["ipRangeEnd"] = t.toIpString(tmp2);
950 nipp.push_back(tmp);
951 if (nipp.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
952 break;
953 }
954 }
955 }
956 network["ipAssignmentPools"] = nipp;
957 }
958 }
959
960 if (b.count("rules")) {
961 json &rules = b["rules"];
962 if (rules.is_array()) {
963 json nrules = json::array();
964 for(unsigned long i=0;i<rules.size();++i) {
965 json &rule = rules[i];
966 if (rule.is_object()) {
967 ZT_VirtualNetworkRule ztr;
968 if (_parseRule(rule,ztr)) {
969 nrules.push_back(_renderRule(ztr));
970 if (nrules.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
971 break;
972 }
973 }
974 }
975 network["rules"] = nrules;
976 }
977 }
978
979 if (b.count("authTokens")) {
980 json &authTokens = b["authTokens"];
981 if (authTokens.is_object()) {
982 json nat;
983 for(json::iterator t(authTokens.begin());t!=authTokens.end();++t) {
984 if ((t.value().is_number())&&(t.value() >= 0))
985 nat[t.key()] = t.value();
986 }
987 network["authTokens"] = nat;
988 } else {
989 network["authTokens"] = {{}};
990 }
991 }
992
993 if (b.count("capabilities")) {
994 json &capabilities = b["capabilities"];
995 if (capabilities.is_array()) {
996 std::map< uint64_t,json > ncaps;
997 for(unsigned long i=0;i<capabilities.size();++i) {
998 json &cap = capabilities[i];
999 if (cap.is_object()) {
1000 json ncap = json::object();
1001 const uint64_t capId = OSUtils::jsonInt(cap["id"],0ULL);
1002 ncap["id"] = capId;
1003 ncap["default"] = OSUtils::jsonBool(cap["default"],false);
1004
1005 json &rules = cap["rules"];
1006 json nrules = json::array();
1007 if (rules.is_array()) {
1008 for(unsigned long i=0;i<rules.size();++i) {
1009 json &rule = rules[i];
1010 if (rule.is_object()) {
1011 ZT_VirtualNetworkRule ztr;
1012 if (_parseRule(rule,ztr)) {
1013 nrules.push_back(_renderRule(ztr));
1014 if (nrules.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
1015 break;
1016 }
1017 }
1018 }
1019 }
1020 ncap["rules"] = nrules;
1021
1022 ncaps[capId] = ncap;
1023 }
1024 }
1025
1026 json ncapsa = json::array();
1027 for(std::map< uint64_t,json >::iterator c(ncaps.begin());c!=ncaps.end();++c) {
1028 ncapsa.push_back(c->second);
1029 if (ncapsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
1030 break;
1031 }
1032 network["capabilities"] = ncapsa;
1033 }
1034 }
1035
1036 if (b.count("tags")) {
1037 json &tags = b["tags"];
1038 if (tags.is_array()) {
1039 std::map< uint64_t,json > ntags;
1040 for(unsigned long i=0;i<tags.size();++i) {
1041 json &tag = tags[i];
1042 if (tag.is_object()) {
1043 json ntag = json::object();
1044 const uint64_t tagId = OSUtils::jsonInt(tag["id"],0ULL);
1045 ntag["id"] = tagId;
1046 json &dfl = tag["default"];
1047 if (dfl.is_null())
1048 ntag["default"] = dfl;
1049 else ntag["default"] = OSUtils::jsonInt(dfl,0ULL);
1050 ntags[tagId] = ntag;
1051 }
1052 }
1053
1054 json ntagsa = json::array();
1055 for(std::map< uint64_t,json >::iterator t(ntags.begin());t!=ntags.end();++t) {
1056 ntagsa.push_back(t->second);
1057 if (ntagsa.size() >= ZT_CONTROLLER_MAX_ARRAY_SIZE)
1058 break;
1059 }
1060 network["tags"] = ntagsa;
1061 }
1062 }
1063
1064 if (b.count("dns")) {
1065 json &dns = b["dns"];
1066 if (dns.is_object()) {
1067 json nd;
1068
1069 nd["domain"] = dns["domain"];
1070
1071 json &srv = dns["servers"];
1072 if (srv.is_array()) {
1073 json ns = json::array();
1074 for(unsigned int i=0;i<srv.size();++i) {
1075 ns.push_back(srv[i]);
1076 }
1077 nd["servers"] = ns;
1078 }
1079
1080 network["dns"] = nd;
1081 }
1082 }
1083
1084 } catch ( ... ) {
1085 responseBody = "{ \"message\": \"exception occurred while parsing body variables\" }";
1086 responseContentType = "application/json";
1087 return 400;
1088 }
1089
1090 network["id"] = nwids;
1091 network["nwid"] = nwids; // legacy
1092
1093 DB::cleanNetwork(network);
1094 _db.save(network,true);
1095
1096 responseBody = OSUtils::jsonDump(network);
1097 responseContentType = "application/json";
1098 return 200;
1099 } // else 404
1100
1101 } // else 404
1102
1103 }
1104
1105 return 404;
1106 }
1107
handleControlPlaneHttpDELETE(const std::vector<std::string> & path,const std::map<std::string,std::string> & urlArgs,const std::map<std::string,std::string> & headers,const std::string & body,std::string & responseBody,std::string & responseContentType)1108 unsigned int EmbeddedNetworkController::handleControlPlaneHttpDELETE(
1109 const std::vector<std::string> &path,
1110 const std::map<std::string,std::string> &urlArgs,
1111 const std::map<std::string,std::string> &headers,
1112 const std::string &body,
1113 std::string &responseBody,
1114 std::string &responseContentType)
1115 {
1116 if (path.empty())
1117 return 404;
1118
1119 if (path[0] == "network") {
1120 if ((path.size() >= 2)&&(path[1].length() == 16)) {
1121 const uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
1122 if (path.size() >= 3) {
1123 if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
1124 const uint64_t address = Utils::hexStrToU64(path[3].c_str());
1125
1126 json network,member;
1127 _db.get(nwid,network,address,member);
1128 _db.eraseMember(nwid, address);
1129
1130 {
1131 std::lock_guard<std::mutex> l(_memberStatus_l);
1132 _memberStatus.erase(_MemberStatusKey(nwid,address));
1133 }
1134
1135 if (!member.size())
1136 return 404;
1137 responseBody = OSUtils::jsonDump(member);
1138 responseContentType = "application/json";
1139 return 200;
1140 }
1141 } else {
1142 json network;
1143 _db.get(nwid,network);
1144 _db.eraseNetwork(nwid);
1145
1146 {
1147 std::lock_guard<std::mutex> l(_memberStatus_l);
1148 for(auto i=_memberStatus.begin();i!=_memberStatus.end();) {
1149 if (i->first.networkId == nwid)
1150 _memberStatus.erase(i++);
1151 else ++i;
1152 }
1153 }
1154
1155 if (!network.size())
1156 return 404;
1157 responseBody = OSUtils::jsonDump(network);
1158 responseContentType = "application/json";
1159 return 200;
1160 }
1161 } // else 404
1162
1163 } // else 404
1164
1165 return 404;
1166 }
1167
handleRemoteTrace(const ZT_RemoteTrace & rt)1168 void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt)
1169 {
1170 static volatile unsigned long idCounter = 0;
1171 char id[128],tmp[128];
1172 std::string k,v;
1173
1174 try {
1175 // Convert Dictionary into JSON object
1176 json d;
1177 char *saveptr = (char *)0;
1178 for(char *l=Utils::stok(rt.data,"\n",&saveptr);(l);l=Utils::stok((char *)0,"\n",&saveptr)) {
1179 char *eq = strchr(l,'=');
1180 if (eq > l) {
1181 k.assign(l,(unsigned long)(eq - l));
1182 v.clear();
1183 ++eq;
1184 while (*eq) {
1185 if (*eq == '\\') {
1186 ++eq;
1187 if (*eq) {
1188 switch(*eq) {
1189 case 'r': v.push_back('\r'); break;
1190 case 'n': v.push_back('\n'); break;
1191 case '0': v.push_back((char)0); break;
1192 case 'e': v.push_back('='); break;
1193 default: v.push_back(*eq); break;
1194 }
1195 ++eq;
1196 }
1197 } else {
1198 v.push_back(*(eq++));
1199 }
1200 }
1201 if ((k.length() > 0)&&(v.length() > 0))
1202 d[k] = v;
1203 }
1204 }
1205
1206 const int64_t now = OSUtils::now();
1207 OSUtils::ztsnprintf(id,sizeof(id),"%.10llx-%.16llx-%.10llx-%.4x",_signingId.address().toInt(),now,rt.origin,(unsigned int)(idCounter++ & 0xffff));
1208 d["id"] = id;
1209 d["objtype"] = "trace";
1210 d["ts"] = now;
1211 d["nodeId"] = Utils::hex10(rt.origin,tmp);
1212 _db.save(d,true);
1213 } catch ( ... ) {
1214 // drop invalid trace messages if an error occurs
1215 }
1216 }
1217
onNetworkUpdate(const void * db,uint64_t networkId,const nlohmann::json & network)1218 void EmbeddedNetworkController::onNetworkUpdate(const void *db,uint64_t networkId,const nlohmann::json &network)
1219 {
1220 // Send an update to all members of the network that are online
1221 const int64_t now = OSUtils::now();
1222 std::lock_guard<std::mutex> l(_memberStatus_l);
1223 for(auto i=_memberStatus.begin();i!=_memberStatus.end();++i) {
1224 if ((i->first.networkId == networkId)&&(i->second.online(now))&&(i->second.lastRequestMetaData))
1225 request(networkId,InetAddress(),0,i->second.identity,i->second.lastRequestMetaData);
1226 }
1227 }
1228
onNetworkMemberUpdate(const void * db,uint64_t networkId,uint64_t memberId,const nlohmann::json & member)1229 void EmbeddedNetworkController::onNetworkMemberUpdate(const void *db,uint64_t networkId,uint64_t memberId,const nlohmann::json &member)
1230 {
1231 // Push update to member if online
1232 try {
1233 std::lock_guard<std::mutex> l(_memberStatus_l);
1234 _MemberStatus &ms = _memberStatus[_MemberStatusKey(networkId,memberId)];
1235 if ((ms.online(OSUtils::now()))&&(ms.lastRequestMetaData))
1236 request(networkId,InetAddress(),0,ms.identity,ms.lastRequestMetaData);
1237 } catch ( ... ) {}
1238 }
1239
onNetworkMemberDeauthorize(const void * db,uint64_t networkId,uint64_t memberId)1240 void EmbeddedNetworkController::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId)
1241 {
1242 const int64_t now = OSUtils::now();
1243 Revocation rev((uint32_t)_node->prng(),networkId,0,now,ZT_REVOCATION_FLAG_FAST_PROPAGATE,Address(memberId),Revocation::CREDENTIAL_TYPE_COM);
1244 rev.sign(_signingId);
1245 {
1246 std::lock_guard<std::mutex> l(_memberStatus_l);
1247 for(auto i=_memberStatus.begin();i!=_memberStatus.end();++i) {
1248 if ((i->first.networkId == networkId)&&(i->second.online(now)))
1249 _node->ncSendRevocation(Address(i->first.nodeId),rev);
1250 }
1251 }
1252 }
1253
_request(uint64_t nwid,const InetAddress & fromAddr,uint64_t requestPacketId,const Identity & identity,const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> & metaData)1254 void EmbeddedNetworkController::_request(
1255 uint64_t nwid,
1256 const InetAddress &fromAddr,
1257 uint64_t requestPacketId,
1258 const Identity &identity,
1259 const Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> &metaData)
1260 {
1261 char nwids[24];
1262 DB::NetworkSummaryInfo ns;
1263 json network,member;
1264
1265 if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender))
1266 return;
1267
1268 const int64_t now = OSUtils::now();
1269
1270 if (requestPacketId) {
1271 std::lock_guard<std::mutex> l(_memberStatus_l);
1272 _MemberStatus &ms = _memberStatus[_MemberStatusKey(nwid,identity.address().toInt())];
1273 if ((now - ms.lastRequestTime) <= ZT_NETCONF_MIN_REQUEST_PERIOD)
1274 return;
1275 ms.lastRequestTime = now;
1276 }
1277
1278 _db.nodeIsOnline(nwid,identity.address().toInt(),fromAddr);
1279
1280 Utils::hex(nwid,nwids);
1281 _db.get(nwid,network,identity.address().toInt(),member,ns);
1282 if ((!network.is_object())||(network.empty())) {
1283 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND, nullptr, 0);
1284 return;
1285 }
1286 const bool newMember = ((!member.is_object())||(member.empty()));
1287 DB::initMember(member);
1288
1289 {
1290 const std::string haveIdStr(OSUtils::jsonString(member["identity"],""));
1291 if (haveIdStr.length() > 0) {
1292 // If we already know this member's identity perform a full compare. This prevents
1293 // a "collision" from being able to auth onto our network in place of an already
1294 // known member.
1295 try {
1296 if (Identity(haveIdStr.c_str()) != identity) {
1297 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0);
1298 return;
1299 }
1300 } catch ( ... ) {
1301 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0);
1302 return;
1303 }
1304 } else {
1305 // If we do not yet know this member's identity, learn it.
1306 char idtmp[1024];
1307 member["identity"] = identity.toString(false,idtmp);
1308 }
1309 }
1310
1311 // These are always the same, but make sure they are set
1312 {
1313 char tmpid[128];
1314 const std::string addrs(identity.address().toString(tmpid));
1315 member["id"] = addrs;
1316 member["address"] = addrs;
1317 member["nwid"] = nwids;
1318 }
1319
1320 // Determine whether and how member is authorized
1321 bool authorized = false;
1322 bool autoAuthorized = false;
1323 json autoAuthCredentialType,autoAuthCredential;
1324 if (OSUtils::jsonBool(member["authorized"],false)) {
1325 authorized = true;
1326 } else if (!OSUtils::jsonBool(network["private"],true)) {
1327 authorized = true;
1328 autoAuthorized = true;
1329 autoAuthCredentialType = "public";
1330 } else {
1331 char presentedAuth[512];
1332 if (metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_AUTH,presentedAuth,sizeof(presentedAuth)) > 0) {
1333 presentedAuth[511] = (char)0; // sanity check
1334 if ((strlen(presentedAuth) > 6)&&(!strncmp(presentedAuth,"token:",6))) {
1335 const char *const presentedToken = presentedAuth + 6;
1336 json authTokens(network["authTokens"]);
1337 json &tokenExpires = authTokens[presentedToken];
1338 if (tokenExpires.is_number()) {
1339 if ((tokenExpires == 0)||(tokenExpires > now)) {
1340 authorized = true;
1341 autoAuthorized = true;
1342 autoAuthCredentialType = "token";
1343 autoAuthCredential = presentedToken;
1344 }
1345 }
1346 }
1347 }
1348 }
1349
1350 // If we auto-authorized, update member record
1351 if ((autoAuthorized)&&(authorized)) {
1352 member["authorized"] = true;
1353 member["lastAuthorizedTime"] = now;
1354 member["lastAuthorizedCredentialType"] = autoAuthCredentialType;
1355 member["lastAuthorizedCredential"] = autoAuthCredential;
1356 }
1357
1358 // Should we check SSO Stuff?
1359 // If network is configured with SSO, and the member is not marked exempt: yes
1360 // Otherwise no, we use standard auth logic.
1361 bool networkSSOEnabled = OSUtils::jsonBool(network["ssoEnabled"], false);
1362 bool memberSSOExempt = OSUtils::jsonBool(member["ssoExempt"], false);
1363 std::string authenticationURL;
1364 if (networkSSOEnabled && !memberSSOExempt) {
1365 authenticationURL = _db.getSSOAuthURL(member, _ssoRedirectURL);
1366 std::string memberId = member["id"];
1367 //fprintf(stderr, "ssoEnabled && !ssoExempt %s-%s\n", nwids, memberId.c_str());
1368 uint64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
1369 //fprintf(stderr, "authExpiryTime: %lld\n", authenticationExpiryTime);
1370 if (authenticationExpiryTime < now) {
1371 if (!authenticationURL.empty()) {
1372 _db.networkMemberSSOHasExpired(nwid, now);
1373 onNetworkMemberDeauthorize(&_db, nwid, identity.address().toInt());
1374
1375 Dictionary<3072> authInfo;
1376 authInfo.add("aU", authenticationURL.c_str());
1377 //fprintf(stderr, "sending auth URL: %s\n", authenticationURL.c_str());
1378
1379 DB::cleanMember(member);
1380 _db.save(member,true);
1381
1382 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes());
1383 return;
1384 }
1385 } else if (authorized) {
1386 _db.memberWillExpire(authenticationExpiryTime, nwid, identity.address().toInt());
1387 }
1388 }
1389
1390 if (authorized) {
1391 // Update version info and meta-data if authorized and if this is a genuine request
1392 if (requestPacketId) {
1393 const uint64_t vMajor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0);
1394 const uint64_t vMinor = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0);
1395 const uint64_t vRev = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0);
1396 const uint64_t vProto = metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,0);
1397
1398 member["vMajor"] = vMajor;
1399 member["vMinor"] = vMinor;
1400 member["vRev"] = vRev;
1401 member["vProto"] = vProto;
1402
1403 {
1404 std::lock_guard<std::mutex> l(_memberStatus_l);
1405 _MemberStatus &ms = _memberStatus[_MemberStatusKey(nwid,identity.address().toInt())];
1406
1407 ms.vMajor = (int)vMajor;
1408 ms.vMinor = (int)vMinor;
1409 ms.vRev = (int)vRev;
1410 ms.vProto = (int)vProto;
1411 ms.lastRequestMetaData = metaData;
1412 ms.identity = identity;
1413 }
1414 }
1415 } else {
1416
1417 // If they are not authorized, STOP!
1418 DB::cleanMember(member);
1419 _db.save(member,true);
1420 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_ACCESS_DENIED, nullptr, 0);
1421 return;
1422 }
1423
1424 // -------------------------------------------------------------------------
1425 // If we made it this far, they are authorized (and authenticated).
1426 // -------------------------------------------------------------------------
1427
1428 int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
1429 if (now > ns.mostRecentDeauthTime) {
1430 // If we recently de-authorized a member, shrink credential TTL/max delta to
1431 // be below the threshold required to exclude it. Cap this to a min/max to
1432 // prevent jitter or absurdly large values.
1433 const uint64_t deauthWindow = now - ns.mostRecentDeauthTime;
1434 if (deauthWindow < ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA) {
1435 credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA;
1436 } else if (deauthWindow < (ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA + 5000ULL)) {
1437 credentialtmd = deauthWindow - 5000ULL;
1438 }
1439 }
1440
1441 std::unique_ptr<NetworkConfig> nc(new NetworkConfig());
1442
1443 nc->networkId = nwid;
1444 nc->type = OSUtils::jsonBool(network["private"],true) ? ZT_NETWORK_TYPE_PRIVATE : ZT_NETWORK_TYPE_PUBLIC;
1445 nc->timestamp = now;
1446 nc->credentialTimeMaxDelta = credentialtmd;
1447 nc->revision = OSUtils::jsonInt(network["revision"],0ULL);
1448 nc->issuedTo = identity.address();
1449 if (OSUtils::jsonBool(network["enableBroadcast"],true)) nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST;
1450 Utils::scopy(nc->name,sizeof(nc->name),OSUtils::jsonString(network["name"],"").c_str());
1451 nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
1452 nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL);
1453
1454 nc->ssoEnabled = OSUtils::jsonBool(network["ssoEnabled"], false);
1455 nc->authenticationExpiryTime = OSUtils::jsonInt(member["authenticationExpiryTime"], 0LL);
1456 if (!authenticationURL.empty())
1457 Utils::scopy(nc->authenticationURL, sizeof(nc->authenticationURL), authenticationURL.c_str());
1458
1459 std::string rtt(OSUtils::jsonString(member["remoteTraceTarget"],""));
1460 if (rtt.length() == 10) {
1461 nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str()));
1462 nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(member["remoteTraceLevel"],0ULL);
1463 } else {
1464 rtt = OSUtils::jsonString(network["remoteTraceTarget"],"");
1465 if (rtt.length() == 10) {
1466 nc->remoteTraceTarget = Address(Utils::hexStrToU64(rtt.c_str()));
1467 } else {
1468 nc->remoteTraceTarget.zero();
1469 }
1470 nc->remoteTraceLevel = (Trace::Level)OSUtils::jsonInt(network["remoteTraceLevel"],0ULL);
1471 }
1472
1473 for(std::vector<Address>::const_iterator ab(ns.activeBridges.begin());ab!=ns.activeBridges.end();++ab)
1474 nc->addSpecialist(*ab,ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE);
1475
1476 json &v4AssignMode = network["v4AssignMode"];
1477 json &v6AssignMode = network["v6AssignMode"];
1478 json &ipAssignmentPools = network["ipAssignmentPools"];
1479 json &routes = network["routes"];
1480 json &rules = network["rules"];
1481 json &capabilities = network["capabilities"];
1482 json &tags = network["tags"];
1483 json &memberCapabilities = member["capabilities"];
1484 json &memberTags = member["tags"];
1485 json &dns = network["dns"];
1486
1487 //fprintf(stderr, "IP Assignment Pools for Network %s: %s\n", nwids, OSUtils::jsonDump(ipAssignmentPools, 2).c_str());
1488
1489 if (metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV,0) <= 0) {
1490 // Old versions with no rules engine support get an allow everything rule.
1491 // Since rules are enforced bidirectionally, newer versions *will* still
1492 // enforce rules on the inbound side.
1493 nc->ruleCount = 1;
1494 nc->rules[0].t = ZT_NETWORK_RULE_ACTION_ACCEPT;
1495 } else {
1496 if (rules.is_array()) {
1497 for(unsigned long i=0;i<rules.size();++i) {
1498 if (nc->ruleCount >= ZT_MAX_NETWORK_RULES)
1499 break;
1500 if (_parseRule(rules[i],nc->rules[nc->ruleCount]))
1501 ++nc->ruleCount;
1502 }
1503 }
1504
1505 std::map< uint64_t,json * > capsById;
1506 if (!memberCapabilities.is_array())
1507 memberCapabilities = json::array();
1508 if (capabilities.is_array()) {
1509 for(unsigned long i=0;i<capabilities.size();++i) {
1510 json &cap = capabilities[i];
1511 if (cap.is_object()) {
1512 const uint64_t id = OSUtils::jsonInt(cap["id"],0ULL) & 0xffffffffULL;
1513 capsById[id] = ∩
1514 if ((newMember)&&(OSUtils::jsonBool(cap["default"],false))) {
1515 bool have = false;
1516 for(unsigned long i=0;i<memberCapabilities.size();++i) {
1517 if (id == (OSUtils::jsonInt(memberCapabilities[i],0ULL) & 0xffffffffULL)) {
1518 have = true;
1519 break;
1520 }
1521 }
1522 if (!have)
1523 memberCapabilities.push_back(id);
1524 }
1525 }
1526 }
1527 }
1528 for(unsigned long i=0;i<memberCapabilities.size();++i) {
1529 const uint64_t capId = OSUtils::jsonInt(memberCapabilities[i],0ULL) & 0xffffffffULL;
1530 std::map< uint64_t,json * >::const_iterator ctmp = capsById.find(capId);
1531 if (ctmp != capsById.end()) {
1532 json *cap = ctmp->second;
1533 if ((cap)&&(cap->is_object())&&(!cap->empty())) {
1534 ZT_VirtualNetworkRule capr[ZT_MAX_CAPABILITY_RULES];
1535 unsigned int caprc = 0;
1536 json &caprj = (*cap)["rules"];
1537 if ((caprj.is_array())&&(!caprj.empty())) {
1538 for(unsigned long j=0;j<caprj.size();++j) {
1539 if (caprc >= ZT_MAX_CAPABILITY_RULES)
1540 break;
1541 if (_parseRule(caprj[j],capr[caprc]))
1542 ++caprc;
1543 }
1544 }
1545 nc->capabilities[nc->capabilityCount] = Capability((uint32_t)capId,nwid,now,1,capr,caprc);
1546 if (nc->capabilities[nc->capabilityCount].sign(_signingId,identity.address()))
1547 ++nc->capabilityCount;
1548 if (nc->capabilityCount >= ZT_MAX_NETWORK_CAPABILITIES)
1549 break;
1550 }
1551 }
1552 }
1553
1554 std::map< uint32_t,uint32_t > memberTagsById;
1555 if (memberTags.is_array()) {
1556 for(unsigned long i=0;i<memberTags.size();++i) {
1557 json &t = memberTags[i];
1558 if ((t.is_array())&&(t.size() == 2))
1559 memberTagsById[(uint32_t)(OSUtils::jsonInt(t[0],0ULL) & 0xffffffffULL)] = (uint32_t)(OSUtils::jsonInt(t[1],0ULL) & 0xffffffffULL);
1560 }
1561 }
1562 if (tags.is_array()) { // check network tags array for defaults that are not present in member tags
1563 for(unsigned long i=0;i<tags.size();++i) {
1564 json &t = tags[i];
1565 if (t.is_object()) {
1566 const uint32_t id = (uint32_t)(OSUtils::jsonInt(t["id"],0) & 0xffffffffULL);
1567 json &dfl = t["default"];
1568 if ((dfl.is_number())&&(memberTagsById.find(id) == memberTagsById.end())) {
1569 memberTagsById[id] = (uint32_t)(OSUtils::jsonInt(dfl,0) & 0xffffffffULL);
1570 json mt = json::array();
1571 mt.push_back(id);
1572 mt.push_back(dfl);
1573 memberTags.push_back(mt); // add default to member tags if not present
1574 }
1575 }
1576 }
1577 }
1578 for(std::map< uint32_t,uint32_t >::const_iterator t(memberTagsById.begin());t!=memberTagsById.end();++t) {
1579 if (nc->tagCount >= ZT_MAX_NETWORK_TAGS)
1580 break;
1581 nc->tags[nc->tagCount] = Tag(nwid,now,identity.address(),t->first,t->second);
1582 if (nc->tags[nc->tagCount].sign(_signingId))
1583 ++nc->tagCount;
1584 }
1585 }
1586
1587 if (routes.is_array()) {
1588 for(unsigned long i=0;i<routes.size();++i) {
1589 if (nc->routeCount >= ZT_MAX_NETWORK_ROUTES)
1590 break;
1591 json &route = routes[i];
1592 json &target = route["target"];
1593 json &via = route["via"];
1594 if (target.is_string()) {
1595 const InetAddress t(target.get<std::string>().c_str());
1596 InetAddress v;
1597 if (via.is_string()) v.fromString(via.get<std::string>().c_str());
1598 if ((t.ss_family == AF_INET)||(t.ss_family == AF_INET6)) {
1599 ZT_VirtualNetworkRoute *r = &(nc->routes[nc->routeCount]);
1600 *(reinterpret_cast<InetAddress *>(&(r->target))) = t;
1601 if (v.ss_family == t.ss_family)
1602 *(reinterpret_cast<InetAddress *>(&(r->via))) = v;
1603 ++nc->routeCount;
1604 }
1605 }
1606 }
1607 }
1608
1609 const bool noAutoAssignIps = OSUtils::jsonBool(member["noAutoAssignIps"],false);
1610
1611 if ((v6AssignMode.is_object())&&(!noAutoAssignIps)) {
1612 if ((OSUtils::jsonBool(v6AssignMode["rfc4193"],false))&&(nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
1613 nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv6rfc4193(nwid,identity.address().toInt());
1614 nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
1615 }
1616 if ((OSUtils::jsonBool(v6AssignMode["6plane"],false))&&(nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)) {
1617 nc->staticIps[nc->staticIpCount++] = InetAddress::makeIpv66plane(nwid,identity.address().toInt());
1618 nc->flags |= ZT_NETWORKCONFIG_FLAG_ENABLE_IPV6_NDP_EMULATION;
1619 }
1620 }
1621
1622 bool haveManagedIpv4AutoAssignment = false;
1623 bool haveManagedIpv6AutoAssignment = false; // "special" NDP-emulated address types do not count
1624 json ipAssignments = member["ipAssignments"]; // we want to make a copy
1625 if (ipAssignments.is_array()) {
1626 for(unsigned long i=0;i<ipAssignments.size();++i) {
1627 if (ipAssignments[i].is_string()) {
1628 const std::string ips = ipAssignments[i];
1629 InetAddress ip(ips.c_str());
1630
1631 int routedNetmaskBits = -1;
1632 for(unsigned int rk=0;rk<nc->routeCount;++rk) {
1633 if (reinterpret_cast<const InetAddress *>(&(nc->routes[rk].target))->containsAddress(ip)) {
1634 const int nb = (int)(reinterpret_cast<const InetAddress *>(&(nc->routes[rk].target))->netmaskBits());
1635 if (nb > routedNetmaskBits)
1636 routedNetmaskBits = nb;
1637 }
1638 }
1639
1640 if (routedNetmaskBits >= 0) {
1641 if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
1642 ip.setPort(routedNetmaskBits);
1643 nc->staticIps[nc->staticIpCount++] = ip;
1644 }
1645 if (ip.ss_family == AF_INET)
1646 haveManagedIpv4AutoAssignment = true;
1647 else if (ip.ss_family == AF_INET6)
1648 haveManagedIpv6AutoAssignment = true;
1649 }
1650 }
1651 }
1652 } else {
1653 ipAssignments = json::array();
1654 }
1655
1656 if ( (ipAssignmentPools.is_array()) && ((v6AssignMode.is_object())&&(OSUtils::jsonBool(v6AssignMode["zt"],false))) && (!haveManagedIpv6AutoAssignment) && (!noAutoAssignIps) ) {
1657 for(unsigned long p=0;((p<ipAssignmentPools.size())&&(!haveManagedIpv6AutoAssignment));++p) {
1658 json &pool = ipAssignmentPools[p];
1659 if (pool.is_object()) {
1660 InetAddress ipRangeStart(OSUtils::jsonString(pool["ipRangeStart"],"").c_str());
1661 InetAddress ipRangeEnd(OSUtils::jsonString(pool["ipRangeEnd"],"").c_str());
1662 if ( (ipRangeStart.ss_family == AF_INET6) && (ipRangeEnd.ss_family == AF_INET6) ) {
1663 uint64_t s[2],e[2],x[2],xx[2];
1664 memcpy(s,ipRangeStart.rawIpData(),16);
1665 memcpy(e,ipRangeEnd.rawIpData(),16);
1666 s[0] = Utils::ntoh(s[0]);
1667 s[1] = Utils::ntoh(s[1]);
1668 e[0] = Utils::ntoh(e[0]);
1669 e[1] = Utils::ntoh(e[1]);
1670 x[0] = s[0];
1671 x[1] = s[1];
1672
1673 for(unsigned int trialCount=0;trialCount<1000;++trialCount) {
1674 if ((trialCount == 0)&&(e[1] > s[1])&&((e[1] - s[1]) >= 0xffffffffffULL)) {
1675 // First see if we can just cram a ZeroTier ID into the higher 64 bits. If so do that.
1676 xx[0] = Utils::hton(x[0]);
1677 xx[1] = Utils::hton(x[1] + identity.address().toInt());
1678 } else {
1679 // Otherwise pick random addresses -- this technically doesn't explore the whole range if the lower 64 bit range is >= 1 but that won't matter since that would be huge anyway
1680 Utils::getSecureRandom((void *)xx,16);
1681 if ((e[0] > s[0]))
1682 xx[0] %= (e[0] - s[0]);
1683 else xx[0] = 0;
1684 if ((e[1] > s[1]))
1685 xx[1] %= (e[1] - s[1]);
1686 else xx[1] = 0;
1687 xx[0] = Utils::hton(x[0] + xx[0]);
1688 xx[1] = Utils::hton(x[1] + xx[1]);
1689 }
1690
1691 InetAddress ip6((const void *)xx,16,0);
1692
1693 // Check if this IP is within a local-to-Ethernet routed network
1694 int routedNetmaskBits = 0;
1695 for(unsigned int rk=0;rk<nc->routeCount;++rk) {
1696 if ( (!nc->routes[rk].via.ss_family) && (nc->routes[rk].target.ss_family == AF_INET6) && (reinterpret_cast<const InetAddress *>(&(nc->routes[rk].target))->containsAddress(ip6)) )
1697 routedNetmaskBits = reinterpret_cast<const InetAddress *>(&(nc->routes[rk].target))->netmaskBits();
1698 }
1699
1700 // If it's routed, then try to claim and assign it and if successful end loop
1701 if ( (routedNetmaskBits > 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip6)) ) {
1702 char tmpip[64];
1703 const std::string ipStr(ip6.toIpString(tmpip));
1704 if (std::find(ipAssignments.begin(),ipAssignments.end(),ipStr) == ipAssignments.end()) {
1705 ipAssignments.push_back(ipStr);
1706 member["ipAssignments"] = ipAssignments;
1707 ip6.setPort((unsigned int)routedNetmaskBits);
1708 if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES)
1709 nc->staticIps[nc->staticIpCount++] = ip6;
1710 haveManagedIpv6AutoAssignment = true;
1711 break;
1712 }
1713 }
1714 }
1715 }
1716 }
1717 }
1718 }
1719
1720 if ( (ipAssignmentPools.is_array()) && ((v4AssignMode.is_object())&&(OSUtils::jsonBool(v4AssignMode["zt"],false))) && (!haveManagedIpv4AutoAssignment) && (!noAutoAssignIps) ) {
1721 for(unsigned long p=0;((p<ipAssignmentPools.size())&&(!haveManagedIpv4AutoAssignment));++p) {
1722 json &pool = ipAssignmentPools[p];
1723 if (pool.is_object()) {
1724 InetAddress ipRangeStartIA(OSUtils::jsonString(pool["ipRangeStart"],"").c_str());
1725 InetAddress ipRangeEndIA(OSUtils::jsonString(pool["ipRangeEnd"],"").c_str());
1726 if ( (ipRangeStartIA.ss_family == AF_INET) && (ipRangeEndIA.ss_family == AF_INET) ) {
1727 uint32_t ipRangeStart = Utils::ntoh((uint32_t)(reinterpret_cast<struct sockaddr_in *>(&ipRangeStartIA)->sin_addr.s_addr));
1728 uint32_t ipRangeEnd = Utils::ntoh((uint32_t)(reinterpret_cast<struct sockaddr_in *>(&ipRangeEndIA)->sin_addr.s_addr));
1729
1730 if ((ipRangeEnd < ipRangeStart)||(ipRangeStart == 0))
1731 continue;
1732 uint32_t ipRangeLen = ipRangeEnd - ipRangeStart;
1733
1734 // Start with the LSB of the member's address
1735 uint32_t ipTrialCounter = (uint32_t)(identity.address().toInt() & 0xffffffff);
1736
1737 for(uint32_t k=ipRangeStart,trialCount=0;((k<=ipRangeEnd)&&(trialCount < 1000));++k,++trialCount) {
1738 uint32_t ip = (ipRangeLen > 0) ? (ipRangeStart + (ipTrialCounter % ipRangeLen)) : ipRangeStart;
1739 ++ipTrialCounter;
1740 if ((ip & 0x000000ff) == 0x000000ff) {
1741 continue; // don't allow addresses that end in .255
1742 }
1743
1744 // Check if this IP is within a local-to-Ethernet routed network
1745 int routedNetmaskBits = -1;
1746 for(unsigned int rk=0;rk<nc->routeCount;++rk) {
1747 if (nc->routes[rk].target.ss_family == AF_INET) {
1748 uint32_t targetIp = Utils::ntoh((uint32_t)(reinterpret_cast<const struct sockaddr_in *>(&(nc->routes[rk].target))->sin_addr.s_addr));
1749 int targetBits = Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(&(nc->routes[rk].target))->sin_port));
1750 if ((ip & (0xffffffff << (32 - targetBits))) == targetIp) {
1751 routedNetmaskBits = targetBits;
1752 break;
1753 }
1754 }
1755 }
1756
1757 // If it's routed, then try to claim and assign it and if successful end loop
1758 const InetAddress ip4(Utils::hton(ip),0);
1759 if ( (routedNetmaskBits > 0) && (!std::binary_search(ns.allocatedIps.begin(),ns.allocatedIps.end(),ip4)) ) {
1760 char tmpip[64];
1761 const std::string ipStr(ip4.toIpString(tmpip));
1762 if (std::find(ipAssignments.begin(),ipAssignments.end(),ipStr) == ipAssignments.end()) {
1763 ipAssignments.push_back(ipStr);
1764 member["ipAssignments"] = ipAssignments;
1765 if (nc->staticIpCount < ZT_MAX_ZT_ASSIGNED_ADDRESSES) {
1766 struct sockaddr_in *const v4ip = reinterpret_cast<struct sockaddr_in *>(&(nc->staticIps[nc->staticIpCount++]));
1767 v4ip->sin_family = AF_INET;
1768 v4ip->sin_port = Utils::hton((uint16_t)routedNetmaskBits);
1769 v4ip->sin_addr.s_addr = Utils::hton(ip);
1770 }
1771 haveManagedIpv4AutoAssignment = true;
1772 break;
1773 }
1774 }
1775 }
1776 }
1777 }
1778 }
1779 }
1780
1781 if(dns.is_object()) {
1782 std::string domain = OSUtils::jsonString(dns["domain"],"");
1783 memcpy(nc->dns.domain, domain.c_str(), domain.size());
1784 json &addrArray = dns["servers"];
1785 if (addrArray.is_array()) {
1786 for(unsigned int j = 0; j < addrArray.size() && j < ZT_MAX_DNS_SERVERS; ++j) {
1787 json &addr = addrArray[j];
1788 nc->dns.server_addr[j] = InetAddress(OSUtils::jsonString(addr,"").c_str());
1789 }
1790 }
1791 } else {
1792 dns = json::object();
1793 }
1794
1795 // Issue a certificate of ownership for all static IPs
1796 if (nc->staticIpCount) {
1797 nc->certificatesOfOwnership[0] = CertificateOfOwnership(nwid,now,identity.address(),1);
1798 for(unsigned int i=0;i<nc->staticIpCount;++i)
1799 nc->certificatesOfOwnership[0].addThing(nc->staticIps[i]);
1800 nc->certificatesOfOwnership[0].sign(_signingId);
1801 nc->certificateOfOwnershipCount = 1;
1802 }
1803
1804 CertificateOfMembership com(now,credentialtmd,nwid,identity);
1805 if (com.sign(_signingId)) {
1806 nc->com = com;
1807 } else {
1808 _sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR, nullptr, 0);
1809 return;
1810 }
1811
1812 DB::cleanMember(member);
1813 _db.save(member,true);
1814 _sender->ncSendConfig(nwid,requestPacketId,identity.address(),*(nc.get()),metaData.getUI(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,0) < 6);
1815 }
1816
_startThreads()1817 void EmbeddedNetworkController::_startThreads()
1818 {
1819 std::lock_guard<std::mutex> l(_threads_l);
1820 if (!_threads.empty())
1821 return;
1822 const long hwc = std::max((long)std::thread::hardware_concurrency(),(long)1);
1823 for(long t=0;t<hwc;++t) {
1824 _threads.emplace_back([this]() {
1825 for(;;) {
1826 _RQEntry *qe = (_RQEntry *)0;
1827 auto timedWaitResult = _queue.get(qe, 1000);
1828 if (timedWaitResult == BlockingQueue<_RQEntry *>::STOP) {
1829 break;
1830 } else if (timedWaitResult == BlockingQueue<_RQEntry *>::OK) {
1831 if (qe) {
1832 try {
1833 _request(qe->nwid,qe->fromAddr,qe->requestPacketId,qe->identity,qe->metaData);
1834 } catch (std::exception &e) {
1835 fprintf(stderr,"ERROR: exception in controller request handling thread: %s" ZT_EOL_S,e.what());
1836 } catch ( ... ) {
1837 fprintf(stderr,"ERROR: exception in controller request handling thread: unknown exception" ZT_EOL_S);
1838 }
1839 delete qe;
1840 }
1841 }
1842
1843 std::set< std::pair<uint64_t, uint64_t> > soon;
1844 std::set< std::pair<uint64_t, uint64_t> > expired;
1845 _db.membersExpiring(soon, expired);
1846
1847 for(auto s=soon.begin();s!=soon.end();++s) {
1848 Identity identity;
1849 Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastMetaData;
1850 {
1851 std::unique_lock<std::mutex> ll(_memberStatus_l);
1852 auto ms = _memberStatus.find(_MemberStatusKey(s->first, s->second));
1853 if (ms != _memberStatus.end()) {
1854 lastMetaData = ms->second.lastRequestMetaData;
1855 identity = ms->second.identity;
1856 }
1857 }
1858 if (identity) {
1859 request(s->first,InetAddress(),0,identity,lastMetaData);
1860 }
1861 }
1862
1863 for(auto e=expired.begin();e!=expired.end();++e) {
1864 onNetworkMemberDeauthorize(nullptr, e->first, e->second);
1865 }
1866 }
1867 });
1868 }
1869 }
1870
1871 } // namespace ZeroTier
1872