Beispiel #1
0
/**
 * Send a search request to the next node in this search.
 * This is called whenever a response comes in or after the global mean response time passes.
 */
static void searchStep(struct SearchRunner_Search* search)
{
    struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner);

    struct Node_Two* node;
    struct SearchStore_Node* nextSearchNode;
    for (;;) {
        nextSearchNode = SearchStore_getNextNode(search->search);

        // If the number of requests sent has exceeded the max search requests, let's stop there.
        if (search->totalRequests >= MAX_REQUESTS_PER_SEARCH || nextSearchNode == NULL) {
            if (search->pub.callback) {
                search->pub.callback(&search->pub, 0, NULL, NULL);
            }
            Allocator_free(search->pub.alloc);
            return;
        }

        node = NodeStore_getBest(&nextSearchNode->address, ctx->nodeStore);

        if (!node) { continue; }
        if (node == ctx->nodeStore->selfNode) { continue; }
        if (Bits_memcmp(node->address.ip6.bytes, nextSearchNode->address.ip6.bytes, 16)) {
            continue;
        }

        break;
    }

    Assert_true(node != ctx->nodeStore->selfNode);

    Bits_memcpyConst(&search->lastNodeAsked, &node->address, sizeof(struct Address));

    struct RouterModule_Promise* rp =
        RouterModule_newMessage(&node->address, 0, ctx->router, search->pub.alloc);

    Dict* message = Dict_new(rp->alloc);
    Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc);
    Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc);

    rp->userData = search;
    rp->callback = searchCallback;

    RouterModule_sendMessage(rp, message);

    search->totalRequests++;
}
Beispiel #2
0
static void authorizedPasswords(List* list, struct Context* ctx)
{
    uint32_t count = List_size(list);
    for (uint32_t i = 0; i < count; i++) {
        Dict* d = List_getDict(list, i);
        Log_info(ctx->logger, "Checking authorized password %d.", i);
        if (!d) {
            Log_critical(ctx->logger, "Not a dictionary type %d.", i);
            exit(-1);
        }
        String* passwd = Dict_getString(d, String_CONST("password"));
        if (!passwd) {
            Log_critical(ctx->logger, "Must specify a password %d.", i);
            exit(-1);
        }
    }

    for (uint32_t i = 0; i < count; i++) {
        struct Allocator* child = Allocator_child(ctx->alloc);
        Dict* d = List_getDict(list, i);
        String* passwd = Dict_getString(d, String_CONST("password"));
        String* user = Dict_getString(d, String_CONST("user"));
        String* displayName = user;
        if (!displayName) {
            displayName = String_printf(child, "password [%d]", i);
        }
        //String* publicKey = Dict_getString(d, String_CONST("publicKey"));
        String* ipv6 = Dict_getString(d, String_CONST("ipv6"));
        Log_info(ctx->logger, "Adding authorized password #[%d] for user [%s].",
            i, displayName->bytes);
        Dict *args = Dict_new(child);
        uint32_t i = 1;
        Dict_putInt(args, String_CONST("authType"), i, child);
        Dict_putString(args, String_CONST("password"), passwd, child);
        if (user) {
            Dict_putString(args, String_CONST("user"), user, child);
        }
        Dict_putString(args, String_CONST("displayName"), displayName, child);
        if (ipv6) {
            Log_info(ctx->logger,
                "  This connection password restricted to [%s] only.", ipv6->bytes);
            Dict_putString(args, String_CONST("ipv6"), ipv6, child);
        }
        rpcCall(String_CONST("AuthorizedPasswords_add"), args, ctx, child);
        Allocator_free(child);
    }
}
Beispiel #3
0
/**
 * Send a search request to the next node in this search.
 * This is called whenever a response comes in or after the global mean response time passes.
 */
static void searchStep(struct SearchRunner_Search* search)
{
    struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner);

    struct SearchStore_Node* nextSearchNode;
    for (;;) {
        nextSearchNode = SearchStore_getNextNode(search->search);

        // If the number of requests sent has exceeded the max search requests, let's stop there.
        if (search->totalRequests >= search->maxRequests) {
            // fallthrough
        } else if (search->numFinds > 0 && search->totalRequests >= search->maxRequestsIfFound) {
            // fallthrough
        } else if (nextSearchNode == NULL) {
            // fallthrough
        } else {
            break;
        }
        if (search->pub.callback) {
            search->pub.callback(&search->pub, 0, NULL, NULL);
        }
        Allocator_free(search->pub.alloc);
        return;
    }

    Bits_memcpyConst(&search->lastNodeAsked, &nextSearchNode->address, sizeof(struct Address));

    struct RouterModule_Promise* rp =
        RouterModule_newMessage(&nextSearchNode->address, 0, ctx->router, search->pub.alloc);

    Dict* message = Dict_new(rp->alloc);

    if (!Bits_memcmp(nextSearchNode->address.ip6.bytes, search->target.ip6.bytes, 16)) {
        Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_GP, rp->alloc);
    } else {
        Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc);
    }
    Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc);

    rp->userData = search;
    rp->callback = searchCallback;

    RouterModule_sendMessage(rp, message);

    search->totalRequests++;
}
static Dict* serialize(void* vcontext)
{
    char* buffer = calloc(2048, 1);
    struct Allocator* allocator = BufferAllocator_new(buffer, 2048);
    Dict* out = Dict_new(allocator);
    Dict_putString(out, &hi, String_new((char*) vcontext, allocator), allocator);
    return out;
}
Dict* Security_getUser(char* userName, struct Allocator* retAlloc)
{
    Dict* ret = Dict_new(retAlloc);
    Dict_putString(ret, String_new("error", retAlloc),
                        String_new("Not supported on windows", retAlloc),
                        retAlloc);
    return ret;
}
Beispiel #6
0
static void sendMsg(struct MsgCore_pvt* mcp,
                    Dict* msgDict,
                    struct Address* addr,
                    struct Allocator* allocator)
{
    struct Allocator* alloc = Allocator_child(allocator);

    // Send the encoding scheme definition
    Dict_putString(msgDict, CJDHTConstants_ENC_SCHEME, mcp->schemeDefinition, allocator);

    // And tell the asker which interface the message came from
    int encIdx = EncodingScheme_getFormNum(mcp->scheme, addr->path);
    Assert_true(encIdx != EncodingScheme_getFormNum_INVALID);
    Dict_putInt(msgDict, CJDHTConstants_ENC_INDEX, encIdx, allocator);

    // send the protocol version
    Dict_putInt(msgDict, CJDHTConstants_PROTOCOL, Version_CURRENT_PROTOCOL, allocator);

    if (!Defined(SUBNODE)) {
        String* q = Dict_getStringC(msgDict, "q");
        String* sq = Dict_getStringC(msgDict, "sq");
        if (q || sq) {
            Log_debug(mcp->log, "Send query [%s] to [%s]",
                ((q) ? q->bytes : sq->bytes),
                Address_toString(addr, alloc)->bytes);
            String* txid = Dict_getStringC(msgDict, "txid");
            Assert_true(txid);
            String* newTxid = String_newBinary(NULL, txid->len + 1, alloc);
            Bits_memcpy(&newTxid->bytes[1], txid->bytes, txid->len);
            newTxid->bytes[0] = '1';
            Dict_putStringC(msgDict, "txid", newTxid, alloc);
        }
    }

    struct Message* msg = Message_new(0, 2048, alloc);
    BencMessageWriter_write(msgDict, msg, NULL);

    //Log_debug(mcp->log, "Sending msg [%s]", Escape_getEscaped(msg->bytes, msg->length, alloc));

    // Sanity check (make sure the addr was actually calculated)
    Assert_true(addr->ip6.bytes[0] == 0xfc);

    struct DataHeader data;
    Bits_memset(&data, 0, sizeof(struct DataHeader));
    DataHeader_setVersion(&data, DataHeader_CURRENT_VERSION);
    DataHeader_setContentType(&data, ContentType_CJDHT);
    Message_push(msg, &data, sizeof(struct DataHeader), NULL);

    struct RouteHeader route;
    Bits_memset(&route, 0, sizeof(struct RouteHeader));
    Bits_memcpy(route.ip6, addr->ip6.bytes, 16);
    route.version_be = Endian_hostToBigEndian32(addr->protocolVersion);
    route.sh.label_be = Endian_hostToBigEndian64(addr->path);
    Bits_memcpy(route.publicKey, addr->key, 32);
    Message_push(msg, &route, sizeof(struct RouteHeader), NULL);

    Iface_send(&mcp->pub.interRouterIf, msg);
}
Beispiel #7
0
static void sendResponse(String* error,
                         struct Admin* admin,
                         String* txid,
                         struct Allocator* tempAlloc)
{
    Dict* output = Dict_new(tempAlloc);
    Dict_putString(output, String_CONST("error"), error, tempAlloc);
    Admin_sendMessage(output, txid, admin);
}
static void sendResponse(String* msg, struct Admin* admin, String* txid)
{
    #define BUFFERSZ 1024
    uint8_t buffer[BUFFERSZ];
    struct Allocator* alloc = BufferAllocator_new(buffer, BUFFERSZ);
    Dict* output = Dict_new(alloc);
    Dict_putString(output, String_CONST("error"), msg, alloc);
    Admin_sendMessage(output, txid, admin);
}
Beispiel #9
0
static void getRouteLabel(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* ctx = Identity_check((struct Context*) vcontext);

    char* err = NULL;

    String* pathToParentS = Dict_getString(args, String_CONST("pathToParent"));
    uint64_t pathToParent = 0;
    if (pathToParentS->len != 19 || AddrTools_parsePath(&pathToParent, pathToParentS->bytes)) {
        err = "parse_pathToParent";
    }

    String* pathParentToChildS = Dict_getString(args, String_CONST("pathParentToChild"));
    uint64_t pathParentToChild = 0;
    if (pathParentToChildS->len != 19
        || AddrTools_parsePath(&pathParentToChild, pathParentToChildS->bytes))
    {
        err = "parse_pathParentToChild";
    }

    uint64_t label = UINT64_MAX;
    if (!err) {
        label = NodeStore_getRouteLabel(ctx->store, pathToParent, pathParentToChild);
        err = NodeStore_getRouteLabel_strerror(label);
    }
    Dict* response = Dict_new(requestAlloc);
    if (!err) {
        String* printedPath = String_newBinary(NULL, 19, requestAlloc);
        AddrTools_printPath(printedPath->bytes, label);
        Dict_putString(response, String_new("result", requestAlloc), printedPath, requestAlloc);
        Dict_putString(response,
                       String_new("error", requestAlloc),
                       String_new("none", requestAlloc),
                       requestAlloc);
        Admin_sendMessage(response, txid, ctx->admin);
    } else {
        Dict_putString(response,
                       String_new("error", requestAlloc),
                       String_new(err, requestAlloc),
                       requestAlloc);
        Admin_sendMessage(response, txid, ctx->admin);
    }
}
Beispiel #10
0
static void addRemoveSomething(Dict* args,
                               void* vcontext,
                               String* txid,
                               struct Allocator* requestAlloc,
                               enum addRemoveSomething_What what)
{
    struct RouteGen_admin_Ctx* ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
    String* route = Dict_getString(args, String_CONST("route"));
    char* error = NULL;

    struct Sockaddr_storage ss;
    if (route->len > 63) {
        error = "parse_failed";
    }
    if (!error) {
        if (Sockaddr_parse(route->bytes, &ss)) {
            error = "parse_failed";
        } else {
            int family = Sockaddr_getFamily(&ss.addr);
            if (family != Sockaddr_AF_INET && family != Sockaddr_AF_INET6) {
                error = "unexpected_af";
            }
        }
    }
    int retVal = -1;
    Dict* out = Dict_new(requestAlloc);
    if (!error) {
        switch (what) {
            case addRemoveSomething_What_ADD_EXCEPTION:
                RouteGen_addException(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_ADD_PREFIX:
                RouteGen_addPrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_ADD_LOCALPREFIX:
                RouteGen_addLocalPrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_EXCEPTION:
                retVal = RouteGen_removeException(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_PREFIX:
                retVal = RouteGen_removePrefix(ctx->rg, &ss.addr); break;
            case addRemoveSomething_What_RM_LOCALPREFIX:
                retVal = RouteGen_removeLocalPrefix(ctx->rg, &ss.addr); break;
            default: Assert_failure("invalid op");
        }
        if (!retVal) {
            error = "no_such_route";
        } else {
            error = "none";
        }
    }
    Dict_putString(out,
                   String_new("error", requestAlloc),
                   String_new(error, requestAlloc),
                   requestAlloc);
    Admin_sendMessage(out, txid, ctx->admin);
}
Beispiel #11
0
static void adminPing(Dict* input, void* vadmin, String* txid)
{
    uint8_t buffer[256];
    struct Allocator* alloc = BufferAllocator_new(buffer, 256);

    String* pong = BSTR("pong");
    Dict* d = Dict_new(alloc);
    Dict_putString(d, CJDHTConstants_QUERY, pong, alloc);

    Admin_sendMessage(d, txid, (struct Admin*) vadmin);
}
Beispiel #12
0
/** @return a string representing the address and port to connect to. */
static void initAngel(struct Pipe* asClientPipe,
                      struct Interface* asCoreIface,
                      char* asCorePipeName,
                      struct EventBase* eventBase,
                      struct Log* logger,
                      struct Allocator* alloc,
                      struct Random* rand)
{
    Dict admin = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST(
        String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), Dict_CONST(
        String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL
    )));
    Dict message = Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&admin), NULL
    );

    struct Allocator* tempAlloc = Allocator_child(alloc);

    struct Message* toAngel = Message_new(0, 1024, tempAlloc);
    BencMessageWriter_write(&message, toAngel, NULL);

    Log_info(logger, "Writing intial configuration to angel on [%s]", asClientPipe->name);
    Interface_sendMessage(&asClientPipe->iface, toAngel);

    // This is client->angel->core data, we can throw this away.
    //struct Message* angelToCore =
    InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL);

    // unterminated string
    //Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes);

    // Send response on behalf of core.
    Dict* coreToAngelResp = Dict_new(tempAlloc);
    Dict_putString(coreToAngelResp, String_CONST("error"), String_CONST("none"), tempAlloc);
    struct Message* coreToAngelMsg = Message_new(0, 256, tempAlloc);
    BencMessageWriter_write(coreToAngelResp, coreToAngelMsg, NULL);
    Interface_sendMessage(asCoreIface, coreToAngelMsg);

    // This is angel->client data, it will tell us which port was bound.
    struct Message* angelToClient =
        InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL);

    uint8_t lastByte = angelToClient->bytes[angelToClient->length-1];
    angelToClient->bytes[angelToClient->length-1] = '\0';
    printf("Response from angel to client: [%s%c]\n", angelToClient->bytes, (char)lastByte);

    Allocator_free(tempAlloc);

    return;
}
Beispiel #13
0
static void udpInterface(Dict* config, struct Context* ctx)
{
    Dict* udp = Dict_getDict(config, String_CONST("UDPInterface"));

    if (udp) {
        // Setup the interface.
        String* bindStr = Dict_getString(udp, String_CONST("bind"));
        Dict* d = Dict_new(ctx->alloc);
        if (bindStr) {
            Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
        }
        rpcCall(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc);

        // Make the connections.
        Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
        if (connectTo) {
            struct Dict_Entry* entry = *connectTo;
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);

                struct Allocator* perCallAlloc = ctx->alloc->child(ctx->alloc);
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
                perCallAlloc->free(perCallAlloc);

                entry = entry->next;
            }
        }
    }
}
Beispiel #14
0
static void showConn(struct IpTunnel_Connection* conn, String* txid, struct Admin* admin)
{
    struct Allocator* alloc;
    BufferAllocator_STACK(alloc, 1024);
    Dict* d = Dict_new(alloc);

    char ip6[40];
    if (!Bits_isZero(conn->connectionIp6, 16)) {
        Assert_always(evutil_inet_ntop(AF_INET6, conn->connectionIp6, ip6, 40));
        Dict_putString(d, String_CONST("ip6Address"), String_CONST(ip6), alloc);
    }

    char ip4[16];
    if (!Bits_isZero(conn->connectionIp4, 4)) {
        Assert_always(evutil_inet_ntop(AF_INET, conn->connectionIp4, ip4, 16));
        Dict_putString(d, String_CONST("ip4Address"), String_CONST(ip4), alloc);
    }

    Dict_putString(d, String_CONST("key"), Key_stringify(conn->header.nodeKey, alloc), alloc);
    Dict_putInt(d, String_CONST("outgoing"), conn->isOutgoing, alloc);

    Admin_sendMessage(d, txid, admin);
}
static void checkPermissionsB(struct Except* eh,
                              String* txid,
                              struct Admin* admin,
                              struct Allocator* requestAlloc)
{
    struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh);
    Dict* out = Dict_new(requestAlloc);
    Dict_putInt(out, String_CONST("noOpenFiles"), sp->noOpenFiles, requestAlloc);
    Dict_putInt(out, String_CONST("seccompExists"), sp->seccompExists, requestAlloc);
    Dict_putInt(out, String_CONST("seccompEnforcing"), sp->seccompEnforcing, requestAlloc);
    Dict_putInt(out, String_CONST("userId"), sp->uid, requestAlloc);
    Dict_putString(out, String_CONST("error"), String_CONST("none"), requestAlloc);
    Admin_sendMessage(out, txid, admin);
}
Beispiel #16
0
void Admin_registerFunctionWithArgCount(char* name,
                                        Admin_FUNCTION(callback),
                                        void* callbackContext,
                                        bool needsAuth,
                                        struct Admin_FunctionArg* arguments,
                                        int argCount,
                                        struct Admin* admin)
{
    if (!admin) {
        return;
    }
    String* str = String_new(name, admin->allocator);
    if (!admin->functionCount) {
        admin->functions = admin->allocator->malloc(sizeof(struct Function), admin->allocator);
    } else {
        admin->functions =
            admin->allocator->realloc(admin->functions,
                                      sizeof(struct Function) * (admin->functionCount + 1),
                                      admin->allocator);
    }
    struct Function* fu = &admin->functions[admin->functionCount];
    admin->functionCount++;

    fu->name = str;
    fu->call = callback;
    fu->context = callbackContext;
    fu->needsAuth = needsAuth;
    fu->args = Dict_new(admin->allocator);
    for (int i = 0; arguments && i < argCount; i++) {
        // "type" must be one of: [ "String", "Int", "Dict", "List" ]
        String* type = NULL;
        if (!strcmp(arguments[i].type, STRING->bytes)) {
            type = STRING;
        } else if (!strcmp(arguments[i].type, INT->bytes)) {
            type = INT;
        } else if (!strcmp(arguments[i].type, DICT->bytes)) {
            type = DICT;
        } else if (!strcmp(arguments[i].type, LIST->bytes)) {
            type = LIST;
        } else {
            abort();
        }
        Dict* arg = Dict_new(admin->allocator);
        Dict_putString(arg, TYPE, type, admin->allocator);
        Dict_putInt(arg, REQUIRED, arguments[i].required, admin->allocator);
        String* name = String_new(arguments[i].name, admin->allocator);
        Dict_putDict(fu->args, name, arg, admin->allocator);
    }
}
Beispiel #17
0
static void pingResponse(struct RouterModule_Promise* promise,
                         uint32_t lag,
                         struct Address* from,
                         Dict* responseDict)
{
    struct Ping* ping = Identity_check((struct Ping*)promise->userData);
    struct Allocator* tempAlloc = promise->alloc;
    Dict* resp = Dict_new(tempAlloc);

    String* versionBin = Dict_getString(responseDict, CJDHTConstants_VERSION);
    if (versionBin && versionBin->len == 20) {
        String* versionStr = String_newBinary(NULL, 40, tempAlloc);
        Hex_encode(versionStr->bytes, 40, versionBin->bytes, 20);
        Dict_putString(resp, String_CONST("version"), versionStr, tempAlloc);
    } else {
        Dict_putString(resp, String_CONST("version"), String_CONST("unknown"), tempAlloc);
    }

    String* result = (responseDict) ? String_CONST("pong") : String_CONST("timeout");
    Dict_putString(resp, String_CONST("result"), result, tempAlloc);

    int64_t* protocolVersion = Dict_getInt(responseDict, CJDHTConstants_PROTOCOL);
    if (protocolVersion) {
        Dict_putInt(resp, String_CONST("protocol"), *protocolVersion, tempAlloc);
    }

    Dict_putInt(resp, String_CONST("ms"), lag, tempAlloc);

    if (from) {
        uint8_t fromStr[60] = "";
        Address_print(fromStr, from);
        Dict_putString(resp, String_CONST("from"), String_new(fromStr, tempAlloc), tempAlloc);
    }

    Admin_sendMessage(resp, ping->txid, ping->ctx->admin);
}
static void listConnections(Dict* args,
                            void* vcontext,
                            String* txid,
                            struct Allocator* alloc)
{
    struct Context* context = vcontext;
    List* l = List_new(alloc);
    for (int i = 0; i < (int)context->ipTun->connectionList.count; i++) {
        List_addInt(l, context->ipTun->connectionList.connections[i].number, alloc);
    }
    Dict* resp = Dict_new(alloc);
    Dict_putList(resp, String_CONST("connections"), l, alloc);
    Dict_putString(resp, String_CONST("error"), String_CONST("none"), alloc);
    Admin_sendMessage(resp, txid, context->admin);
}
Beispiel #19
0
static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    String* ifaceType = Dict_getString(ifaceConf, String_CONST("type"));
    if (!String_equals(ifaceType, String_CONST("TUNInterface"))) {
        return;
    }

    // Setup the interface.
    String* device = Dict_getString(ifaceConf, String_CONST("tunDevice"));

    Dict* args = Dict_new(tempAlloc);
    if (device) {
        Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc);
    }
    rpcCall0(String_CONST("Core_initTunnel"), args, ctx, tempAlloc, false);
}
Beispiel #20
0
static void sessionStats(Dict* args,
                         void* vcontext,
                         String* txid,
                         struct Allocator* alloc)
{
    struct Context* context = Identity_check((struct Context*) vcontext);
    int64_t* handleP = Dict_getInt(args, String_CONST("handle"));
    uint32_t handle = *handleP;

    struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm);

    Dict* r = Dict_new(alloc);
    if (!session) {
        Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc);
        Admin_sendMessage(r, txid, context->admin);
        return;
    }

    uint8_t printedAddr[40];
    AddrTools_printIp(printedAddr, session->caSession->herIp6);
    Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc);

    String* state =
        String_new(CryptoAuth_stateString(CryptoAuth_getState(session->caSession)), alloc);
    Dict_putString(r, String_CONST("state"), state, alloc);

    struct ReplayProtector* rp = &session->caSession->replayProtector;
    Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc);
    Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc);
    Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc);

    struct Address addr;
    Bits_memcpyConst(addr.key, session->caSession->herPublicKey, 32);
    addr.path = session->sendSwitchLabel;
    addr.protocolVersion = session->version;

    Dict_putString(r, String_CONST("addr"), Address_toString(&addr, alloc), alloc);

    Dict_putString(r, String_CONST("publicKey"),
                      Key_stringify(session->caSession->herPublicKey, alloc), alloc);
    Dict_putInt(r, String_CONST("version"), session->version, alloc);
    Dict_putInt(r, String_CONST("handle"), session->receiveHandle, alloc);
    Dict_putInt(r, String_CONST("sendHandle"), session->sendHandle, alloc);

    Dict_putInt(r, String_CONST("timeOfLastIn"), session->timeOfLastIn, alloc);
    Dict_putInt(r, String_CONST("timeOfLastOut"), session->timeOfLastOut, alloc);

    Dict_putString(r, String_CONST("deprecation"),
        String_CONST("publicKey,version will soon be removed"), alloc);

    Admin_sendMessage(r, txid, context->admin);
    return;
}
Beispiel #21
0
static void minSinatures(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc)
{
    struct Context* context = vcontext;
    struct Allocator* alloc = Allocator_child(context->alloc);
    int64_t* count = Dict_getInt(args, String_CONST("count"));
    char* err = "none";
    if (*count < 0 || *count > INT32_MAX) {
        err = "count cannot be less than zero or more than INT32_MAX";
    } else {
        context->rainfly->minSignatures = *count;
    }

    Dict* response = Dict_new(alloc);
    Dict_putString(response, String_CONST("error"), String_CONST(err), alloc);

    Admin_sendMessage(response, txid, context->admin);

    Allocator_free(alloc);
}
Beispiel #22
0
List* EncodingScheme_asList(struct EncodingScheme* list, struct Allocator* alloc)
{
    Assert_true(EncodingScheme_isSane(list));
    String* prefixLen = String_new("prefixLen", alloc);
    String* bitCount = String_new("bitCount", alloc);
    String* prefix = String_new("prefix", alloc);
    List* scheme = NULL;
    for (int i = 0; i < (int)list->count; i++) {
        Dict* form = Dict_new(alloc);
        Dict_putInt(form, prefixLen, list->forms[i].prefixLen, alloc);
        Dict_putInt(form, bitCount, list->forms[i].bitCount, alloc);
        String* pfx = String_newBinary(NULL, 8, alloc);
        uint32_t prefix_be = Endian_hostToBigEndian32(list->forms[i].prefix);
        Hex_encode(pfx->bytes, 8, (uint8_t*)&prefix_be, 4);
        Dict_putString(form, prefix, pfx, alloc);
        scheme = List_addDict(scheme, form, alloc);
    }
    return scheme;
}
Beispiel #23
0
static void commit(Dict* args,
                   void* vcontext,
                   String* txid,
                   struct Allocator* requestAlloc)
{
    struct RouteGen_admin_Ctx* const ctx = Identity_check((struct RouteGen_admin_Ctx*) vcontext);
    String* const tunName = Dict_getString(args, String_CONST("tunName"));
    Dict* const ret = Dict_new(requestAlloc);
    char* error = "none";
    struct Jmp j;
    Jmp_try(j) {
        RouteGen_commit(ctx->rg, tunName->bytes, requestAlloc, &j.handler);
    } Jmp_catch {
        error = j.message;
    }
    Dict_putString(ret,
                   String_new("error", requestAlloc),
                   String_new(error, requestAlloc),
                   requestAlloc);
    Admin_sendMessage(ret, txid, ctx->admin);
}
Beispiel #24
0
static void udpInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);
    for (uint32_t i = 0; i < count; i++) {
        Dict *udp = List_getDict(ifaces, i);
        if (!udp) {
            continue;
        }
        // Setup the interface.
        String* bindStr = Dict_getString(udp, String_CONST("bind"));
        Dict* d = Dict_new(ctx->alloc);
        if (bindStr) {
            Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
        }
        Dict* resp = NULL;
        rpcCall0(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc, &resp, true);
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));

        // Make the connections.
        Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
        if (connectTo) {
            struct Dict_Entry* entry = *connectTo;
            struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* all =  entry->val->as.dictionary;
                Dict* value = Dict_new(perCallAlloc);
                String* pub_d = Dict_getString(all, String_CONST("publicKey"));
                String* pss_d = Dict_getString(all, String_CONST("password"));
                String* peerName_d = Dict_getString(all, String_CONST("peerName"));
                String* login_d = Dict_getString(all, String_CONST("login"));

                if ( !pub_d || !pss_d ) {
                    const char * error_name = "(unknown)";
                    if ( !pub_d ) {
                        error_name = "publicKey";
                    }
                    if ( !pss_d ) {
                        error_name = "password";
                    }
                    Log_warn(ctx->logger,
                        "Skipping peer: missing %s for peer [%s]", error_name, key->bytes);
                    if (abort_if_invalid_ref) {
                        Assert_failure("Invalid peer reference");
                    }
                    else {
                        entry = entry->next;
                        continue;
                    }
                }

                Dict_putString(value, String_CONST("publicKey"), pub_d, perCallAlloc);
                Dict_putString(value, String_CONST("password"), pss_d, perCallAlloc);
                Dict_putString(value, String_CONST("peerName"), peerName_d, perCallAlloc);
                Dict_putString(value, String_CONST("login"), login_d, perCallAlloc);

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
                key = String_clone(key, perCallAlloc);
                char* lastColon = CString_strrchr(key->bytes, ':');

                if (!Sockaddr_parse(key->bytes, NULL)) {
                    // it's a sockaddr, fall through
                } else if (lastColon) {
                    // try it as a hostname.
                    int port = atoi(lastColon+1);
                    if (!port) {
                        Log_critical(ctx->logger, "Couldn't get port number from [%s]", key->bytes);
                        exit(-1);
                    }
                    *lastColon = '\0';
                    struct Sockaddr* adr = Sockaddr_fromName(key->bytes, perCallAlloc);
                    if (adr != NULL) {
                        Sockaddr_setPort(adr, port);
                        key = String_new(Sockaddr_print(adr, perCallAlloc), perCallAlloc);
                    } else {
                        Log_warn(ctx->logger, "Failed to lookup hostname [%s]", key->bytes);
                        entry = entry->next;
                        continue;
                    }
                }
                struct Allocator* child = Allocator_child(ctx->alloc);
                struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE + 256, child);
                int r = BencMessageWriter_writeDictTry(value, msg, NULL);

                const int max_reference_size = 298;
                if (r != 0 || msg->length > max_reference_size) {
                    Log_warn(ctx->logger, "Peer skipped:");
                    Log_warn(ctx->logger, "Too long peer reference for [%s]", key->bytes);
                    if (abort_if_invalid_ref) {
                        Assert_failure("Invalid peer reference");
                    }
                    else {
                        entry = entry->next;
                        continue;
                    }
                }
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                Dict_putString(value, String_CONST("address"), key, perCallAlloc);
                rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
                entry = entry->next;
            }
            Allocator_free(perCallAlloc);
        }
    }
}
static void adminPeerStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc)
{
    struct Context* context = Identity_check((struct Context*)vcontext);
    struct InterfaceController_PeerStats* stats = NULL;

    int64_t* page = Dict_getInt(args, String_CONST("page"));
    int i = (page) ? *page * ENTRIES_PER_PAGE : 0;

    int count = InterfaceController_getPeerStats(context->ic, alloc, &stats);

    String* bytesIn = String_CONST("bytesIn");
    String* bytesOut = String_CONST("bytesOut");
    String* pubKey = String_CONST("publicKey");
    String* addr = String_CONST("addr");
    String* state = String_CONST("state");
    String* last = String_CONST("last");
    String* switchLabel = String_CONST("switchLabel");
    String* isIncoming = String_CONST("isIncoming");
    String* user = String_CONST("user");
    String* version = String_CONST("version");

    String* duplicates = String_CONST("duplicates");
    String* lostPackets = String_CONST("lostPackets");
    String* receivedOutOfRange = String_CONST("receivedOutOfRange");

    List* list = List_new(alloc);
    for (int counter=0; i < count && counter++ < ENTRIES_PER_PAGE; i++) {
        Dict* d = Dict_new(alloc);
        Dict_putInt(d, bytesIn, stats[i].bytesIn, alloc);
        Dict_putInt(d, bytesOut, stats[i].bytesOut, alloc);
        Dict_putString(d, addr, Address_toString(&stats[i].addr, alloc), alloc);
        Dict_putString(d, pubKey, Key_stringify(stats[i].addr.key, alloc), alloc);

        String* stateString = String_new(InterfaceController_stateString(stats[i].state), alloc);
        Dict_putString(d, state, stateString, alloc);

        Dict_putInt(d, last, stats[i].timeOfLastMessage, alloc);

        uint8_t labelStack[20];
        AddrTools_printPath(labelStack, stats[i].addr.path);
        Dict_putString(d, switchLabel, String_new((char*)labelStack, alloc), alloc);

        Dict_putInt(d, isIncoming, stats[i].isIncomingConnection, alloc);
        Dict_putInt(d, duplicates, stats[i].duplicates, alloc);
        Dict_putInt(d, lostPackets, stats[i].lostPackets, alloc);
        Dict_putInt(d, receivedOutOfRange, stats[i].receivedOutOfRange, alloc);

        if (stats[i].user) {
            Dict_putString(d, user, stats[i].user, alloc);
        }

        uint8_t address[16];
        AddressCalc_addressForPublicKey(address, stats[i].addr.key);
        Dict_putInt(d, version, stats[i].addr.protocolVersion, alloc);

        List_addDict(list, d, alloc);
    }

    Dict* resp = Dict_new(alloc);
    Dict_putList(resp, String_CONST("peers"), list, alloc);
    Dict_putInt(resp, String_CONST("total"), count, alloc);

    if (i < count) {
        Dict_putInt(resp, String_CONST("more"), 1, alloc);
    }

    Dict_putString(resp, String_CONST("deprecation"),
        String_CONST("publicKey,switchLabel,version will soon be removed"), alloc);

    Admin_sendMessage(resp, txid, context->admin);
}
Beispiel #26
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;
}
Beispiel #27
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

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

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

    if (argc == 2) {
        // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf(rand);
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if (strcmp(argv[1], "--version") == 0) {
            //printf("Version ID: %s\n", RouterModule_gitVersion());
            return 0;
        } 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\n", argv[0]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        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(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;
    }

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

    // --------------------- Setup Pipes to Angel --------------------- //
    int pipeToAngel[2];
    int pipeFromAngel[2];
    if (Pipe_createUniPipe(pipeToAngel) || Pipe_createUniPipe(pipeFromAngel)) {
        Except_raise(eh, -1, "Failed to create pipes to angel [%s]", Errno_getString());
    }

    char pipeToAngelStr[8];
    snprintf(pipeToAngelStr, 8, "%d", pipeToAngel[0]);
    char pipeFromAngelStr[8];
    snprintf(pipeFromAngelStr, 8, "%d", pipeFromAngel[1]);
    char* args[] = { "angel", pipeToAngelStr, pipeFromAngelStr, NULL };

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

    String* corePath = getCorePath(allocator);
    if (!corePath) {
        Except_raise(eh, -1, "Can't find a usable cjdns core executable, "
                             "make sure it is in the same directory as cjdroute");
    }

    if (!privateKey) {
        Except_raise(eh, -1, "Need to specify privateKey.");
    }
    Log_info(logger, "Forking angel to background.");
    Process_spawn(corePath->bytes, args);

    // --------------------- 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 = strlen(adminPass->bytes);
    }
    if (!adminBind) {
        adminBind = String_new("127.0.0.1:0", allocator);
    }

    // --------------------- Get user for angel to setuid() ---------------------- //
    String* securityUser = NULL;
    List* securityConf = Dict_getList(&config, String_CONST("security"));
    for (int i = 0; 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"), corePath, 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);
    }

    #define CONFIG_BUFF_SIZE 1024
    uint8_t buff[CONFIG_BUFF_SIZE] = {0};
    struct Writer* toAngelWriter = ArrayWriter_new(buff, CONFIG_BUFF_SIZE - 1, allocator);
    if (StandardBencSerializer_get()->serializeDictionary(toAngelWriter, preConf)) {
        Except_raise(eh, -1, "Failed to serialize pre-configuration");
    }
    write(pipeToAngel[1], buff, toAngelWriter->bytesWritten(toAngelWriter));
    Log_keys(logger, "Sent [%s] to angel process.", buff);

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

    uint32_t amount = Waiter_getData(buff, CONFIG_BUFF_SIZE, pipeFromAngel[0], eventBase, eh);
    Dict responseFromAngel;
    struct Reader* responseFromAngelReader = ArrayReader_new(buff, amount, allocator);
    if (StandardBencSerializer_get()->parseDictionary(responseFromAngelReader,
                                                      allocator,
                                                      &responseFromAngel))
    {
        Except_raise(eh, -1, "Failed to parse pre-configuration response [%s]", buff);
    }

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

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

    // sanity check
    Assert_true(EventBase_eventCount(eventBase) == 0);

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

    return 0;
}
Beispiel #28
0
static void ipTunnel(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
{
    List* incoming = Dict_getList(ifaceConf, String_CONST("allowedConnections"));
    if (incoming) {
        Dict* d;
        for (int i = 0; (d = List_getDict(incoming, i)) != NULL; i++) {
            String* key = Dict_getString(d, String_CONST("publicKey"));
            String* ip4 = Dict_getString(d, String_CONST("ip4Address"));
            // Note that the prefix length has to be a proper int in the config
            // (not quoted!)
            int64_t* ip4Prefix = Dict_getInt(d, String_CONST("ip4Prefix"));
            String* ip6 = Dict_getString(d, String_CONST("ip6Address"));
            int64_t* ip6Prefix = Dict_getInt(d, String_CONST("ip6Prefix"));
            if (!key) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'publicKey' required.", i);
                exit(1);
            }
            if (!ip4 && !ip6) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "either 'ip4Address' or 'ip6Address' required.", i);
                exit(1);
            } else if (ip4Prefix && !ip4) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'ip4Address' required with 'ip4Prefix'.", i);
                exit(1);
            } else if (ip6Prefix && !ip6) {
                Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
                                          "'ip6Address' required with 'ip6Prefix'.", i);
                exit(1);
            }
            Log_debug(ctx->logger, "Allowing IpTunnel connections from [%s]", key->bytes);

            if (ip4) {
                Log_debug(ctx->logger, "Issue IPv4 address %s", ip4->bytes);
                if (ip4Prefix) {
                    Log_debug(ctx->logger, "Issue IPv4 netmask/prefix length /%d",
                        (int) *ip4Prefix);
                } else {
                    Log_debug(ctx->logger, "Use default netmask/prefix length /0");
                }
            }

            if (ip6) {
                Log_debug(ctx->logger, "Issue IPv6 address [%s]", ip6->bytes);
                if (ip6Prefix) {
                    Log_debug(ctx->logger, "Issue IPv6 netmask/prefix length /%d",
                        (int) *ip6Prefix);
                } else {
                    Log_debug(ctx->logger, "Use default netmask/prefix length /0");
                }
            }

            Dict_putString(d, String_CONST("publicKeyOfAuthorizedNode"), key, tempAlloc);
            rpcCall0(String_CONST("IpTunnel_allowConnection"), d, ctx, tempAlloc, NULL, true);
        }
    }

    List* outgoing = Dict_getList(ifaceConf, String_CONST("outgoingConnections"));
    if (outgoing) {
        String* s;
        for (int i = 0; (s = List_getString(outgoing, i)) != NULL; i++) {
            Log_debug(ctx->logger, "Initiating IpTunnel connection to [%s]", s->bytes);
            Dict requestDict =
                Dict_CONST(String_CONST("publicKeyOfNodeToConnectTo"), String_OBJ(s), NULL);
            rpcCall0(String_CONST("IpTunnel_connectTo"), &requestDict, ctx, tempAlloc, NULL, true);
        }
    }
}
Beispiel #29
0
static void ethInterface(Dict* config, struct Context* ctx)
{
    List* ifaces = Dict_getList(config, String_CONST("ETHInterface"));
    if (!ifaces) {
        ifaces = List_new(ctx->alloc);
        List_addDict(ifaces, Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc);
    }

    uint32_t count = List_size(ifaces);

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        if (!deviceStr || !String_equals(String_CONST("all"), deviceStr)) { continue; }
        Log_info(ctx->logger, "Setting up all ETHInterfaces...");
        Dict* res = NULL;
        Dict* d = Dict_new(ctx->alloc);
        if (rpcCall0(String_CONST("ETHInterface_listDevices"), d, ctx, ctx->alloc, &res, false)) {
            Log_info(ctx->logger, "Getting device list failed");
            break;
        }
        List* devs = Dict_getList(res, String_CONST("devices"));
        uint32_t devCount = List_size(devs);
        for (uint32_t j = 0; j < devCount; j++) {
            Dict* d = Dict_new(ctx->alloc);
            String* deviceName = List_getString(devs, j);
            // skip loopback...
            if (String_equals(String_CONST("lo"), deviceName)) { continue; }
            Dict_putString(d, String_CONST("bindDevice"), deviceName, ctx->alloc);
            Dict* resp;
            Log_info(ctx->logger, "Creating new ETHInterface [%s]", deviceName->bytes);
            if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
                Log_warn(ctx->logger, "Failed to create ETHInterface.");
                continue;
            }
            int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
            ethInterfaceSetBeacon(ifNum, eth, ctx);
        }
        return;
    }

    for (uint32_t i = 0; i < count; i++) {
        Dict *eth = List_getDict(ifaces, i);
        if (!eth) { continue; }
        // Setup the interface.
        String* deviceStr = Dict_getString(eth, String_CONST("bind"));
        Log_info(ctx->logger, "Setting up ETHInterface [%d].", i);
        Dict* d = Dict_new(ctx->alloc);
        if (deviceStr) {
            Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes);
            Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc);
        }
        Dict* resp = NULL;
        if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, &resp, false)) {
            Log_warn(ctx->logger, "Failed to create ETHInterface.");
            continue;
        }
        int ifNum = *(Dict_getInt(resp, String_CONST("interfaceNumber")));
        ethInterfaceSetBeacon(ifNum, eth, ctx);

        // Make the connections.
        Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo"));
        if (connectTo) {
            Log_info(ctx->logger, "ETHInterface should connect to a specific node.");
            struct Dict_Entry* entry = *connectTo;
            while (entry != NULL) {
                String* key = (String*) entry->key;
                if (entry->val->type != Object_DICT) {
                    Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] "
                                               "is not a dictionary type.", key->bytes);
                    exit(-1);
                }
                Dict* value = entry->val->as.dictionary;

                Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);

                struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
                // Turn the dict from the config into our RPC args dict by filling in all
                // the arguments,
                Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc);
                Dict_putInt(value, String_CONST("interfaceNumber"), ifNum, perCallAlloc);
                rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc);
                Allocator_free(perCallAlloc);

                entry = entry->next;
            }
        }
    }
}
Beispiel #30
0
static void security(struct Allocator* tempAlloc, List* conf, struct Log* log, struct Context* ctx)
{
    int seccomp = 1;
    int nofiles = 0;
    int noforks = 1;
    int chroot = 1;
    int setupComplete = 1;
    int setuser = 1;
    if (Defined(win32)) {
        setuser = 0;
    }

    int uid = -1;
    int64_t* group = NULL;
    int keepNetAdmin = 1;

    do {
        Dict* d = Dict_new(tempAlloc);
        Dict_putString(d, String_CONST("user"), String_CONST("nobody"), tempAlloc);
        if (!Defined(win32)) {
            Dict* ret = NULL;
            rpcCall0(String_CONST("Security_getUser"), d, ctx, tempAlloc, &ret, true);
            uid = *Dict_getInt(ret, String_CONST("uid"));
            group = Dict_getInt(ret, String_CONST("gid"));
        }
    } while (0);

    for (int i = 0; conf && i < List_size(conf); i++) {
        Dict* elem = List_getDict(conf, i);
        String* s;
        if (elem && (s = Dict_getString(elem, String_CONST("setuser")))) {
            if (setuser == 0) { continue; }
            Dict* d = Dict_new(tempAlloc);
            Dict_putString(d, String_CONST("user"), s, tempAlloc);
            Dict* ret = NULL;
            rpcCall0(String_CONST("Security_getUser"), d, ctx, tempAlloc, &ret, true);
            uid = *Dict_getInt(ret, String_CONST("uid"));
            group = Dict_getInt(ret, String_CONST("gid"));
            int64_t* nka = Dict_getInt(elem, String_CONST("keepNetAdmin"));
            int64_t* exemptAngel = Dict_getInt(elem, String_CONST("exemptAngel"));
            keepNetAdmin = ((nka) ? *nka : ((exemptAngel) ? *exemptAngel : 0));
            continue;
        }
        if (elem && (s = Dict_getString(elem, String_CONST("chroot")))) {
            Log_debug(log, "Security_chroot(%s)", s->bytes);
            Dict* d = Dict_new(tempAlloc);
            Dict_putString(d, String_CONST("root"), s, tempAlloc);
            rpcCall0(String_CONST("Security_chroot"), d, ctx, tempAlloc, NULL, false);
            chroot = 0;
            continue;
        }
        uint64_t* x;
        if (elem && (x = Dict_getInt(elem, String_CONST("nofiles")))) {
            if (!*x) { continue; }
            nofiles = 1;
            continue;
        }
        if (elem && (x = Dict_getInt(elem, String_CONST("setuser")))) {
            if (!*x) { setuser = 0; }
            continue;
        }
        if (elem && (x = Dict_getInt(elem, String_CONST("seccomp")))) {
            if (!*x) { seccomp = 0; }
            continue;
        }
        if (elem && (x = Dict_getInt(elem, String_CONST("noforks")))) {
            if (!*x) { noforks = 0; }
            continue;
        }
        if (elem && (x = Dict_getInt(elem, String_CONST("chroot")))) {
            if (!*x) { chroot = 0; }
            continue;
        }
        if (elem && (x = Dict_getInt(elem, String_CONST("setupComplete")))) {
            if (!*x) { setupComplete = 0; }
            continue;
        }
        Log_info(ctx->logger, "Unrecognized entry in security at index [%d]", i);
    }

    if (chroot) {
        Log_debug(log, "Security_chroot(/var/run)");
        Dict* d = Dict_new(tempAlloc);
        Dict_putString(d, String_CONST("root"), String_CONST("/var/run/"), tempAlloc);
        rpcCall0(String_CONST("Security_chroot"), d, ctx, tempAlloc, NULL, false);
    }
    /* FIXME(sdg): moving noforks after setuser might make nproc <- 0,0 work
     on older kernels, where doing it before causes setuid to fail w EAGAIN. */
    if (noforks) {
        Log_debug(log, "Security_noforks()");
        Dict* d = Dict_new(tempAlloc);
        rpcCall(String_CONST("Security_noforks"), d, ctx, tempAlloc);
    }
    if (setuser) {
        Log_debug(log, "Security_setUser(uid:%d, keepNetAdmin:%d)", uid, keepNetAdmin);
        Dict* d = Dict_new(tempAlloc);
        Dict_putInt(d, String_CONST("uid"), uid, tempAlloc);
        if (group) {
            Dict_putInt(d, String_CONST("gid"), (int)*group, tempAlloc);
        }
        Dict_putInt(d, String_CONST("keepNetAdmin"), keepNetAdmin, tempAlloc);
        rpcCall0(String_CONST("Security_setUser"), d, ctx, tempAlloc, NULL, false);
    }
    if (nofiles) {
        Log_debug(log, "Security_nofiles()");
        Dict* d = Dict_new(tempAlloc);
        rpcCall(String_CONST("Security_nofiles"), d, ctx, tempAlloc);
    }
    if (seccomp) {
        Log_debug(log, "Security_seccomp()");
        Dict* d = Dict_new(tempAlloc);
        rpcCall(String_CONST("Security_seccomp"), d, ctx, tempAlloc);
    }
    if (setupComplete) {
        Log_debug(log, "Security_setupComplete()");
        Dict* d = Dict_new(tempAlloc);
        rpcCall(String_CONST("Security_setupComplete"), d, ctx, tempAlloc);
    }
}