Esempio n. 1
0
struct AdminTestFramework* AdminTestFramework_setUp(int argc, char** argv, char* testName)
{
    if (argc > 2 && !strcmp(testName, argv[1]) && !strcmp("angel", argv[2])) {
        exit(AngelInit_main(argc-1, &argv[1]));
    }

    struct Allocator* alloc = MallocAllocator_new(1<<20);

    struct Writer* logwriter = FileWriter_new(stdout, alloc);
    Assert_true(logwriter);
    struct Log* logger = WriterLog_new(logwriter, alloc);

    struct EventBase* eventBase = EventBase_new(alloc);
    struct Random* rand = Random_new(alloc, logger, NULL);


    char asClientPipeName[32] = {0};
    Random_base32(rand, (uint8_t*)asClientPipeName, 31);
    struct Pipe* asClientPipe = Pipe_named(asClientPipeName, eventBase, NULL, alloc);
    asClientPipe->logger = logger;

    char asCorePipeName[32] = {0};
    Random_base32(rand, (uint8_t*)asCorePipeName, 31);
    struct Pipe* asCorePipe = Pipe_named(asCorePipeName, eventBase, NULL, alloc);
    asCorePipe->logger = logger;
    struct Interface* asCoreIface = FramingInterface_new(65535, &asCorePipe->iface, alloc);

    spawnAngel(testName, asClientPipeName, eventBase, alloc);

    Log_info(logger, "Initializing Angel");
    initAngel(asClientPipe, asCoreIface, (char*)asCorePipe->name, eventBase, logger, alloc, rand);

    struct Sockaddr_storage addr;
    Assert_true(!Sockaddr_parse("127.0.0.1", &addr));

    Log_info(logger, "Binding UDP admin socket");
    struct AddrInterface* udpAdmin =
        UDPAddrInterface_new(eventBase, &addr.addr, alloc, NULL, logger);

    String* password = String_new("abcd", alloc);
    struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, password);

    // Now setup the client.

    struct AdminClient* client =
        AdminClient_new(udpAdmin->addr, password, eventBase, logger, alloc);

    Assert_true(client);

    return Allocator_clone(alloc, (&(struct AdminTestFramework) {
        .admin = admin,
        .client = client,
        .alloc = alloc,
        .eventBase = eventBase,
        .logger = logger,
        .addr = Sockaddr_clone(udpAdmin->addr, alloc),
        .angelInterface = asCoreIface
    }));
Esempio n. 2
0
int main()
{
    struct Allocator* mainAlloc = MallocAllocator_new(1<<20);
    struct Log* log = FileWriterLog_new(stdout, mainAlloc);
    struct Random* rand = Random_new(mainAlloc, log, NULL);
    struct Context* ctx = Allocator_malloc(mainAlloc, sizeof(struct Context));
    Identity_set(ctx);

    struct Interface iface = { .sendMessage = NULL };
    struct Interface* fi = FramingInterface_new(4096, &iface, mainAlloc);
    fi->receiveMessage = messageOut;
    fi->receiverContext = ctx;

    for (int i = 0; i < CYCLES; i++) {
        struct Allocator* alloc = Allocator_child(mainAlloc);
        // max frame size must be at least 5 so that at least 1 byte of data is sent.
        int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1;
        int maxMessageSize = ( Random_uint32(rand) % (MAX_MSG_SZ - MIN_MSG_SZ) ) + MIN_MSG_SZ;
        Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize);
        ctx->alloc = alloc;
        ctx->messages = NULL;
        ctx->messageCount = 0;
        ctx->currentMessage = 0;

        // Create one huge message, then create lots of little frames inside of it
        // then split it up in random places and send the sections to the framing
        // interface.
        struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc);

        Assert_true(WORK_BUFF_SZ == msg->length);
        Random_bytes(rand, msg->bytes, msg->length);
        Message_shift(msg, -WORK_BUFF_SZ, NULL);

        for (;;) {
            int len = Random_uint32(rand) % maxFrameSize;
            if (!len) {
                len++;
            }
            if (msg->padding < len + 4) {
                break;
            }
            Message_shift(msg, len, NULL);

            ctx->messageCount++;
            ctx->messages =
                Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*));
            struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc);
            Bits_memcpy(om->bytes, msg->bytes, len);

            Message_push32(msg, len, NULL);
        }

        do {
            int nextMessageSize = Random_uint32(rand) % maxMessageSize;
            if (!nextMessageSize) {
                nextMessageSize++;
            }
            if (nextMessageSize > msg->length) {
                nextMessageSize = msg->length;
            }
            struct Allocator* msgAlloc = Allocator_child(alloc);
            struct Message* m = Message_new(nextMessageSize, 0, msgAlloc);
            Message_pop(msg, m->bytes, nextMessageSize, NULL);
            Interface_receiveMessage(&iface, m);
            Allocator_free(msgAlloc);
        } while (msg->length);

        Assert_true(ctx->messageCount == ctx->currentMessage);

        Allocator_free(alloc);
    }

    return 0;
}
Esempio n. 3
0
/*
 * This process is started with 2 parameters, they must all be numeric in base 10.
 * toAngel the pipe which is used to send data back to the angel process.
 * fromAngel the pipe which is used to read incoming data from the angel.
 *
 * Upon initialization, this process will wait for an initial configuration to be sent to
 * it and then it will send an initial response.
 */
int Core_main(int argc, char** argv)
{
    struct Except* eh = NULL;

    if (argc != 3) {
        Except_raise(eh, -1, "This is internal to cjdns and shouldn't started manually.");
    }

    struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE);
    struct Log* preLogger = FileWriterLog_new(stderr, alloc);
    struct EventBase* eventBase = EventBase_new(alloc);

    // -------------------- Setup the Pre-Logger ---------------------- //
    struct Log* logger = IndirectLog_new(alloc);
    IndirectLog_set(logger, preLogger);

    // -------------------- Setup the PRNG ---------------------- //
    struct Random* rand = LibuvEntropyProvider_newDefaultRandom(eventBase, logger, eh, alloc);

    // -------------------- Change Canary Value ---------------------- //
    MallocAllocator_setCanary(alloc, (long)Random_int64(rand));
    struct Allocator* tempAlloc = Allocator_child(alloc);


    // The first read inside of getInitialConfig() will begin it waiting.
    struct Pipe* angelPipe = Pipe_named(argv[2], eventBase, eh, alloc);
    angelPipe->logger = logger;
    angelPipe->onClose = angelDied;

    struct Interface* angelIface = FramingInterface_new(65535, &angelPipe->iface, alloc);

    Dict* config = getInitialConfig(angelIface, eventBase, tempAlloc, eh);

    struct Hermes* hermes = Hermes_new(angelIface, eventBase, logger, alloc);

    String* privateKeyHex = Dict_getString(config, String_CONST("privateKey"));
    Dict* adminConf = Dict_getDict(config, String_CONST("admin"));
    String* pass = Dict_getString(adminConf, String_CONST("pass"));
    String* bind = Dict_getString(adminConf, String_CONST("bind"));
    if (!(pass && privateKeyHex && bind)) {
        if (!pass) {
            Except_raise(eh, -1, "Expected 'pass'");
        }
        if (!bind) {
            Except_raise(eh, -1, "Expected 'bind'");
        }
        if (!privateKeyHex) {
            Except_raise(eh, -1, "Expected 'privateKey'");
        }
        Except_raise(eh, -1, "Expected 'pass', 'privateKey' and 'bind' in configuration.");
    }
    Log_keys(logger, "Starting core with admin password [%s]", pass->bytes);
    uint8_t privateKey[32];
    if (privateKeyHex->len != 64
        || Hex_decode(privateKey, 32, (uint8_t*) privateKeyHex->bytes, 64) != 32)
    {
        Except_raise(eh, -1, "privateKey must be 64 bytes of hex.");
    }

    struct Sockaddr_storage bindAddr;
    if (Sockaddr_parse(bind->bytes, &bindAddr)) {
        Except_raise(eh, -1, "bind address [%s] unparsable", bind->bytes);
    }

    struct AddrInterface* udpAdmin =
        UDPAddrInterface_new(eventBase, &bindAddr.addr, alloc, eh, logger);

    struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, pass);

    char* boundAddr = Sockaddr_print(udpAdmin->addr, tempAlloc);
    Dict adminResponse = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST(boundAddr)), NULL
    );
    Dict response = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&adminResponse), NULL
    ));
    // This always times out because the angel doesn't respond.
    Hermes_callAngel(&response, angelResponse, NULL, alloc, eh, hermes);

    // --------------------- Setup the Logger --------------------- //
    Dict* logging = Dict_getDict(config, String_CONST("logging"));
    String* logTo = Dict_getString(logging, String_CONST("logTo"));
    if (logTo && String_equals(logTo, String_CONST("stdout"))) {
        // do nothing, continue logging to stdout.
    } else {
        struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand);
        IndirectLog_set(logger, adminLogger);
        logger = adminLogger;
    }

    // CryptoAuth
    struct Address addr;
    parsePrivateKey(privateKey, &addr, eh);
    struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand);

    struct Sockaddr* myAddr = Sockaddr_fromBytes(addr.ip6.bytes, Sockaddr_AF_INET6, alloc);

    struct SwitchCore* switchCore = SwitchCore_new(logger, alloc);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(alloc);
    ReplyModule_register(registry, alloc);

    // Router
    struct RouterModule* router = RouterModule_register(registry,
                                                        alloc,
                                                        addr.key,
                                                        eventBase,
                                                        logger,
                                                        admin,
                                                        rand);

    SerializationModule_register(registry, logger, alloc);

    struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand, hermes);

    struct Ducttape* dt = Ducttape_register(privateKey,
                                            registry,
                                            router,
                                            switchCore,
                                            eventBase,
                                            alloc,
                                            logger,
                                            admin,
                                            ipTun,
                                            rand);

    struct SwitchPinger* sp =
        SwitchPinger_new(&dt->switchPingerIf, eventBase, logger, alloc);

    // Interfaces.
    struct InterfaceController* ifController =
        DefaultInterfaceController_new(cryptoAuth,
                                       switchCore,
                                       router,
                                       logger,
                                       eventBase,
                                       sp,
                                       rand,
                                       alloc);

    // ------------------- Register RPC functions ----------------------- //
    SwitchPinger_admin_register(sp, admin, alloc);
    UDPInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#ifdef HAS_ETH_INTERFACE
    ETHInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#endif
    RouterModule_admin_register(router, admin, alloc);
    AuthorizedPasswords_init(admin, cryptoAuth, alloc);
    Admin_registerFunction("ping", adminPing, admin, false, NULL, admin);
    Core_admin_register(myAddr, dt, logger, ipTun, alloc, admin, eventBase);
    Security_admin_register(alloc, logger, admin);
    IpTunnel_admin_register(ipTun, admin, alloc);

    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .allocator = alloc,
        .admin = admin,
        .logger = logger,
        .hermes = hermes
    }));
Esempio n. 4
0
/**
 * Input:
 * {
 *   "admin": {
 *     "core": "/path/to/core/binary",
 *     "bind": "127.0.0.1:12345",
 *     "pass": "******",
 *     "user": "******"
 *   }
 * }
 * for example:
 * d5:admind4:core30:./build/admin/angel/cjdns-core4:bind15:127.0.0.1:123454:pass4:abcdee
 *
 * Pre-existing core mode:
 * {
 *   "admin": {
 *     "core": {
 *       "fromCore": 12,
 *       "toCore": 14
 *     },
 *     "bind": "127.0.0.1:12345",
 *     "pass": "******",
 *     "user": "******"
 *   }
 * }
 *
 * If "core" is a dictionary, the angel will behave as though the core is already spawned and
 * it will read from the core on the file descriptor given by "fromCore" and write to the file
 * given by "toCore".
 *
 * "user" is optional, if set the angel will setuid() that user's uid.
 */
int AngelInit_main(int argc, char** argv)
{
    struct Except* eh = NULL;

    struct Allocator* alloc = MallocAllocator_new(1<<21);
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* logger = WriterLog_new(logWriter, alloc);
    struct Random* rand = Random_new(alloc, logger, eh);
    MallocAllocator_setCanary(alloc, (long)Random_int64(rand));
    struct Allocator* tempAlloc = Allocator_child(alloc);
    struct EventBase* eventBase = EventBase_new(alloc);

    struct Pipe* clientPipe = getClientPipe(argc, argv, eventBase, eh, alloc);
    clientPipe->logger = logger;

    Log_debug(logger, "Getting pre-configuration from client");

    struct Message* preConf = InterfaceWaiter_waitForData(&clientPipe->iface, eventBase, alloc, eh);

    Log_debug(logger, "Finished getting pre-configuration from client");

    struct Reader* reader = ArrayReader_new(preConf->bytes, preConf->length, tempAlloc);
    Dict config;
    if (StandardBencSerializer_get()->parseDictionary(reader, tempAlloc, &config)) {
        Except_raise(eh, -1, "Failed to parse configuration.");
    }

    Dict* admin = Dict_getDict(&config, String_CONST("admin"));
    String* core = Dict_getString(admin, String_CONST("core"));
    String* bind = Dict_getString(admin, String_CONST("bind"));
    String* pass = Dict_getString(admin, String_CONST("pass"));
    String* user = Dict_getString(admin, String_CONST("user"));
    String* corePipeName = Dict_getString(admin, String_CONST("corePipeName"));

    if (!bind || !pass || (!core && !corePipeName)) {
        Except_raise(eh, -1, "missing configuration params in preconfig. [%s]", preConf->bytes);
    }

    if (!corePipeName) {
        char name[32] = {0};
        Random_base32(rand, (uint8_t*)name, 31);
        corePipeName = String_new(name, tempAlloc);
    }

    struct Pipe* corePipe = Pipe_named(corePipeName->bytes, eventBase, eh, alloc);
    corePipe->logger = logger;
    corePipe->onClose = coreDied;
    struct Interface* coreIface = FramingInterface_new(65535, &corePipe->iface, alloc);

    if (core) {
        Log_info(logger, "Initializing core [%s]", core->bytes);
        initCore(core->bytes, corePipeName, eventBase, alloc, eh);
    }

    Log_debug(logger, "Sending pre-configuration to core.");


    sendConfToCore(coreIface, tempAlloc, &config, eh, logger);

    struct Message* coreResponse = InterfaceWaiter_waitForData(coreIface, eventBase, tempAlloc, eh);

    Interface_sendMessage(&clientPipe->iface, coreResponse);

    #ifdef Log_KEYS
        uint8_t lastChar = coreResponse->bytes[coreResponse->length-1];
        coreResponse->bytes[coreResponse->length-1] = 0;
        Log_keys(logger, "Sent [%s%c] to client.", coreResponse->bytes, lastChar);
        coreResponse->bytes[coreResponse->length-1] = lastChar;
    #endif

    if (user) {
        setUser(user->bytes, logger, eh);
    }

    Allocator_free(tempAlloc);
    Angel_start(coreIface, eventBase, logger, alloc);
    return 0;
}