static uint8_t serverFirstIncoming(struct Message* msg, struct Interface* iface) { struct UDPInterfaceContext* uictx = (struct UDPInterfaceContext*) iface->receiverContext; struct Interface* udpDefault = UDPInterface_getDefaultInterface(uictx->udpContext); assert(udpDefault); UDPInterface_bindToCurrentEndpoint(udpDefault); struct User* u = CryptoAuth_getUser(iface); assert(u); // Add it to the switch, this will change the receiveMessage for this interface. struct Address addr; memset(&addr, 0, sizeof(struct Address)); SwitchCore_addInterface(iface, u->trust, &addr.networkAddress_be, uictx->context->switchCore); uint8_t* herKey = CryptoAuth_getHerPublicKey(iface); memcpy(addr.key, herKey, 32); uint8_t printedAddr[60]; Address_print(printedAddr, &addr); Log_info1(uictx->context->logger, "Node %s has connected to us.\n", printedAddr); // Prepare for the next connection. struct Interface* newUdpDefault = UDPInterface_getDefaultInterface(uictx->udpContext); struct Interface* newAuthedUdpDefault = CryptoAuth_wrapInterface(newUdpDefault, NULL, true, true, uictx->context->ca); newAuthedUdpDefault->receiveMessage = serverFirstIncoming; newAuthedUdpDefault->receiverContext = uictx; // Send the message on to the switch so the first message isn't lost. return iface->receiveMessage(msg, iface); }
static inline void sendMessages(struct Context* ctx, int count, int size, const char* type, bool authPackets) { printf("Test sending %d %d byte\t%s packets.\tpacket auth %s", count, size, type, ((authPackets) ? "enabled." : "disabled.")); ctx->cif2 = CryptoAuth_wrapInterface(&ctx->if2, NULL, false, authPackets, ctx->ca2); ctx->cif1 = CryptoAuth_wrapInterface(&ctx->if1, publicKey, false, authPackets, ctx->ca1); uint64_t startTime = Time_hrtime(); if (type != HELLO) { setupMessage(ctx, size); ctx->cif1->sendMessage(&ctx->message, ctx->cif1); if (type == TRAFFIC) { setupMessage(ctx, size); ctx->cif2->sendMessage(&ctx->message, ctx->cif2); } } for (int i = 0; i < count; i++) { setupMessage(ctx, size); if (type == KEY) { ctx->cif2->sendMessage(&ctx->message, ctx->cif2); } else { ctx->cif1->sendMessage(&ctx->message, ctx->cif1); } } uint64_t endTimes = Time_hrtime(); uint64_t time = (endTimes - startTime) / 1000000; uint64_t kbSent = (size * count * 8) / 1024; // same as kbSent / (time / 1024) (converting time to seconds) uint64_t kbps = (kbSent * 1024) / time; printf("\tFinished in %dms. %d Kb/s\n\n", (int)time, (int)kbps); }
static void configureUDP(Dict* config, struct Context* ctx) { String* bindStr = Dict_getString(config, BSTR("bind")); char* bindAddress = bindStr ? bindStr->bytes : NULL; struct UDPInterface* udpContext = UDPInterface_new(ctx->base, bindAddress, ctx->allocator, ctx->eHandler, ctx->logger); if (bindStr) { struct Interface* udpDefault = UDPInterface_getDefaultInterface(udpContext); struct Interface* authedDef = CryptoAuth_wrapInterface(udpDefault, NULL, true, true, ctx->ca); struct UDPInterfaceContext* uictx = ctx->allocator->malloc(sizeof(struct UDPInterfaceContext), ctx->allocator); uictx->context = ctx; uictx->udpContext = udpContext; authedDef->receiveMessage = serverFirstIncoming; authedDef->receiverContext = uictx; } Dict* connectTo = Dict_getDict(config, BSTR("connectTo")); if (connectTo) { struct Dict_Entry* entry = *connectTo; while (entry != NULL) { String* key = (String*) entry->key; if (entry->val->type != Object_DICT) { fprintf(stderr, "interfaces.UDPInterface.connectTo: entry %s is not a dictionary type.\n", key->bytes); abort(); } Dict* value = entry->val->as.dictionary; udpConnectTo(key, value, udpContext, ctx); entry = entry->next; } } }
static void udpConnectTo(String* connectToAddress, Dict* config, struct UDPInterface* udpContext, struct Context* ctx) { String* password = Dict_getString(config, BSTR("password")); int64_t* authType = Dict_getInt(config, BSTR("authType")); String* publicKey = Dict_getString(config, BSTR("publicKey")); int64_t* trust = Dict_getInt(config, BSTR("trust")); #define FAIL_IF_NULL(cannotBeNull, fieldName) \ if (!cannotBeNull) { \ fprintf(stderr, \ "interfaces.UDPInterface['%s']." fieldName " is not set, " \ "this field is mandatory.\n", \ connectToAddress->bytes); \ exit(-1); \ } FAIL_IF_NULL(password, "password") FAIL_IF_NULL(authType, "authType") FAIL_IF_NULL(publicKey, "publicKey") FAIL_IF_NULL(trust, "trust") #undef FAIL_IF_NULL #define CHECK_RANGE(number, min, max) \ if (number < min || number > max) { \ fprintf(stderr, \ "interfaces.UDPInterface['%s'].number must be between min and max\n", \ connectToAddress->bytes); \ exit(-1); \ } CHECK_RANGE(*authType, 1, 255) CHECK_RANGE(*trust, 0, INT64_MAX) #undef CHECK_RANGE uint8_t pkBytes[32]; if (publicKey->len < 52 || Base32_decode(pkBytes, 32, (uint8_t*)publicKey->bytes, 52) != 32) { fprintf(stderr, "interfaces.UDPInterface['%s'].publicKey could not be parsed.\n", connectToAddress->bytes); exit(-1); } uint8_t addressBytes[16]; AddressCalc_addressForPublicKey(addressBytes, pkBytes); if (addressBytes[0] != 0xFC) { fprintf(stderr, "interfaces.UDPInterface['%s'].publicKey\n( %s )\nis not in FC00/8 range, " "it was probably mistranscribed.\n", connectToAddress->bytes, publicKey->bytes); exit(-1); } struct Interface* udp = UDPInterface_addEndpoint(udpContext, connectToAddress->bytes, ctx->eHandler); struct Interface* authedUdp = CryptoAuth_wrapInterface(udp, pkBytes, false, true, ctx->ca); CryptoAuth_setAuth(password, *authType, authedUdp); uint64_t switchAddr_be; SwitchCore_addInterface(authedUdp, *trust, &switchAddr_be, ctx->switchCore); struct Address addr; memset(&addr, 0, sizeof(struct Address)); memcpy(addr.key, pkBytes, 32); addr.networkAddress_be = switchAddr_be; RouterModule_addNode(&addr, ctx->routerModule); }
static int reconnectionNewEndpointTest(struct InterfaceController* ifController, uint8_t* pk, struct Message** fromSwitchPtr, struct Allocator* alloc, struct EventBase* eventBase, struct Log* logger, struct Interface* routerIf, struct Random* rand) { struct Message* message; struct Interface iface = { .sendMessage = messageFromInterface, .senderContext = &message, .allocator = alloc }; uint8_t* buffer = Allocator_malloc(alloc, 512); struct Message* outgoing = &(struct Message) { .length = 0, .padding = 512, .bytes = buffer + 512 }; struct CryptoAuth* externalCa = CryptoAuth_new(alloc, NULL, eventBase, logger, rand); struct Interface* wrapped = CryptoAuth_wrapInterface(&iface, pk, NULL, false, "", externalCa); CryptoAuth_setAuth(String_CONST("passwd"), 1, wrapped); struct Interface icIface = { .allocator = alloc, .sendMessage = messageFromInterface, .senderContext = &message }; InterfaceController_registerPeer(ifController, NULL, NULL, true, false, &icIface); uint8_t hexBuffer[1025]; for (int i = 0; i < 4; i++) { outgoing->length = 0; outgoing->padding = 512; outgoing->bytes = buffer + 512; Message_shift(outgoing, 12, NULL); Bits_memcpyConst(outgoing->bytes, "hello world", 12); Message_shift(outgoing, SwitchHeader_SIZE, NULL); Bits_memcpyConst(outgoing->bytes, (&(struct SwitchHeader) { .label_be = Endian_hostToBigEndian64(1), .lowBits_be = 0 }), SwitchHeader_SIZE); wrapped->sendMessage(outgoing, wrapped); *fromSwitchPtr = NULL; icIface.receiveMessage(outgoing, &icIface); message = *fromSwitchPtr; Assert_true(message); Assert_true(message->length == 24); Hex_encode(hexBuffer, 1025, message->bytes, message->length); printf("%s\n", hexBuffer); // Need to bounce the packets back when connecting after the first try. // This is needed to establish the CryptoAuth session and make the InterfaceController // merge the endpoints. if (i > 0) { // Reverse the bits to reverse the path: uint64_t path; Bits_memcpyConst(&path, message->bytes, 8); path = Bits_bitReverse64(path); Bits_memcpyConst(message->bytes, &path, 8); printf("sending back response.\n"); routerIf->receiveMessage(message, routerIf); printf("forwarding response to external cryptoAuth.\n"); iface.receiveMessage(message, &iface); printf("forwarded.\n"); } else { printf("not responding because we don't want to establish a connection yet.\n"); } } // check everything except the label Assert_true(!CString_strcmp((char*)hexBuffer+16, "0000000068656c6c6f20776f726c6400")); // check label: make sure the interface has been switched back into position 0. uint64_t label_be; Hex_decode((uint8_t*) &label_be, 8, hexBuffer, 16); uint64_t rev_label = Bits_bitReverse64(Endian_bigEndianToHost64(label_be)); // check label is decoded to 0 Assert_true(0 == NumberCompress_getDecompressed(rev_label, NumberCompress_bitsUsedForLabel(rev_label))); // check no other bits are set uint64_t out = NumberCompress_getCompressed(0, NumberCompress_bitsUsedForLabel(rev_label)); Assert_true(rev_label == out); return 0; }
int InterfaceController_registerPeer(struct InterfaceController* ifController, uint8_t herPublicKey[32], String* password, bool requireAuth, bool isIncomingConnection, struct Interface* externalInterface) { // This function is overridden by some tests... if (ifController->registerPeer) { return ifController->registerPeer(ifController, herPublicKey, password, requireAuth, isIncomingConnection, externalInterface); } struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifController); if (Map_OfIFCPeerByExernalIf_indexForKey(&externalInterface, &ic->peerMap) > -1) { return 0; } Log_debug(ic->logger, "registerPeer [%p] total [%u]", (void*)externalInterface, ic->peerMap.count); uint8_t ip6[16]; if (herPublicKey) { AddressCalc_addressForPublicKey(ip6, herPublicKey); if (!AddressCalc_validAddress(ip6)) { return InterfaceController_registerPeer_BAD_KEY; } if (!Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) { // can't link with yourself, wiseguy return InterfaceController_registerPeer_BAD_KEY; } } else { Assert_true(requireAuth); } struct Allocator* epAllocator = externalInterface->allocator; struct InterfaceController_Peer* ep = Allocator_calloc(epAllocator, sizeof(struct InterfaceController_Peer), 1); ep->bytesOut = 0; ep->bytesIn = 0; ep->external = externalInterface; int setIndex = Map_OfIFCPeerByExernalIf_put(&externalInterface, &ep, &ic->peerMap); ep->handle = ic->peerMap.handles[setIndex]; Identity_set(ep); Allocator_onFree(epAllocator, closeInterface, ep); // If the other end need needs to supply a valid password to connect // we will set the connection state to UNAUTHENTICATED so that if the // packet is invalid, the connection will be dropped right away. if (requireAuth) { ep->state = InterfaceController_PeerState_UNAUTHENTICATED; } ep->cryptoAuthIf = CryptoAuth_wrapInterface(externalInterface, herPublicKey, NULL, requireAuth, "outer", ic->ca); ep->cryptoAuthIf->receiveMessage = receivedAfterCryptoAuth; ep->cryptoAuthIf->receiverContext = ep; // Always use authType 1 until something else comes along, then we'll have to refactor. if (password) { CryptoAuth_setAuth(password, 1, ep->cryptoAuthIf); } ep->isIncomingConnection = isIncomingConnection; Bits_memcpyConst(&ep->switchIf, (&(struct Interface) { .sendMessage = sendFromSwitch, // ifcontrollerForPeer uses this. // sendFromSwitch relies on the fact that the // switchIf is the same memory location as the Peer. .senderContext = ic, .allocator = epAllocator }), sizeof(struct Interface));
printf("\nSetting up:\n"); struct Allocator* allocator = MallocAllocator_new(1048576); textBuff = Allocator_malloc(allocator, BUFFER_SIZE); struct Writer* logwriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logwriter, allocator); struct Random* rand = Random_new(allocator, logger, NULL); struct EventBase* base = EventBase_new(allocator); ca1 = CryptoAuth_new(allocator, NULL, base, logger, rand); if1 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf2, .receiveMessage = recvMessageOnIf2, .allocator = allocator })); cif1 = CryptoAuth_wrapInterface(if1, publicKey, false, false, ca1); cif1->receiveMessage = recvMessageOnIf1; ca2 = CryptoAuth_new(allocator, privateKey, base, logger, rand); if (password) { String passStr = {.bytes=(char*)password,.len=strlen((char*)password)}; CryptoAuth_setAuth(&passStr, 1, cif1); CryptoAuth_addUser(&passStr, 1, userObj, ca2); } if2 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf1, .allocator = allocator })); cif2 = CryptoAuth_wrapInterface(if2, NULL, false, authenticatePackets, ca2); cif2->receiveMessage = recvMessageOnIf2;
struct SessionManager* sm) { int ifaceIndex = Map_OfSessionsByIp6_indexForKey((struct Ip6*)lookupKey, &sm->ifaceMap); if (ifaceIndex == -1) { // Make sure cleanup() doesn't get behind. cleanup(sm); struct Allocator* ifAllocator = Allocator_child(sm->allocator); struct Interface* outsideIf = ifAllocator->clone(sizeof(struct Interface), ifAllocator, &(struct Interface) { .sendMessage = sm->encryptedOutgoing, .senderContext = sm->interfaceContext, .allocator = ifAllocator }); struct Interface* insideIf = CryptoAuth_wrapInterface(outsideIf, cryptoKey, false, true, sm->cryptoAuth); insideIf->receiveMessage = sm->decryptedIncoming; insideIf->receiverContext = sm->interfaceContext; struct SessionManager_Session s = { .lastMessageTime = Time_currentTimeSeconds(sm->eventBase), // Create a trick interface which pretends to be on both sides of the crypto. .iface = { .sendMessage = insideIf->sendMessage, .senderContext = insideIf->senderContext, .receiveMessage = outsideIf->receiveMessage, .receiverContext = outsideIf->receiverContext, .allocator = ifAllocator } };
printf("\nSetting up:\n"); struct Allocator* allocator = MallocAllocator_new(1048576); textBuff = Allocator_malloc(allocator, BUFFER_SIZE); struct Writer* logwriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logwriter, allocator); struct Random* rand = Random_new(allocator, logger, NULL); struct EventBase* base = EventBase_new(allocator); ca1 = CryptoAuth_new(allocator, NULL, base, logger, rand); if1 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf2, .receiveMessage = recvMessageOnIf2, .allocator = allocator })); cif1 = CryptoAuth_wrapInterface(if1, publicKey, NULL, false, "cif1", ca1); cif1->receiveMessage = recvMessageOnIf1; ca2 = CryptoAuth_new(allocator, privateKey, base, logger, rand); if (password) { String passStr = {.bytes=(char*)password,.len=strlen((char*)password)}; CryptoAuth_setAuth(&passStr, 1, cif1); CryptoAuth_addUser(&passStr, 1, String_new(userObj, allocator), ca2); } if2 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf1, .allocator = allocator })); cif2 = CryptoAuth_wrapInterface(if2, NULL, NULL, false, "cif2", ca2); cif2->receiveMessage = recvMessageOnIf2;
static int registerPeer(struct InterfaceController* ifController, uint8_t herPublicKey[32], String* password, bool requireAuth, bool transient, struct Interface* externalInterface) { struct Context* ic = Identity_cast((struct Context*) ifController); Log_debug(ic->logger, "registerPeer [%p] total [%u]", (void*)externalInterface, ic->peerMap.count); if (Map_OfIFCPeerByExernalIf_indexForKey(&externalInterface, &ic->peerMap) > -1) { Log_debug(ic->logger, "Skipping registerPeer [%p] because peer is already registered", (void*)externalInterface); return 0; } uint8_t ip6[16]; if (herPublicKey) { AddressCalc_addressForPublicKey(ip6, herPublicKey); if (!AddressCalc_validAddress(ip6)) { return InterfaceController_registerPeer_BAD_KEY; } } struct Allocator* epAllocator = externalInterface->allocator; struct IFCPeer* ep = Allocator_calloc(epAllocator, sizeof(struct IFCPeer), 1); ep->external = externalInterface; int setIndex = Map_OfIFCPeerByExernalIf_put(&externalInterface, &ep, &ic->peerMap); ep->handle = ic->peerMap.handles[setIndex]; Identity_set(ep); Allocator_onFree(epAllocator, closeInterface, ep); // If the other end need not supply a valid password to connect // we will set the connection state to HANDSHAKE because we don't // want the connection to be trashed after the first invalid packet. if (!requireAuth) { ep->state = InterfaceController_PeerState_HANDSHAKE; } ep->cryptoAuthIf = CryptoAuth_wrapInterface(externalInterface, herPublicKey, requireAuth, true, ic->ca); ep->cryptoAuthIf->receiveMessage = receivedAfterCryptoAuth; ep->cryptoAuthIf->receiverContext = ep; // Always use authType 1 until something else comes along, then we'll have to refactor. if (password) { CryptoAuth_setAuth(password, 1, ep->cryptoAuthIf); } ep->transient = transient; Bits_memcpyConst(&ep->switchIf, (&(struct Interface) { .sendMessage = sendFromSwitch, // ifcontrollerForPeer uses this. // sendFromSwitch relies on the fact that the // switchIf is the same memory location as the Peer. .senderContext = ic, .allocator = epAllocator }), sizeof(struct Interface));
.allocator = ifAlloc }, }, .sm = sm })); Identity_set(ss); ss->pub.timeOfCreation = Time_currentTimeMilliseconds(sm->eventBase); // const hack Bits_memcpyConst((void*)&ss->pub.external.senderContext, &ss, sizeof(char*)); Bits_memcpyConst(ss->pub.ip6, lookupKey, 16); ss->pub.internal = CryptoAuth_wrapInterface(&ss->pub.external, cryptoKey, lookupKey, false, "inner", sm->cryptoAuth); ss->pub.internal->receiveMessage = receiveMessage; ss->pub.internal->receiverContext = ss; ifaceIndex = Map_OfSessionsByIp6_put((struct Ip6*)lookupKey, &ss, &sm->ifaceMap); ss->pub.receiveHandle_be = Endian_hostToBigEndian32(sm->ifaceMap.handles[ifaceIndex] + sm->first); } else { uint8_t* herPubKey = CryptoAuth_getHerPublicKey(sm->ifaceMap.values[ifaceIndex]->pub.internal); if (Bits_isZero(herPubKey, 32) && cryptoKey) {