Esempio n. 1
0
int main()
{
    printInfo();

    volatile uint64_t b =  0x0123456789abcdef;
    volatile uint64_t sb = 0xefcdab8967452301;

    volatile uint32_t a =  0x01234567;
    volatile uint32_t sa = 0x67452301;

    volatile uint16_t c =  0xcabe;
    volatile uint16_t sc = 0xbeca;

    if (!Endian_isBigEndian()) {
        Assert_true(c == Endian_bigEndianToHost16(sc));
        Assert_true(c == Endian_hostToBigEndian16(sc));
        Assert_true(c == Endian_hostToLittleEndian16(c));
        Assert_true(c == Endian_littleEndianToHost16(c));

        Assert_true(a == Endian_bigEndianToHost32(sa));
        Assert_true(a == Endian_hostToBigEndian32(sa));
        Assert_true(a == Endian_hostToLittleEndian32(a));
        Assert_true(a == Endian_littleEndianToHost32(a));

        Assert_true(b == Endian_bigEndianToHost64(sb));
        Assert_true(b == Endian_hostToBigEndian64(sb));
        Assert_true(b == Endian_hostToLittleEndian64(b));
        Assert_true(b == Endian_littleEndianToHost64(b));
    } else {
        Assert_true(c == Endian_bigEndianToHost16(c));
        Assert_true(c == Endian_hostToBigEndian16(c));
        Assert_true(c == Endian_hostToLittleEndian16(sc));
        Assert_true(c == Endian_littleEndianToHost16(sc));

        Assert_true(a == Endian_bigEndianToHost32(a));
        Assert_true(a == Endian_hostToBigEndian32(a));
        Assert_true(a == Endian_hostToLittleEndian32(sa));
        Assert_true(a == Endian_littleEndianToHost32(sa));

        Assert_true(b == Endian_bigEndianToHost64(b));
        Assert_true(b == Endian_hostToBigEndian64(b));
        Assert_true(b == Endian_hostToLittleEndian64(sb));
        Assert_true(b == Endian_littleEndianToHost64(sb));
    }

    Assert_true(b == Endian_byteSwap64(sb));
    Assert_true(a == Endian_byteSwap32(sa));
    Assert_true(c == Endian_byteSwap16(sc));
    return 0;
}
Esempio n. 2
0
/**
 * When we send a message it goes into the CryptoAuth.
 * for the content level crypto then it goes to outgoingFromCryptoAuth then comes here.
 * Message is aligned on the beginning of the crypto header, ip6 header must be reapplied.
 */
static inline uint8_t outgoingFromMe(struct Message* message, struct Ducttape* context)
{
    // Need to set the length field to take into account
    // the crypto headers which are hidden under the ipv6 packet.
    context->ip6Header->payloadLength_be = Endian_hostToBigEndian16(message->length);

    Message_shift(message, Headers_IP6Header_SIZE);

    // If this message is addressed to us, it means the cryptoauth kicked back a response
    // message when we asked it to decrypt a message for us and the ipv6 addresses need to
    // be flipped to send it back to the other node.
    if (isForMe(message, context)) {
        struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) message->bytes;
        Assert_true(context->ip6Header == ip6);
        Bits_memcpyConst(ip6->destinationAddr, ip6->sourceAddr, 16);
        Bits_memcpyConst(ip6->sourceAddr, &context->myAddr.ip6.bytes, 16);
        // It came from me...
        context->routerAddress = context->myAddr.ip6.bytes;
    } else {
        Bits_memcpyConst(message->bytes, context->ip6Header, Headers_IP6Header_SIZE);
    }

    // Forward this call to core() which will check it's validity
    // and since it's not to us, forward it to the correct node.
    return core(message, context);
}
Esempio n. 3
0
/**
 * When we send a message it goes into the CryptoAuth.
 * for the content level crypto then it goes to outgoingFromCryptoAuth then comes here.
 * Message is aligned on the beginning of the CryptoAuth header.
 */
static inline uint8_t outgoingFromMe(struct Message* message,
                                     struct Ducttape_MessageHeader* dtHeader,
                                     struct SessionManager_Session* session,
                                     struct Ducttape_pvt* context)
{
    // Move back to the beginning of the ip6Header behind the crypto.
    Message_shift(message, Headers_IP6Header_SIZE);
    struct Headers_IP6Header* header = (struct Headers_IP6Header*) message->bytes;

    if (!Bits_memcmp(header->destinationAddr, context->myAddr.ip6.bytes, 16)) {
        // This happens when an empty connect-to-me packet is sent to us,
        // CryptoAuth is called with a message and instead of returning a decrypted message
        // to send to the TUN, it outputs a message to send back down the wire but the
        // header is still the same.
        // these messages are always empty so we just flip the source and destination around
        // and send it back.
        Bits_memcpyConst(header->destinationAddr, header->sourceAddr, 16);
        Bits_memcpyConst(header->sourceAddr, context->myAddr.ip6.bytes, 16);

    } else {
        // sanity check.
        Assert_true(!Bits_memcmp(header->sourceAddr, context->myAddr.ip6.bytes, 16));
    }

    // Need to set the length field to take into account
    // the crypto headers which are hidden under the ipv6 packet.
    header->payloadLength_be =
        Endian_hostToBigEndian16(message->length - Headers_IP6Header_SIZE);


    // Forward this call to core() which will check its validity
    // and since it's not to us, forward it to the correct node.
    return core(message, dtHeader, session, context);
}
Esempio n. 4
0
void TestFramework_craftIPHeader(struct Message* msg, uint8_t srcAddr[16], uint8_t destAddr[16])
{
    Message_shift(msg, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes;

    ip->versionClassAndFlowLabel = 0;
    ip->flowLabelLow_be = 0;
    ip->payloadLength_be = Endian_hostToBigEndian16(msg->length - Headers_IP6Header_SIZE);
    ip->nextHeader = 123; // made up number
    ip->hopLimit = 255;
    Bits_memcpy(ip->sourceAddr, srcAddr, 16);
    Bits_memcpy(ip->destinationAddr, destAddr, 16);
    Headers_setIpVersion(ip);
}
Esempio n. 5
0
static uint8_t sendMessage(struct Message* message, struct Interface* ethIf)
{
    struct ETHInterface* context = Identity_cast((struct ETHInterface*) ethIf);

    struct sockaddr_ll addr;
    Bits_memcpyConst(&addr, &context->addrBase, sizeof(struct sockaddr_ll));
    Message_pop(message, addr.sll_addr, 8);

    /* Cut down on the noise
    uint8_t buff[sizeof(addr) * 2 + 1] = {0};
    Hex_encode(buff, sizeof(buff), (uint8_t*)&addr, sizeof(addr));
    Log_debug(context->logger, "Sending ethernet frame to [%s]", buff);
    */

    // Check if we will have to pad the message and pad if necessary.
    int pad = 0;
    for (int length = message->length; length+2 < MIN_PACKET_SIZE; length += 8) {
        pad++;
    }
    if (pad > 0) {
        int length = message->length;
        Message_shift(message, pad*8);
        Bits_memset(message->bytes, 0, pad*8);
        Bits_memmove(message->bytes, &message->bytes[pad*8], length);
    }
    Assert_true(pad < 8);
    uint16_t padAndId_be = Endian_hostToBigEndian16((context->id << 3) | pad);
    Message_push(message, &padAndId_be, 2);

    if (sendto(context->socket,
               message->bytes,
               message->length,
               0,
               (struct sockaddr*) &addr,
               sizeof(struct sockaddr_ll)) < 0)
    {
        switch (errno) {
            case EMSGSIZE:
                return Error_OVERSIZE_MESSAGE;

            case ENOBUFS:
            case EAGAIN:
                return Error_LINK_LIMIT_EXCEEDED;

            default:;
                Log_info(context->logger, "Got error sending to socket [%s]", strerror(errno));
        }
    }
    return 0;
}
int main()
{
    char* pingBenc = "d1:q4:ping4:txid4:abcde";
    struct Allocator* alloc = MallocAllocator_new(1<<22);
    struct TestFramework* tf = TestFramework_setUp("0123456789abcdefghijklmnopqrstuv", alloc, NULL);
    struct Ducttape_pvt* dt = Identity_cast((struct Ducttape_pvt*) tf->ducttape);

    struct Allocator* allocator = MallocAllocator_new(85000);
    uint16_t buffLen = sizeof(struct Ducttape_IncomingForMe) + 8 + strlen(pingBenc);
    uint8_t* buff = allocator->calloc(buffLen, 1, allocator);
    struct Headers_SwitchHeader* sh = (struct Headers_SwitchHeader*) buff;
    sh->label_be = Endian_hostToBigEndian64(4);
    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) &sh[1];

    uint8_t herPublicKey[32];
    Base32_decode(herPublicKey, 32,
                  (uint8_t*) "0z5tscp8td1sc6cv4htp7jbls79ltqxw9pbg190x0kbm1lguqtx0", 52);
    AddressCalc_addressForPublicKey(ip6->sourceAddr, herPublicKey);

    struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) &ip6[1];
    ip6->hopLimit = 0;
    ip6->nextHeader = 17;
    udp->sourceAndDestPorts = 0;
    udp->length_be = Endian_hostToBigEndian16(strlen(pingBenc));

    strncpy((char*)(udp + 1), pingBenc, strlen(pingBenc));

    dt->switchInterface.receiveMessage = catchResponse;
    dt->switchInterface.receiverContext = NULL;

    // bad checksum
    udp->checksum_be = 1;
    struct Message m = { .bytes = buff, .length = buffLen, .padding = 0 };
    Ducttape_injectIncomingForMe(&m, &dt->public, herPublicKey);
    Assert_always(!dt->switchInterface.receiverContext);

    // zero checksum
    udp->checksum_be = 0;
    struct Message m2 = { .bytes = buff, .length = buffLen, .padding = 0 };
    Ducttape_injectIncomingForMe(&m2, &dt->public, herPublicKey);
    Assert_always(dt->switchInterface.receiverContext);

    // good checksum
    udp->checksum_be =
        Checksum_udpIp6(ip6->sourceAddr, (uint8_t*) udp, strlen(pingBenc) + Headers_UDPHeader_SIZE);
    struct Message m3 = { .bytes = buff, .length = buffLen, .padding = 0 };
    Ducttape_injectIncomingForMe(&m3, &dt->public, herPublicKey);
    Assert_always(dt->switchInterface.receiverContext);
}
Esempio n. 7
0
static int handleOutgoing(struct DHTMessage* dmessage, void* vcontext)
{
    struct Ducttape_pvt* context = Identity_check((struct Ducttape_pvt*) vcontext);

    // Sending a message to yourself?
    // Short circuit because setting up a CA session with yourself causes problems.
    if (!Bits_memcmp(dmessage->address->key, context->myAddr.key, 32)) {
        struct Allocator* alloc = Allocator_child(context->alloc);
        Allocator_adopt(alloc, dmessage->binMessage->alloc);
        incomingDHT(dmessage->binMessage, dmessage->address, context);
        Allocator_free(alloc);
        return 0;
    }

    struct Message* msg = dmessage->binMessage;

    {
        Message_push(msg, (&(struct Headers_UDPHeader) {
            .srcPort_be = 0,
            .destPort_be = 0,
            .length_be = Endian_hostToBigEndian16(msg->length),
            .checksum_be = 0,
        }), Headers_UDPHeader_SIZE, NULL);
    }
Esempio n. 8
0
static int handleOutgoing(struct DHTMessage* dmessage,
                          void* vcontext)
{
    struct Ducttape* context = (struct Ducttape*) vcontext;

    struct Message message =
        { .length = dmessage->length, .bytes = (uint8_t*) dmessage->bytes, .padding = 512 };

    Message_shift(&message, Headers_UDPHeader_SIZE);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message.bytes;
    uh->sourceAndDestPorts = 0;
    uh->length_be = Endian_hostToBigEndian16(dmessage->length);
    uh->checksum_be = 0;

    uint16_t payloadLength = message.length;

    Message_shift(&message, Headers_IP6Header_SIZE);
    struct Headers_IP6Header* header = (struct Headers_IP6Header*) message.bytes;
    header->versionClassAndFlowLabel = 0;
    header->flowLabelLow_be = 0;
    header->nextHeader = 17;
    header->hopLimit = 0;
    header->payloadLength_be = Endian_hostToBigEndian16(payloadLength);

    Bits_memcpyConst(header->sourceAddr,
                     context->myAddr.ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

    Bits_memcpyConst(header->destinationAddr,
                     dmessage->address->ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

    context->ip6Header = header;
    context->switchHeader = NULL;

    sendToRouter(dmessage->address, &message, context);

    return 0;
}

// Aligned on the beginning of the content.
static inline bool isRouterTraffic(struct Message* message, struct Headers_IP6Header* ip6)
{
    if (ip6->nextHeader != 17 || ip6->hopLimit != 0) {
        return false;
    }

    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;
    return message->length >= Headers_UDPHeader_SIZE
        && uh->sourceAndDestPorts == 0
        && (int) Endian_bigEndianToHost16(uh->length_be) == message->length - Headers_UDPHeader_SIZE;
}

/**
 * Message which is for us, message is aligned on the beginning of the content.
 * this is called from core() which calls through an interfaceMap.
 */
static inline uint8_t incomingForMe(struct Message* message,
                                    struct Ducttape* context,
                                    uint8_t herPubKey[32])
{
    struct Address addr;
    AddressCalc_addressForPublicKey(addr.ip6.bytes, herPubKey);

    if (memcmp(addr.ip6.bytes, context->ip6Header->sourceAddr, 16)) {
        #ifdef Log_DEBUG
            uint8_t keyAddr[40];
            Address_printIp(keyAddr, &addr);
            Bits_memcpyConst(addr.ip6.bytes, context->ip6Header->sourceAddr, 16);
            uint8_t srcAddr[40];
            Address_printIp(srcAddr, &addr);
            Log_debug2(context->logger,
                       "Dropped packet because source address is not same as key.\n"
                       "    %s source addr\n"
                       "    %s hash of key\n",
                       srcAddr,
                       keyAddr);
        #endif
        return Error_INVALID;
    }

    if (message->length == 0) {
        #ifdef Log_WARN
            uint8_t keyAddr[40];
            uint8_t ipv6Hex[80];
            Address_printIp(keyAddr, &addr);
            Hex_encode(ipv6Hex, 80, (uint8_t*) context->ip6Header, 40);
            Log_warn2(context->logger,
                      "Got ipv6 packet from %s which has no content!\nIPv6 Header: [%s]",
                      keyAddr, ipv6Hex);
        #endif
        return Error_INVALID;
    }

    if (isRouterTraffic(message, context->ip6Header)) {
        // Shift off the UDP header.
        Message_shift(message, -Headers_UDPHeader_SIZE);
        addr.path = Endian_bigEndianToHost64(context->switchHeader->label_be);
        Bits_memcpyConst(addr.key, herPubKey, 32);
        return incomingDHT(message, &addr, context);
    }

    // RouterModule_addNode(&addr, context->routerModule);

    if (!context->routerIf) {
        Log_warn(context->logger,
                 "Dropping message because there is no router interface configured.\n");
        return Error_UNDELIVERABLE;
    }

    // Now write a message to the TUN device.
    // Need to move the ipv6 header forward up to the content because there's a crypto header
    // between the ipv6 header and the content which just got eaten.
    Message_shift(message, Headers_IP6Header_SIZE);
    uint16_t sizeDiff = message->bytes - (uint8_t*)context->ip6Header;
    if (sizeDiff) {
        context->ip6Header->payloadLength_be =
            Endian_hostToBigEndian16(
                Endian_bigEndianToHost16(context->ip6Header->payloadLength_be) - sizeDiff);
        memmove(message->bytes, context->ip6Header, Headers_IP6Header_SIZE);
    }
    context->routerIf->sendMessage(message, context->routerIf);
    return Error_NONE;
}

uint8_t Ducttape_injectIncomingForMe(struct Message* message,
                                     struct Ducttape* context,
                                     uint8_t herPublicKey[32])
{
    struct Headers_SwitchHeader sh;
    Bits_memcpyConst(&sh, message->bytes, Headers_SwitchHeader_SIZE);
    context->switchHeader = &sh;
    Message_shift(message, -Headers_SwitchHeader_SIZE);

    struct Headers_IP6Header ip6;
    Bits_memcpyConst(&ip6, message->bytes, Headers_IP6Header_SIZE);
    context->ip6Header = &ip6;
    Message_shift(message, -Headers_IP6Header_SIZE);

    return incomingForMe(message, context, herPublicKey);
}

/**
 * Send a message to another switch.
 * Switchheader will precede the message.
 */
static inline uint8_t sendToSwitch(struct Message* message,
                                   struct Headers_SwitchHeader* destinationSwitchHeader,
                                   struct Ducttape* context)
{
    Message_shift(message, Headers_SwitchHeader_SIZE);
    struct Headers_SwitchHeader* switchHeaderLocation =
        (struct Headers_SwitchHeader*) message->bytes;

    if (destinationSwitchHeader != switchHeaderLocation) {
        memmove(message->bytes, destinationSwitchHeader, Headers_SwitchHeader_SIZE);
    }

    return context->switchInterface.receiveMessage(message, &context->switchInterface);
}
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface);

    struct Sockaddr_storage ss;
    Message_pop(message, &ss, context->pub.addr->addrLen, NULL);
    struct Sockaddr* addr = &ss.addr;

    struct Headers_UDPHeader udp;
    udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.addr));
    udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr));
    udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE);
    udp.checksum_be = 0;
    Message_push(message, &udp, sizeof(struct Headers_UDPHeader), NULL);

    struct Headers_IP6Header ip = {
        .nextHeader = 17,
        .hopLimit = 255,
    };
    ip.payloadLength_be = Endian_hostToBigEndian16(message->length);
    Headers_setIpVersion(&ip);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.destinationAddr, addrPtr, 16);
    Assert_true(Sockaddr_getAddress(context->pub.addr, &addrPtr) == 16);
    Bits_memcpyConst(ip.sourceAddr, addrPtr, 16);

    uint16_t checksum = Checksum_udpIp6(ip.sourceAddr, message->bytes, message->length);
    ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum;

    Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL);

    return Interface_sendMessage(context->wrapped, message);
}

static uint8_t receiveMessage(struct Message* message, struct Interface* iface)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface->receiverContext);

    if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
        // runt
        return Error_NONE;
    }

    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;

    // udp
    if (ip->nextHeader != 17) {
        return Error_NONE;
    }

    struct Allocator* alloc = Allocator_child(message->alloc);
    struct Sockaddr* addr = Sockaddr_clone(context->pub.addr, alloc);
    uint8_t* addrPtr = NULL;
    Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16);
    Bits_memcpyConst(addrPtr, ip->sourceAddr, 16);

    struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]);
    Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be));

    if (Sockaddr_getPort(context->pub.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
        // not the right port
        return Error_NONE;
    }

    Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL);
    Message_push(message, addr, addr->addrLen, NULL);

    return Interface_receiveMessage(&context->pub.generic, message);
}

struct AddrInterface* PacketHeaderToUDPAddrInterface_new(struct Interface* toWrap,
                                                         struct Allocator* alloc,
                                                         struct Sockaddr* addr)
{
    struct PacketHeaderToUDPAddrInterface_pvt* context =
        Allocator_malloc(alloc, sizeof(struct PacketHeaderToUDPAddrInterface_pvt));

    Bits_memcpyConst(context, (&(struct PacketHeaderToUDPAddrInterface_pvt) {
        .pub = {
            .generic = {
                .sendMessage = sendMessage,
                .senderContext = context,
                .allocator = alloc
            }
        },
        .wrapped = toWrap
    }), sizeof(struct PacketHeaderToUDPAddrInterface_pvt));
Esempio n. 10
0
static int handleOutgoing(struct DHTMessage* dmessage,
                          void* vcontext)
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*) vcontext);

    struct Message message = {
        .length = dmessage->length,
        .bytes = (uint8_t*) dmessage->bytes,
        .padding = 512,
        .capacity = DHTMessage_MAX_SIZE
    };

    Message_shift(&message, Headers_UDPHeader_SIZE);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message.bytes;
    uh->sourceAndDestPorts = 0;
    uh->length_be = Endian_hostToBigEndian16(dmessage->length);
    uh->checksum_be = 0;

    uint16_t payloadLength = message.length;

    Message_shift(&message, Headers_IP6Header_SIZE);
    struct Headers_IP6Header* header = (struct Headers_IP6Header*) message.bytes;
    header->versionClassAndFlowLabel = 0;
    header->flowLabelLow_be = 0;
    header->nextHeader = 17;
    header->hopLimit = 0;
    header->payloadLength_be = Endian_hostToBigEndian16(payloadLength);

    Bits_memcpyConst(header->sourceAddr,
                     context->myAddr.ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

    Bits_memcpyConst(header->destinationAddr,
                     dmessage->address->ip6.bytes,
                     Address_SEARCH_TARGET_SIZE);

    #ifdef Log_DEBUG
        Assert_true(!((uintptr_t)dmessage->bytes % 4) || !"alignment fault");
    #endif

    uh->checksum_be =
        Checksum_udpIp6(header->sourceAddr, (uint8_t*) uh, message.length - Headers_IP6Header_SIZE);

    struct Ducttape_MessageHeader* dtHeader = getDtHeader(&message, true);
    dtHeader->ip6Header = header;
    dtHeader->switchLabel = dmessage->address->path;

    struct SessionManager_Session* session =
        SessionManager_getSession(dmessage->address->ip6.bytes,
                                  dmessage->address->key,
                                  context->sm);
    if (session->version == Version_DEFAULT_ASSUMPTION && dmessage->replyTo) {
        int64_t* verPtr = Dict_getInt(dmessage->replyTo->asDict, String_CONST("p"));
        session->version = (verPtr) ? *verPtr : Version_DEFAULT_ASSUMPTION;
    }
    if (session->version == Version_DEFAULT_ASSUMPTION) {
        struct Node* n = RouterModule_getNode(dmessage->address->path, context->routerModule);
        if (n) {
            n->version = session->version =
                (n->version > session->version) ? n->version : session->version;
        }
    }

    sendToRouter(&message, dtHeader, session, context);

    return 0;
}

// Aligned on the beginning of the content.
static inline bool isRouterTraffic(struct Message* message, struct Headers_IP6Header* ip6)
{
    if (ip6->nextHeader != 17 || ip6->hopLimit != 0) {
        return false;
    }

    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;
    return message->length >= Headers_UDPHeader_SIZE
        && uh->sourceAndDestPorts == 0
        && (int) Endian_bigEndianToHost16(uh->length_be) ==
            (message->length - Headers_UDPHeader_SIZE);
}

#define debugHandles(logger, session, message, ...) \
    do {                                                                               \
        uint8_t ip[40];                                                                \
        AddrTools_printIp(ip, session->ip6);                                           \
        Log_debug(logger, "ver[%u] send[%d] recv[%u] ip[%s] " message,                 \
                  session->version,                                                    \
                  Endian_hostToBigEndian32(session->sendHandle_be),                    \
                  Endian_hostToBigEndian32(session->receiveHandle_be),                 \
                  ip,                                                                  \
                  __VA_ARGS__);                                                        \
    } while (0)
//CHECKFILES_IGNORE expecting a ;

#define debugHandles0(logger, session, message) \
    debugHandles(logger, session, message "%s", "")

#define debugHandlesAndLabel(logger, session, label, message, ...) \
    do {                                                                               \
        uint8_t path[20];                                                              \
        AddrTools_printPath(path, label);                                              \
        debugHandles(logger, session, "path[%s] " message, path, __VA_ARGS__);         \
    } while (0)
//CHECKFILES_IGNORE expecting a ;

#define debugHandlesAndLabel0(logger, session, label, message) \
    debugHandlesAndLabel(logger, session, label, "%s", message)


/**
 * Message which is for us, message is aligned on the beginning of the content.
 * this is called from core() which calls through an interfaceMap.
 */
static inline uint8_t incomingForMe(struct Message* message,
                                    struct Ducttape_MessageHeader* dtHeader,
                                    struct SessionManager_Session* session,
                                    struct Ducttape_pvt* context,
                                    uint8_t herPublicKey[32])
{
    struct Address addr;
    Bits_memcpyConst(addr.ip6.bytes, session->ip6, 16);
    //AddressCalc_addressForPublicKey(addr.ip6.bytes, herPubKey);

    if (Bits_memcmp(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16)) {
        #ifdef Log_DEBUG
            uint8_t keyAddr[40];
            Address_printIp(keyAddr, &addr);
            Bits_memcpyConst(addr.ip6.bytes, dtHeader->ip6Header->sourceAddr, 16);
            uint8_t srcAddr[40];
            Address_printIp(srcAddr, &addr);
            Log_debug(context->logger,
                       "Dropped packet because source address is not same as key.\n"
                       "    %s source addr\n"
                       "    %s hash of key\n",
                       srcAddr,
                       keyAddr);
        #endif
        return Error_INVALID;
    }

    if (isRouterTraffic(message, dtHeader->ip6Header)) {
        // Check the checksum.
        struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;

        if (Checksum_udpIp6(dtHeader->ip6Header->sourceAddr, (uint8_t*)uh, message->length)) {
            #ifdef Log_DEBUG
                uint8_t keyAddr[40];
                Address_printIp(keyAddr, &addr);
                Log_debug(context->logger,
                          "Router packet with incorrect checksum, from [%s]", keyAddr);
            #endif
            return Error_INVALID;
        }

        // Shift off the UDP header.
        Message_shift(message, -Headers_UDPHeader_SIZE);
        addr.path = Endian_bigEndianToHost64(dtHeader->switchHeader->label_be);
        Bits_memcpyConst(addr.key, herPublicKey, 32);
        return incomingDHT(message, &addr, context);
    }

    if (!context->userIf) {
        Log_warn(context->logger,
                 "Dropping message because there is no router interface configured.\n");
        return Error_UNDELIVERABLE;
    }

    // prevent router advertizement schenanigans
    if (dtHeader->ip6Header->hopLimit == 255) {
        dtHeader->ip6Header->hopLimit--;
    }

    // Now write a message to the TUN device.
    // Need to move the ipv6 header forward up to the content because there's a crypto header
    // between the ipv6 header and the content which just got eaten.
    Message_shift(message, Headers_IP6Header_SIZE);
    uint16_t sizeDiff = message->bytes - (uint8_t*)dtHeader->ip6Header;
    if (sizeDiff) {
        dtHeader->ip6Header->payloadLength_be =
            Endian_hostToBigEndian16(
                Endian_bigEndianToHost16(dtHeader->ip6Header->payloadLength_be) - sizeDiff);
        Bits_memmoveConst(message->bytes, dtHeader->ip6Header, Headers_IP6Header_SIZE);
    }

    TUNMessageType_push(message, Ethernet_TYPE_IP6);

    context->userIf->sendMessage(message, context->userIf);
    return Error_NONE;
}

uint8_t Ducttape_injectIncomingForMe(struct Message* message,
                                     struct Ducttape* dt,
                                     uint8_t herPublicKey[32])
{
    struct Ducttape_pvt* context = Identity_cast((struct Ducttape_pvt*)dt);
    struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true);
    struct Headers_SwitchHeader sh;
    Bits_memcpyConst(&sh, message->bytes, Headers_SwitchHeader_SIZE);
    dtHeader->switchHeader = &sh;
    Message_shift(message, -Headers_SwitchHeader_SIZE);

    struct Headers_IP6Header ip6;
    Bits_memcpyConst(&ip6, message->bytes, Headers_IP6Header_SIZE);
    dtHeader->ip6Header = &ip6;
    Message_shift(message, -Headers_IP6Header_SIZE);

    struct SessionManager_Session s;
    AddressCalc_addressForPublicKey(s.ip6, herPublicKey);
    s.version = Version_CURRENT_PROTOCOL;

    return incomingForMe(message, dtHeader, &s, context, herPublicKey);
}

/**
 * Send a message to another switch.
 * Switchheader will precede the message.
 */
static inline uint8_t sendToSwitch(struct Message* message,
                                   struct Ducttape_MessageHeader* dtHeader,
                                   struct SessionManager_Session* session,
                                   struct Ducttape_pvt* context)
{
    uint64_t label = dtHeader->switchLabel;

    if (CryptoAuth_getState(&session->iface) >= CryptoAuth_HANDSHAKE3) {
        debugHandlesAndLabel0(context->logger, session, label, "layer2 sending run message");
        uint32_t sendHandle_be = session->sendHandle_be;
        #ifdef Version_2_COMPAT
        if (session->version < 3) {
            sendHandle_be |= HANDLE_FLAG_BIT_be;
        }
        #endif
        Message_push(message, &sendHandle_be, 4);
    } else {
        debugHandlesAndLabel0(context->logger, session, label, "layer2 sending start message");
        #ifdef Version_2_COMPAT
        if (session->version < 3) {
            Message_push(message, &session->receiveHandle_be, 4);
        }
        #endif
    }

    Message_shift(message, Headers_SwitchHeader_SIZE);

    Assert_true(message->bytes == (uint8_t*)dtHeader->switchHeader);

    return context->switchInterface.receiveMessage(message, &context->switchInterface);
}
Esempio n. 11
0
static int tryRouterSolicitation(struct Message* msg,
                                 struct Ethernet* eth,
                                 struct Headers_IP6Header* ip6,
                                 struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_RouterSolicitation* sol = (struct NDPHeader_RouterSolicitation*)msg->bytes;

    if (sol->oneThirtyThree != 133 || sol->zero != 0) {
printf("wrong type/code for router solicitation\n");
        return 0;
    }

    if (ns->pub.prefixLen < 1 || ns->pub.prefixLen > 128) {
printf("address prefix not set\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, ALL_ROUTERS, 16))
    {
printf("wrong address for router solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    // Prefix option
    struct NDPHeader_RouterAdvert_PrefixOpt prefix = {
        .three = 3,
        .four = 4,
        .bits = 0,
        .validLifetimeSeconds_be = 0xffffffffu,
        .preferredLifetimeSeconds_be = 0xffffffffu,
        .reservedTwo = 0
    };
    Bits_memcpyConst(prefix.prefix, ns->pub.advertisePrefix, 16);
    prefix.prefixLen = ns->pub.prefixLen;
    Message_push(msg, &prefix, sizeof(struct NDPHeader_RouterAdvert_PrefixOpt), NULL);

    // NDP message
    struct NDPHeader_RouterAdvert adv = {
        .oneThirtyFour = 134,
        .zero = 0,
        .checksum = 0,
        .currentHopLimit = 0,
        .bits = 0,
        .routerLifetime_be = Endian_hostToBigEndian16(10),
        .reachableTime_be = 0,
        .retransTime_be = 0
    };
    Message_push(msg, &adv, sizeof(struct NDPHeader_RouterAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static int tryNeighborSolicitation(struct Message* msg,
                                   struct Ethernet* eth,
                                   struct Headers_IP6Header* ip6,
                                   struct NDPServer_pvt* ns)
{
    if (msg->length < NDPHeader_RouterSolicitation_SIZE) {
        return 0;
    }
    struct NDPHeader_NeighborSolicitation* sol = (struct NDPHeader_NeighborSolicitation*)msg->bytes;

    if (sol->oneThirtyFive != 135 || sol->zero != 0) {
printf("wrong type/code for neighbor solicitation\n");
        return 0;
    }

    if (Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)
        && Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 13))
    {
printf("wrong address for neighbor solicitation\n");
        return 0;
    }

    // now we're committed.
    Message_shift(msg, -msg->length, NULL);

    struct NDPHeader_NeighborAdvert_MacOpt macOpt = {
        .two = 2,
        .one = 1
    };
    Bits_memcpyConst(macOpt.mac, eth->destAddr, 6);
    Message_push(msg, &macOpt, sizeof(struct NDPHeader_NeighborAdvert_MacOpt), NULL);

    struct NDPHeader_NeighborAdvert na = {
        .oneThirtySix = 136,
        .zero = 0,
        .checksum = 0,
        .bits = NDPHeader_NeighborAdvert_bits_ROUTER
            | NDPHeader_NeighborAdvert_bits_SOLICITED
            | NDPHeader_NeighborAdvert_bits_OVERRIDE
    };
    Bits_memcpyConst(na.targetAddr, UNICAST_ADDR, 16);
    Message_push(msg, &na, sizeof(struct NDPHeader_NeighborAdvert), NULL);

    sendResponse(msg, eth, ip6, ns);
    return 1;
}

static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface->receiverContext);

    if (msg->length < Ethernet_SIZE + Headers_IP6Header_SIZE) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    struct Ethernet* eth = (struct Ethernet*) msg->bytes;
    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (&eth[1]);

    if (eth->ethertype != Ethernet_TYPE_IP6 || ip6->nextHeader != 58 /* ICMPv6 */) {
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }

    // store the eth and ip6 headers so they don't get clobbered
    struct Ethernet storedEth;
    Message_pop(msg, &storedEth, sizeof(struct Ethernet), NULL);

    struct Headers_IP6Header storedIp6;
    Message_pop(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);

    if (!tryNeighborSolicitation(msg, &storedEth, &storedIp6, ns)
        && !tryRouterSolicitation(msg, &storedEth, &storedIp6, ns))
    {
        Message_push(msg, &storedIp6, sizeof(struct Headers_IP6Header), NULL);
        Message_push(msg, &storedEth, sizeof(struct Ethernet), NULL);
        return Interface_receiveMessage(&ns->pub.generic, msg);
    }
    // responding happens in sendResponse..
    return 0;
}

static uint8_t sendMessage(struct Message* msg, struct Interface* iface)
{
    struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface);
    return Interface_sendMessage(ns->wrapped, msg);
}

struct NDPServer* NDPServer_new(struct Interface* external, struct Allocator* alloc)
{
    struct NDPServer_pvt* out = Allocator_calloc(alloc, sizeof(struct NDPServer_pvt), 1);
    out->wrapped = external;
    Identity_set(out);
    InterfaceWrapper_wrap(external, sendMessage, receiveMessage, &out->pub.generic);
    return &out->pub;
}
Esempio n. 12
0
static Iface_DEFUN sendMessage(struct Message* msg, struct Iface* iface)
{
    struct ETHInterface_pvt* ctx =
        Identity_containerOf(iface, struct ETHInterface_pvt, pub.generic.iface);

    struct Sockaddr* sa = (struct Sockaddr*) msg->bytes;
    Assert_true(msg->length >= Sockaddr_OVERHEAD);
    Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE);

    struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } };
    Message_pop(msg, &sockaddr, sa->addrLen, NULL);

    struct sockaddr_ll addr;
    Bits_memcpy(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll));

    if (sockaddr.generic.flags & Sockaddr_flags_BCAST) {
        Bits_memset(addr.sll_addr, 0xff, 6);
    } else {
        Bits_memcpy(addr.sll_addr, sockaddr.mac, 6);
    }

    struct ETHInterface_Header hdr = {
        .version = ETHInterface_CURRENT_VERSION,
        .zero = 0,
        .length_be = Endian_hostToBigEndian16(msg->length + ETHInterface_Header_SIZE),
        .fc00_be = Endian_hostToBigEndian16(0xfc00)
    };
    Message_push(msg, &hdr, ETHInterface_Header_SIZE, NULL);
    struct Except* eh = NULL;
    sendMessageInternal(msg, &addr, ctx, eh);
    return NULL;
}

static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* messageAlloc)
{
    struct Message* msg = Message_new(MAX_PACKET_SIZE, PADDING, messageAlloc);

    struct sockaddr_ll addr;
    uint32_t addrLen = sizeof(struct sockaddr_ll);

    // Knock it out of alignment by 2 bytes so that it will be
    // aligned when the idAndPadding is shifted off.
    Message_shift(msg, 2, NULL);

    int rc = recvfrom(context->socket,
                      msg->bytes,
                      msg->length,
                      0,
                      (struct sockaddr*) &addr,
                      &addrLen);

    if (rc < ETHInterface_Header_SIZE) {
        Log_debug(context->logger, "Failed to receive eth frame");
        return;
    }

    Assert_true(msg->length >= rc);
    msg->length = rc;

    //Assert_true(addrLen == SOCKADDR_LL_LEN);

    struct ETHInterface_Header hdr;
    Message_pop(msg, &hdr, ETHInterface_Header_SIZE, NULL);

    // here we could put a switch statement to handle different versions differently.
    if (hdr.version != ETHInterface_CURRENT_VERSION) {
        Log_debug(context->logger, "DROP unknown version");
        return;
    }

    uint16_t reportedLength = Endian_bigEndianToHost16(hdr.length_be);
    reportedLength -= ETHInterface_Header_SIZE;
    if (msg->length != reportedLength) {
        if (msg->length < reportedLength) {
            Log_debug(context->logger, "DROP size field is larger than frame");
            return;
        }
        msg->length = reportedLength;
    }
    if (hdr.fc00_be != Endian_hostToBigEndian16(0xfc00)) {
        Log_debug(context->logger, "DROP bad magic");
        return;
    }

    struct ETHInterface_Sockaddr  sockaddr = { .zero = 0 };
    Bits_memcpy(sockaddr.mac, addr.sll_addr, 6);
    sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE;
    if (addr.sll_pkttype == PACKET_BROADCAST) {
        sockaddr.generic.flags |= Sockaddr_flags_BCAST;
    }

    Message_push(msg, &sockaddr, ETHInterface_Sockaddr_SIZE, NULL);

    Assert_true(!((uintptr_t)msg->bytes % 4) && "Alignment fault");

    Iface_send(&context->pub.generic.iface, msg);
}

static void handleEvent(void* vcontext)
{
    struct ETHInterface_pvt* context = Identity_check((struct ETHInterface_pvt*) vcontext);
    struct Allocator* messageAlloc = Allocator_child(context->pub.generic.alloc);
    handleEvent2(context, messageAlloc);
    Allocator_free(messageAlloc);
}

List* ETHInterface_listDevices(struct Allocator* alloc, struct Except* eh)
{
    List* out = List_new(alloc);
#ifndef android
    struct ifaddrs* ifaddr = NULL;
    if (getifaddrs(&ifaddr) || ifaddr == NULL) {
        Except_throw(eh, "getifaddrs() -> errno:%d [%s]", errno, strerror(errno));
    }
    for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) {
            List_addString(out, String_new(ifa->ifa_name, alloc), alloc);
        }
    }
    freeifaddrs(ifaddr);
#endif
    return out;
}

static int closeSocket(struct Allocator_OnFreeJob* j)
{
    struct ETHInterface_pvt* ctx = Identity_check((struct ETHInterface_pvt*) j->userData);
    close(ctx->socket);
    return 0;
}

struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
                                      const char* bindDevice,
                                      struct Allocator* alloc,
                                      struct Except* exHandler,
                                      struct Log* logger)
{
    struct ETHInterface_pvt* ctx = Allocator_calloc(alloc, sizeof(struct ETHInterface_pvt), 1);
    Identity_set(ctx);
    ctx->pub.generic.iface.send = sendMessage;
    ctx->pub.generic.alloc = alloc;
    ctx->logger = logger;

    struct ifreq ifr = { .ifr_ifindex = 0 };

    ctx->socket = socket(AF_PACKET, SOCK_DGRAM, Ethernet_TYPE_CJDNS);
    if (ctx->socket == -1) {
        Except_throw(exHandler, "call to socket() failed. [%s]", strerror(errno));
    }
    Allocator_onFree(alloc, closeSocket, ctx);

    CString_strncpy(ifr.ifr_name, bindDevice, IFNAMSIZ - 1);
    ctx->ifName = String_new(bindDevice, alloc);

    if (ioctl(ctx->socket, SIOCGIFINDEX, &ifr) == -1) {
        Except_throw(exHandler, "failed to find interface index [%s]", strerror(errno));
    }
    ctx->ifindex = ifr.ifr_ifindex;

    if (ioctl(ctx->socket, SIOCGIFFLAGS, &ifr) < 0) {
        Except_throw(exHandler, "ioctl(SIOCGIFFLAGS) [%s]", strerror(errno));
    }
    if (!((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))) {
        Log_info(logger, "Bringing up interface [%s]", ifr.ifr_name);
        ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
        if (ioctl(ctx->socket, SIOCSIFFLAGS, &ifr) < 0) {
            Except_throw(exHandler, "ioctl(SIOCSIFFLAGS) [%s]", strerror(errno));
        }
    }

    ctx->addrBase = (struct sockaddr_ll) {
        .sll_family = AF_PACKET,
        .sll_protocol = Ethernet_TYPE_CJDNS,
        .sll_ifindex = ctx->ifindex,
        .sll_hatype = ARPHRD_ETHER,
        .sll_pkttype = PACKET_OTHERHOST,
        .sll_halen = ETH_ALEN
    };

    if (bind(ctx->socket, (struct sockaddr*) &ctx->addrBase, sizeof(struct sockaddr_ll))) {
        Except_throw(exHandler, "call to bind() failed [%s]", strerror(errno));
    }

    Socket_makeNonBlocking(ctx->socket);

    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc, exHandler);

    return &ctx->pub;
}
Esempio n. 13
0
int main()
{
    AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey);
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Log* logger = FileWriterLog_new(stdout, alloc);
    struct Random* rand = Random_new(alloc, logger, NULL);
    struct EventBase* eb = EventBase_new(alloc);

    struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand);
    struct Sockaddr_storage ip6ToGive;
    Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive);
    IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, 0, NULL, 0, ipTun);

    struct Message* message;
    Message_STACK(message, 64, 512);
    message->alloc = alloc;

    const char* requestForAddresses =
        "d"
          "1:q" "21:IpTunnel_getAddresses"
          "4:txid" "4:abcd"
        "e";
    CString_strcpy((char*)message->bytes, requestForAddresses);
    message->length = CString_strlen(requestForAddresses);

    Message_shift(message, Headers_UDPHeader_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;

    uh->srcPort_be = 0;
    uh->destPort_be = 0;
    uh->length_be = Endian_hostToBigEndian16(message->length - Headers_UDPHeader_SIZE);
    uint16_t* checksum = &uh->checksum_be;
    *checksum = 0;
    uint32_t length = message->length;

    Message_shift(message, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;

    ip->versionClassAndFlowLabel = 0;
    ip->flowLabelLow_be = 0;
    ip->payloadLength_be = Endian_hostToBigEndian16(length);
    ip->nextHeader = 17;
    ip->hopLimit = 255;
    Bits_memset(ip->sourceAddr, 0, 32);
    Headers_setIpVersion(ip);

    Message_shift(message, RouteHeader_SIZE + DataHeader_SIZE, NULL);
    struct RouteHeader* rh = (struct RouteHeader*) message->bytes;
    struct DataHeader* dh = (struct DataHeader*) &rh[1];

    Bits_memset(rh, 0, RouteHeader_SIZE + DataHeader_SIZE);
    Bits_memcpy(rh->ip6, nodeCjdnsIp6, 16);
    Bits_memcpy(rh->publicKey, fakePubKey, 32);
    DataHeader_setContentType(dh, ContentType_IPTUN);

    *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length);

    int origCap = message->capacity;
    int origLen = message->length;

    struct Iface nodeIface = { .send = responseWithIpCallback };
    Iface_plumb(&nodeIface, &ipTun->nodeInterface);
    struct Iface tunIface = { .send = messageToTun };
    Iface_plumb(&tunIface, &ipTun->tunInterface);

    Iface_send(&nodeIface, message);
    Assert_true(called == 2);
    called = 0;

    // This is a hack, reusing the message will cause breakage if IpTunnel is refactored.
    Message_reset(message);
    Message_shift(message, origCap, NULL);
    message->length = origLen;

    Bits_memcpy(ip->sourceAddr, fakeIp6ToGive, 16);
    // This can't be zero.
    Bits_memset(ip->destinationAddr, 1, 16);

    Iface_send(&nodeIface, message);
    Assert_true(called == 1);

    Allocator_free(alloc);
    return 0;
}
Esempio n. 14
0
int main()
{
    // This is valid benc but it takes over 75k of memory (on an amd64)
    // to build a structure representing it.
    char* evilBenc =
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "d1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:ad1:a"
        "3:lol"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
        "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";

    struct Ducttape* dt = TestFramework_setUp();

    struct Allocator* allocator = MallocAllocator_new(85000);
    uint16_t buffLen = sizeof(struct Ducttape_IncomingForMe) + 8 + strlen(evilBenc);
    uint8_t* buff = allocator->calloc(buffLen, 1, allocator);

    struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) (buff + Headers_SwitchHeader_SIZE);
    uint8_t* herPublicKey = (uint8_t*) "0123456789abcdefghijklmnopqrstuv";
    AddressCalc_addressForPublicKey(ip6->sourceAddr, herPublicKey);

    struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (ip6 + 1);
    ip6->hopLimit = 0;
    ip6->nextHeader = 17;
    udp->sourceAndDestPorts = 0;
    udp->length_be = Endian_hostToBigEndian16(strlen(evilBenc));

    strncpy((char*)(udp + 1), evilBenc, strlen(evilBenc));

    struct Message m = { .bytes = buff, .length = buffLen, .padding = 0 };

    Ducttape_injectIncomingForMe(&m, dt, herPublicKey);
}
Esempio n. 15
0
static void testAddr(struct Context* ctx,
                     char* addr4, int prefix4, int alloc4,
                     char* addr6, int prefix6, int alloc6)
{
    struct Allocator* alloc = Allocator_child(ctx->alloc);
    struct IpTunnel* ipTun = IpTunnel_new(ctx->log, ctx->base, alloc, ctx->rand, NULL);

    struct Sockaddr* sa4 = NULL;
    struct Sockaddr_storage ip6ToGive;
    struct Sockaddr_storage ip4ToGive;
    if (addr4) {
        Assert_true(!Sockaddr_parse(addr4, &ip4ToGive));
        sa4 = &ip4ToGive.addr;
        Assert_true(Sockaddr_getFamily(sa4) == Sockaddr_AF_INET);
    }
    struct Sockaddr* sa6 = NULL;
    if (addr6) {
        Assert_true(!Sockaddr_parse(addr6, &ip6ToGive));
        sa6 = &ip6ToGive.addr;
        Assert_true(Sockaddr_getFamily(sa6) == Sockaddr_AF_INET6);
    }

    IpTunnel_allowConnection(ctx->pubKey,
                             sa6, prefix6, alloc6,
                             sa4, prefix4, alloc4,
                             ipTun);

    struct Message* msg = Message_new(64, 512, alloc);
    const char* requestForAddresses =
        "d"
          "1:q" "21:IpTunnel_getAddresses"
          "4:txid" "4:abcd"
        "e";
    CString_strcpy(msg->bytes, requestForAddresses);
    msg->length = CString_strlen(requestForAddresses);

    Message_push(msg, NULL, Headers_UDPHeader_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) msg->bytes;
    uh->length_be = Endian_hostToBigEndian16(msg->length - Headers_UDPHeader_SIZE);

    uint16_t* checksum = &((struct Headers_UDPHeader*) msg->bytes)->checksum_be;
    *checksum = 0;
    uint32_t length = msg->length;

    // Because of old reasons, we need to have at least an empty IPv6 header
    Message_push(msg, NULL, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) msg->bytes;
    Headers_setIpVersion(ip);
    ip->payloadLength_be = Endian_hostToBigEndian16(msg->length - Headers_IP6Header_SIZE);
    ip->nextHeader = 17;

    *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length);

    pushRouteDataHeaders(ctx, msg);

    struct IfaceContext* nodeIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1);
    nodeIf->ctx = ctx;
    nodeIf->iface.send = responseWithIpCallback;
    struct IfaceContext* tunIf = Allocator_calloc(alloc, sizeof(struct IfaceContext), 1);
    tunIf->ctx = ctx;
    tunIf->iface.send = messageToTun;
    Iface_plumb(&nodeIf->iface, &ipTun->nodeInterface);
    Iface_plumb(&tunIf->iface, &ipTun->tunInterface);
    ctx->expectedResponse =
        getExpectedResponse(sa4, prefix4, alloc4, sa6, prefix6, alloc6, alloc);
    Iface_send(&nodeIf->iface, msg);
    Assert_true(ctx->called == 2);
    ctx->called = 0;

    if (sa4) {
        uint8_t* addrBytes = NULL;
        Assert_true(Sockaddr_getAddress(sa4, &addrBytes) == 4);
        uint32_t addr;
        Bits_memcpy(&addr, addrBytes, 4);
        addr = Endian_bigEndianToHost32(addr);
        // Send from the address specified
        Assert_true(trySend4(alloc, addr, &nodeIf->iface, ctx));

        if (alloc4 < 32) {
            // Send from another (random) address in the prefix
            uint32_t flip = Random_uint32(ctx->rand) >> alloc4;
            if (prefix4 != 32) {
                Assert_true(trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx));
            } else {
                // If netSize is not specified, we do not allow multi-address
                Assert_true(!trySend4(alloc, addr ^ flip, &nodeIf->iface, ctx));
            }
        } else {
Esempio n. 16
0
int main()
{
    AddressCalc_addressForPublicKey(nodeCjdnsIp6, fakePubKey);
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Writer* w = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(w, alloc);
    struct Random* rand = Random_new(alloc, logger, NULL);
    struct EventBase* eb = EventBase_new(alloc);

    struct IpTunnel* ipTun = IpTunnel_new(logger, eb, alloc, rand, NULL);
    struct Sockaddr_storage ip6ToGive;
    Sockaddr_parse("fd01:0101:0101:0101:0101:0101:0101:0101", &ip6ToGive);
    IpTunnel_allowConnection(fakePubKey, &ip6ToGive.addr, NULL, ipTun);

    struct Message* message;
    Message_STACK(message, 64, 512);
    message->alloc = alloc;

    const char* requestForAddresses =
        "d"
          "1:q" "21:IpTunnel_getAddresses"
          "4:txid" "4:abcd"
        "e";
    CString_strcpy((char*)message->bytes, requestForAddresses);
    message->length = CString_strlen(requestForAddresses);

    Message_shift(message, Headers_UDPHeader_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;

    uh->srcPort_be = 0;
    uh->destPort_be = 0;
    uh->length_be = Endian_hostToBigEndian16(message->length - Headers_UDPHeader_SIZE);
    uint16_t* checksum = &uh->checksum_be;
    *checksum = 0;
    uint32_t length = message->length;

    Message_shift(message, Headers_IP6Header_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;

    ip->versionClassAndFlowLabel = 0;
    ip->flowLabelLow_be = 0;
    ip->payloadLength_be = Endian_hostToBigEndian16(length);
    ip->nextHeader = 17;
    ip->hopLimit = 255;
    Bits_memset(ip->sourceAddr, 0, 32);
    Headers_setIpVersion(ip);

    Message_shift(message, IpTunnel_PacketInfoHeader_SIZE, NULL);
    struct IpTunnel_PacketInfoHeader* pi = (struct IpTunnel_PacketInfoHeader*) message->bytes;

    Bits_memcpyConst(pi->nodeIp6Addr, nodeCjdnsIp6, 16);
    Bits_memcpyConst(pi->nodeKey, fakePubKey, 32);

    *checksum = Checksum_udpIp6(ip->sourceAddr, (uint8_t*) uh, length);

    ipTun->nodeInterface.receiveMessage = responseWithIpCallback;
    ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface);
    Assert_true(called);
    called = 0;

    // Now create a message for someone else.
    Message_shift(message,
        Headers_UDPHeader_SIZE
        + Headers_IP6Header_SIZE
        + IpTunnel_PacketInfoHeader_SIZE,
        NULL);
    Bits_memcpyConst(ip->sourceAddr, fakeIp6ToGive, 16);
    // This can't be zero.
    Bits_memset(ip->destinationAddr, 1, 16);

    ipTun->tunInterface.receiveMessage = messageToTun;
    ipTun->nodeInterface.sendMessage(message, &ipTun->nodeInterface);
    Assert_true(called);

    Allocator_free(alloc);
    return 0;
}
Esempio n. 17
0
static uint16_t completeChecksum(uint32_t state)
{
    return Endian_hostToBigEndian16(~state & 0xFFFF);
}