Example #1
0
struct TAPDevice* TAPDevice_find(const char* preferredName,
                                 struct Except* eh,
                                 struct Allocator* alloc)
{
    #define BUFF_SZ 0x100
    char guid[BUFF_SZ] = {0};
    char buff[BUFF_SZ] = {0};
    if (preferredName != NULL) {
        snprintf(buff, sizeof(buff), "%s", preferredName);
    }

    if (get_device_guid(guid, sizeof(guid), buff, sizeof(buff), eh)) {
        return NULL;
    }

    struct TAPDevice* out = Allocator_malloc(alloc, sizeof(struct TAPDevice));
    out->name = Allocator_malloc(alloc, CString_strlen(buff)+1);
    Bits_memcpy(out->name, buff, CString_strlen(buff)+1);

    snprintf(buff, sizeof(buff), USERMODEDEVICEDIR "%s" TAPSUFFIX, guid);

    out->path = Allocator_malloc(alloc, CString_strlen(buff)+1);
    Bits_memcpy(out->path, buff, CString_strlen(buff)+1);
    return out;
}
Example #2
0
static void onConnectionParent(struct Pipe* p, int status)
{
    Assert_true(!status);
    struct Context* c = Identity_check((struct Context*) p->userData);

    struct Allocator* alloc = Allocator_child(c->alloc);
    uint8_t* bytes = Allocator_calloc(alloc, CString_strlen(MESSAGE) + 1, 1);
    Bits_memcpy(bytes, MESSAGE, CString_strlen(MESSAGE));
    struct Message* m = Allocator_clone(alloc, (&(struct Message) {
        .length = CString_strlen(MESSAGE),
        .padding = 0,
        .capacity = CString_strlen(MESSAGE),
        .alloc = alloc,
        .bytes = bytes
    }));
Example #3
0
static uint8_t responseWithIpCallback(struct Message* message, struct Interface* iface)
{
    struct IpTunnel_PacketInfoHeader* pi = (struct IpTunnel_PacketInfoHeader*) message->bytes;
    Assert_true(!Bits_memcmp(nodeCjdnsIp6, pi->nodeIp6Addr, 16));
    Assert_true(!Bits_memcmp(fakePubKey, pi->nodeKey, 32));

    Message_shift(message, -IpTunnel_PacketInfoHeader_SIZE, NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;
    Assert_true(Headers_getIpVersion(ip) == 6);
    uint16_t length = Endian_bigEndianToHost16(ip->payloadLength_be);
    Assert_true(length + Headers_IP6Header_SIZE == message->length);
    Assert_true(ip->nextHeader == 17);
    Assert_true(Bits_isZero(ip->sourceAddr, 32));

    Message_shift(message, -Headers_IP6Header_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;
    Assert_true(!Checksum_udpIp6(ip->sourceAddr, message->bytes, length));

    Assert_true(uh->srcPort_be == 0);
    Assert_true(uh->destPort_be == 0);
    Assert_true(Endian_bigEndianToHost16(uh->length_be) + Headers_UDPHeader_SIZE == length);

    Message_shift(message, -Headers_UDPHeader_SIZE, NULL);
    char* expectedResponse =
        "d"
          "9:addresses" "d"
            "3:ip6" "16:\xfd\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
          "e"
          "4:txid" "4:abcd"
        "e";
    Assert_true(message->length == (int32_t) CString_strlen(expectedResponse));
    Assert_true(!Bits_memcmp(message->bytes, expectedResponse, message->length));
    called = 1;
    return 0;
}
Example #4
0
static int calculateAuth(Dict* message,
                         String* password,
                         String* cookieStr,
                         struct Allocator* alloc)
{
    // Calculate the hash of the password.
    String* hashHex = String_newBinary(NULL, 64, alloc);
    uint8_t passAndCookie[64];
    uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0;
    snprintf((char*) passAndCookie, 64, "%s%u", password->bytes, cookie);
    uint8_t hash[32];
    crypto_hash_sha256(hash, passAndCookie, CString_strlen((char*) passAndCookie));
    Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32);

    Dict_putString(message, String_new("hash", alloc), hashHex, alloc);
    Dict_putString(message, String_new("cookie", alloc), cookieStr, alloc);

    // serialize the message with the password hash
    struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE, alloc);
    BencMessageWriter_write(message, msg, NULL);

    // calculate the hash of the message with the password hash
    crypto_hash_sha256(hash, msg->bytes, msg->length);

    // swap the hash of the message with the password hash into the location
    // where the password hash was.
    Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32);
    return 0;
}
static int parseEmptyList()
{
    char* test = "d" "2:hi" "le" "e";
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Reader* reader = ArrayReader_new(test, CString_strlen(test), alloc);
    Dict d;
    int ret = StandardBencSerializer_get()->parseDictionary(reader, alloc, &d);

    char out[256];
    struct Writer* w = ArrayWriter_new(out, 256, alloc);
    ret |= StandardBencSerializer_get()->serializeDictionary(w, &d);
    ret |= Bits_memcmp(test, out, CString_strlen(test));

    Allocator_free(alloc);
    return ret;
}
/**
 * Helper function for writing an integer into a writer in base 10 format.
 *
 * @param writer the place to write the integer to.
 * @param integer the number to write.
 */
static int32_t writeint64_t(struct Writer* writer,
                            int64_t integer)
{
    char buffer[32] = {0};
    snprintf(buffer, 32, "%" PRId64, integer);
    return Writer_write(writer, buffer, CString_strlen(buffer));
}
Example #7
0
static void sendMessage(struct TwoNodes* tn,
                        char* message,
                        struct TestFramework* from,
                        struct TestFramework* to)
{
    struct Message* msg;
    Message_STACK(msg, 64, 512);

    Bits_memcpy(msg->bytes, message, CString_strlen(message) + 1);
    msg->length = CString_strlen(message) + 1;

    TestFramework_craftIPHeader(msg, from->ip, to->ip);

    msg = Message_clone(msg, from->alloc);

    struct Iface* fromIf;

    if (from == tn->nodeA) {
        fromIf = &tn->tunA;
    } else if (from == tn->nodeB) {
        fromIf = &tn->tunB;
    } else {
        Assert_true(false);
    }

    TUNMessageType_push(msg, Ethernet_TYPE_IP6, NULL);
    Iface_send(fromIf, msg);

    if (to == tn->nodeA) {
        Assert_true(tn->messageFrom == TUNA);
    } else if (to == tn->nodeB) {
        Assert_true(tn->messageFrom == TUNB);
    } else {
        Assert_true(false);
    }

    TestFramework_assertLastMessageUnaltered(tn->nodeA);
    TestFramework_assertLastMessageUnaltered(tn->nodeB);

    tn->messageFrom = 0;
}
Example #8
0
char* ArchInfo_describe(enum ArchInfo ai, struct Allocator* alloc)
{
    uint8_t flagBuff[archFlags_BUFF_SZ];
    archFlags(ai, flagBuff);

    uint8_t buff[1024];
    snprintf(buff, 1024, "%s %d-bit %sEndian %s",
        archStr(ai),
        ArchInfo_getBits(ai),
        ArchInfo_isBigEndian(ai) ? "Big" : "Little",
        flagBuff);

    int len = CString_strlen(buff);
    Assert_true(len < 1024);
    if (buff[len-1] == ' ') { buff[--len] = '\0'; }
    char* out = Allocator_malloc(alloc, len+1);
    Bits_memcpy(out, buff, len+1);
    return out;
}
Example #9
0
static Iface_DEFUN responseWithIpCallback(struct Message* message, struct Iface* iface)
{
    struct RouteHeader* rh = (struct RouteHeader*) message->bytes;
    Assert_true(!Bits_memcmp(nodeCjdnsIp6, rh->ip6, 16));
    Assert_true(!Bits_memcmp(fakePubKey, rh->publicKey, 32));

    Message_shift(message, -(RouteHeader_SIZE + DataHeader_SIZE), NULL);
    struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;
    Assert_true(Headers_getIpVersion(ip) == 6);
    uint16_t length = Endian_bigEndianToHost16(ip->payloadLength_be);
    Assert_true(length + Headers_IP6Header_SIZE == message->length);
    Assert_true(ip->nextHeader == 17);
    Assert_true(Bits_isZero(ip->sourceAddr, 32));

    Message_shift(message, -Headers_IP6Header_SIZE, NULL);
    struct Headers_UDPHeader* uh = (struct Headers_UDPHeader*) message->bytes;
    Assert_true(!Checksum_udpIp6(ip->sourceAddr, message->bytes, length));

    Assert_true(uh->srcPort_be == 0);
    Assert_true(uh->destPort_be == 0);
    Assert_true(Endian_bigEndianToHost16(uh->length_be) + Headers_UDPHeader_SIZE == length);

    Message_shift(message, -Headers_UDPHeader_SIZE, NULL);

    // We can't check that the message is an exact match because the padding depends on the
    // alignment of the output but we can make sure the right content is there...
    // Message should start with "d0000" (with some number of zeros)
    char* expectedResponse =
        "9:addresses" "d"
            "3:ip6" "16:\xfd\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
            "9:ip6Prefix" "i128e"
          "e"
          "4:txid" "4:abcd"
        "e";
    Assert_true(message->length >= (int32_t) CString_strlen(expectedResponse));
    Assert_true(CString_strstr(message->bytes, expectedResponse));
    called |= 2;
    return 0;
}
Example #10
0
static int is_tap_win32_dev(const char *guid)
{
    HKEY netcard_key;
    LONG status;
    DWORD len;
    int i = 0;

    status = RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        ADAPTER_KEY,
        0,
        KEY_READ,
        &netcard_key);

    if (status != ERROR_SUCCESS) {
        return FALSE;
    }

    for (;;) {
        char enum_name[256];
        char unit_string[256];
        HKEY unit_key;
        char component_id_string[] = "ComponentId";
        char component_id[256];
        char net_cfg_instance_id_string[] = "NetCfgInstanceId";
        char net_cfg_instance_id[256];
        DWORD data_type;

        len = sizeof (enum_name);
        status = RegEnumKeyEx(
            netcard_key,
            i,
            enum_name,
            &len,
            NULL,
            NULL,
            NULL,
            NULL);

        if (status == ERROR_NO_MORE_ITEMS) {
            break;
        } else if (status != ERROR_SUCCESS) {
            return FALSE;
        }

        snprintf (unit_string, sizeof(unit_string), "%s\\%s",
                  ADAPTER_KEY, enum_name);

        status = RegOpenKeyEx(
            HKEY_LOCAL_MACHINE,
            unit_string,
            0,
            KEY_READ,
            &unit_key);

        if (status != ERROR_SUCCESS) {
            return FALSE;
        } else {
            len = sizeof (component_id);
            status = RegQueryValueEx(
                unit_key,
                component_id_string,
                NULL,
                &data_type,
                (uint8_t*)component_id,
                &len);

            if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
                len = sizeof (net_cfg_instance_id);
                status = RegQueryValueEx(
                    unit_key,
                    net_cfg_instance_id_string,
                    NULL,
                    &data_type,
                    (uint8_t*)net_cfg_instance_id,
                    &len);

                if (status == ERROR_SUCCESS && data_type == REG_SZ) {
                    if (!Bits_memcmp(component_id, "tap", CString_strlen("tap")) &&
                        !strcmp (net_cfg_instance_id, guid)) {
                        RegCloseKey (unit_key);
                        RegCloseKey (netcard_key);
                        return TRUE;
                    }
                }
            }
            RegCloseKey (unit_key);
        }
        ++i;
    }

    RegCloseKey (netcard_key);
    return FALSE;
}
Example #11
0
static int get_device_guid(
    char *name,
    int name_size,
    char *actual_name,
    int actual_name_size,
    struct Except* eh)
{
    LONG status;
    HKEY control_net_key;
    DWORD len;

    WinFail_check(eh, (
        RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &control_net_key)
    ));

    int stop = 0;
    for (int i = 0; !stop; i++) {
        char enum_name[256];
        char connection_string[256];
        HKEY connKey;
        char name_data[256];
        DWORD name_type;
        const char name_string[] = "Name";

        len = sizeof (enum_name);
        status = RegEnumKeyEx(control_net_key, i, enum_name, &len, NULL, NULL, NULL, NULL);

        if (status == ERROR_NO_MORE_ITEMS) {
            break;
        } else if (status != ERROR_SUCCESS) {
            WinFail_fail(eh, "RegEnumKeyEx() failed", status);
        }

        if (len != CString_strlen(NETWORK_ADAPTER_GUID)) {
            // extranious directory, eg: "Descriptions"
            continue;
        }

        snprintf(connection_string,
             sizeof(connection_string),
             "%s\\%s\\Connection",
             NETWORK_CONNECTIONS_KEY, enum_name);

        WinFail_check(eh, (
            RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connKey)
        ));


        // In Windows 10, some interface keys don't have names. We should keep
        // going and treat those interfaces as having empty string names.

        len = sizeof (name_data);
        status = RegQueryValueEx(connKey, name_string, NULL, &name_type,
            (uint8_t*)name_data, &len);

        if (status == ERROR_FILE_NOT_FOUND) {
            // The interface has no name.
            strncpy(name_data, "",  sizeof (name_data));
        } else if (status != ERROR_SUCCESS) {
            WinFail_fail(eh, "RegQueryValueEx() for interface name failed", status);
        } else {
            if (name_type != REG_SZ) {
                // Someone named an interface with a non-string
                WinFail_fail(eh, "RegQueryValueEx() name_type != REG_SZ", status);
            }
        }

        if (is_tap_win32_dev(enum_name)) {
            snprintf(name, name_size, "%s", enum_name);
            if (actual_name) {
                if (CString_strcmp(actual_name, "") != 0) {
                    if (CString_strcmp(name_data, actual_name) != 0) {
                        RegCloseKey (connKey);
                        ++i;
                        continue;
                    }
                }
                else {
                    snprintf(actual_name, actual_name_size, "%s", name_data);
                }
            }
            stop = 1;
        }

        RegCloseKey(connKey);
    }

    RegCloseKey (control_net_key);

    if (stop == 0) {
        return -1;
    }

    return 0;
}
Example #12
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;
}
Example #13
0
int main(int argc, char** argv)
{
    #ifdef Log_KEYS
        fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");
    #endif

    if (argc < 2) {
        // Fall through.
    } else if (!CString_strcmp("angel", argv[1])) {
        return AngelInit_main(argc, argv);
    } else if (!CString_strcmp("core", argv[1])) {
        return Core_main(argc, argv);
    }

    Assert_ifParanoid(argc > 0);
    struct Except* eh = NULL;

    // Allow it to allocate 8MB
    struct Allocator* allocator = MallocAllocator_new(1<<23);
    struct Random* rand = Random_new(allocator, NULL, eh);
    struct EventBase* eventBase = EventBase_new(allocator);

    if (argc == 2) {
        // one argument
        if ((CString_strcmp(argv[1], "--help") == 0) || (CString_strcmp(argv[1], "-h") == 0)) {
            return usage(allocator, argv[0]);
        } else if (CString_strcmp(argv[1], "--genconf") == 0) {
            return genconf(rand);
        } else if (CString_strcmp(argv[1], "--pidfile") == 0) {
            // deprecated
            fprintf(stderr, "'--pidfile' option is deprecated.\n");
            return 0;
        } else if (CString_strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (CString_strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if ((CString_strcmp(argv[1], "--version") == 0)
            || (CString_strcmp(argv[1], "-v") == 0))
        {
            printf("Cjdns protocol version: %d\n", Version_CURRENT_PROTOCOL);
            return 0;
        } else if (CString_strcmp(argv[1], "--cleanconf") == 0) {
            // Performed after reading configuration
        } else if (CString_strcmp(argv[1], "--nobg") == 0) {
            // Performed while reading configuration
        } else {
            fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]);
            fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
            return -1;
        }
    } else if (argc > 2) {
        // more than one argument?
        fprintf(stderr, "%s: too many arguments [%s]\n", argv[0], argv[1]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        // because of '--pidfile $filename'?
        if (CString_strcmp(argv[1], "--pidfile") == 0)
        {
            fprintf(stderr, "\n'--pidfile' option is deprecated.\n");
        }
        return -1;
    }

    if (isatty(STDIN_FILENO)) {
        // We were started from a terminal
        // The chances an user wants to type in a configuration
        // bij hand are pretty slim so we show him the usage
        return usage(allocator, argv[0]);
    } else {
        // We assume stdin is a configuration file and that we should
        // start routing
    }

    struct Reader* stdinReader = FileReader_new(stdin, allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    if (argc == 2 && CString_strcmp(argv[1], "--cleanconf") == 0) {
        struct Writer* stdoutWriter = FileWriter_new(stdout, allocator);
        JsonBencSerializer_get()->serializeDictionary(stdoutWriter, &config);
        printf("\n");
        return 0;
    }

    int forceNoBackground = 0;
    if (argc == 2 && CString_strcmp(argv[1], "--nobg") == 0) {
        forceNoBackground = 1;
    }

    struct Writer* logWriter = FileWriter_new(stdout, allocator);
    struct Log* logger = WriterLog_new(logWriter, allocator);

    // --------------------- Get Admin  --------------------- //
    Dict* configAdmin = Dict_getDict(&config, String_CONST("admin"));
    String* adminPass = Dict_getString(configAdmin, String_CONST("password"));
    String* adminBind = Dict_getString(configAdmin, String_CONST("bind"));
    if (!adminPass) {
        adminPass = String_newBinary(NULL, 32, allocator);
        Random_base32(rand, (uint8_t*) adminPass->bytes, 32);
        adminPass->len = CString_strlen(adminPass->bytes);
    }
    if (!adminBind) {
        Except_throw(eh, "You must specify admin.bind in the cjdroute.conf file.");
    }

    // --------------------- Welcome to cjdns ---------------------- //
    char* archInfo = ArchInfo_describe(ArchInfo_detect(), allocator);
    char* sysInfo = SysInfo_describe(SysInfo_detect(), allocator);
    Log_info(logger, "Cjdns %s %s", archInfo, sysInfo);

    // --------------------- Check for running instance  --------------------- //

    Log_info(logger, "Checking for running instance...");
    checkRunningInstance(allocator, eventBase, adminBind, adminPass, logger, eh);

    // --------------------- Setup Pipes to Angel --------------------- //
    char angelPipeName[64] = "client-angel-";
    Random_base32(rand, (uint8_t*)angelPipeName+13, 31);
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 0);
    struct Pipe* angelPipe = Pipe_named(angelPipeName, eventBase, eh, allocator);
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 2);
    angelPipe->logger = logger;

    char* args[] = { "angel", angelPipeName, NULL };

    // --------------------- Spawn Angel --------------------- //
    String* privateKey = Dict_getString(&config, String_CONST("privateKey"));

    char* corePath = Process_getPath(allocator);

    if (!corePath) {
        Except_throw(eh, "Can't find a usable cjdns core executable, "
                         "make sure it is in the same directory as cjdroute");
    }

    if (!privateKey) {
        Except_throw(eh, "Need to specify privateKey.");
    }
    Log_info(logger, "Forking angel to background.");
    Process_spawn(corePath, args, eventBase, allocator);

    // --------------------- Get user for angel to setuid() ---------------------- //
    String* securityUser = NULL;
    List* securityConf = Dict_getList(&config, String_CONST("security"));
    for (int i = 0; securityConf && i < List_size(securityConf); i++) {
        securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser"));
        if (securityUser) {
            int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel"));
            if (ea && *ea) {
                securityUser = NULL;
            }
            break;
        }
    }

    // --------------------- Pre-Configure Angel ------------------------- //
    Dict* preConf = Dict_new(allocator);
    Dict* adminPreConf = Dict_new(allocator);
    Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator);
    Dict_putString(adminPreConf, String_CONST("core"), String_new(corePath, allocator), allocator);
    Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator);
    Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator);
    Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator);
    if (securityUser) {
        Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator);
    }
    Dict* logging = Dict_getDict(&config, String_CONST("logging"));
    if (logging) {
        Dict_putDict(preConf, String_CONST("logging"), logging, allocator);
    }

    struct Message* toAngelMsg = Message_new(0, 1024, allocator);
    BencMessageWriter_write(preConf, toAngelMsg, eh);
    Interface_sendMessage(&angelPipe->iface, toAngelMsg);

    Log_debug(logger, "Sent [%d] bytes to angel process", toAngelMsg->length);

    // --------------------- Get Response from Angel --------------------- //

    struct Message* fromAngelMsg =
        InterfaceWaiter_waitForData(&angelPipe->iface, eventBase, allocator, eh);
    Dict* responseFromAngel = BencMessageReader_read(fromAngelMsg, allocator, eh);

    // --------------------- Get Admin Addr/Port/Passwd --------------------- //
    Dict* responseFromAngelAdmin = Dict_getDict(responseFromAngel, String_CONST("admin"));
    adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind"));

    if (!adminBind) {
        Except_throw(eh, "didn't get address and port back from angel");
    }
    struct Sockaddr_storage adminAddr;
    if (Sockaddr_parse(adminBind->bytes, &adminAddr)) {
        Except_throw(eh, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234",
                     adminBind->bytes);
    }

    // sanity check, Pipe_named() creates 2 events, see above.
    Assert_ifParanoid(EventBase_eventCount(eventBase) == 2);

    // --------------------- Configuration ------------------------- //
    Configurator_config(&config,
                        &adminAddr.addr,
                        adminPass,
                        eventBase,
                        logger,
                        allocator);

    // --------------------- noBackground ------------------------ //

    int64_t* noBackground = Dict_getInt(&config, String_CONST("noBackground"));
    if (forceNoBackground || (noBackground && *noBackground)) {
        EventBase_beginLoop(eventBase);
    }

    //Allocator_free(allocator);
    return 0;
}
Example #14
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 {
Example #15
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;
}
Example #16
0
static void encryptRndNonceTest()
{
    uint8_t buff[44];
    Bits_memset(buff, 0, 44);

    uint8_t nonce[24];
    Bits_memset(nonce, 0, 24);

    uint8_t secret[32];
    Bits_memset(secret, 0, 32);

    struct Message m = { .bytes=&buff[32], .length=HELLOWORLDLEN, .padding=32};
    CString_strcpy((char*) m.bytes, HELLOWORLDLOWER);

    CryptoAuth_encryptRndNonce(nonce, &m, secret);

    uint8_t* expected = (uint8_t*) "1391ac5d03ba9f7099bffbb6e6c69d67ae5bd79391a5b94399b293dc";
    uint8_t output[57];
    Hex_encode(output, 57, m.bytes, m.length);

    printf("\n%s\n%s\n", (char*) expected, (char*) output);
    Assert_true(!Bits_memcmp(expected, output, 56));

    Assert_true(!CryptoAuth_decryptRndNonce(nonce, &m, secret));
    Assert_true(m.length == HELLOWORLDLEN && !Bits_memcmp(m.bytes, HELLOWORLDLOWER, m.length));
}

static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger)
{
    struct RandomSeed* evilSeed = DeterminentRandomSeed_new(alloc, NULL);
    return Random_newWithSeed(alloc, logger, evilSeed, NULL);
}

struct Context
{
    struct Allocator* alloc;
    struct CryptoAuth* ca;
    struct CryptoAuth_Session* sess;
    struct Log* log;
    struct EventBase* base;
};

static struct Context* setUp(uint8_t* myPrivateKey,
                             uint8_t* herPublicKey,
                             uint8_t* authPassword,
                             struct Allocator* alloc)
{
    struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
    struct Log* log = ctx->log = FileWriterLog_new(stdout, alloc);
    struct EventBase* base = ctx->base = EventBase_new(alloc);
    struct CryptoAuth* ca = ctx->ca =
        CryptoAuth_new(alloc, myPrivateKey, base, log, evilRandom(alloc, log));

    struct CryptoAuth_Session* sess = ctx->sess =
        CryptoAuth_newSession(ca, alloc, herPublicKey, NULL, false, Gcc_FILE);

    if (authPassword) {
        CryptoAuth_setAuth(String_CONST(authPassword), NULL, sess);
    }

    return ctx;
}

static void testHello(uint8_t* password, uint8_t* expectedOutput)
{
    Assert_true(CString_strlen((char*)expectedOutput) == 264);
    struct Allocator* alloc = MallocAllocator_new(1<<20);
    struct Context* ctx = setUp(NULL, HERPUBKEY, password, alloc);
    struct Message* msg = Message_new(0, CryptoHeader_SIZE + 12, alloc);
    Message_push(msg, HELLOWORLD, HELLOWORLDLEN, NULL);

    Assert_true(!CryptoAuth_encrypt(ctx->sess, msg));

    char* actual = Hex_print(msg->bytes, msg->length, alloc);
    if (CString_strcmp(actual, expectedOutput)) {
        Assert_failure("Test failed.\n"
                       "Expected %s\n"
                       "     Got %s\n", expectedOutput, actual);
    }
    Allocator_free(alloc);
}