Exemple #1
0
void DetermineCfenginePort()
{
    assert(sizeof(CFENGINE_PORT_STR) >= PRINTSIZE(CFENGINE_PORT));
    /* ... but we leave more space, as service names can be longer */

    errno = 0;
    struct servent *server = getservbyname(CFENGINE_SERVICE, "tcp");
    if (server != NULL)
    {
        CFENGINE_PORT = ntohs(server->s_port);
        snprintf(CFENGINE_PORT_STR, sizeof(CFENGINE_PORT_STR),
                 "%d", CFENGINE_PORT);
    }
    else if (errno == 0)
    {
        Log(LOG_LEVEL_VERBOSE,
            "No registered cfengine service, using default");
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE,
            "Unable to query services database, using default. (getservbyname: %s)",
            GetErrorStr());
    }
    Log(LOG_LEVEL_VERBOSE, "Default port for cfengine is %d", CFENGINE_PORT);
}
Exemple #2
0
static void PrintStringIndexLine(int prefix_spaces, int len)
{
    char arrow_str[CF_BUFSIZE];
    arrow_str[0] = '^';
    arrow_str[1] = '\0';
    char index_str[CF_BUFSIZE];
    index_str[0] = '0';
    index_str[1] = '\0';
    for (int lineindex = 10; lineindex <= len; lineindex += 10)
    {
        char num[PRINTSIZE(lineindex)];
        xsnprintf(num, sizeof(num), "%10d", lineindex);
        strlcat(index_str, num, sizeof(index_str));
        strlcat(arrow_str, "         ^", sizeof(arrow_str));
    }

    // Prefix the beginning of the indexes with the given number.
    Log(LOG_LEVEL_DEBUG, "%*s%s", prefix_spaces, "", arrow_str);
    Log(LOG_LEVEL_DEBUG, "%*s%s", prefix_spaces, "Index: ", index_str);
}
static int OpenReceiverChannel(void)
{
    struct addrinfo *response = NULL, *ap;
    struct addrinfo query = {
        .ai_flags = AI_PASSIVE,
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
    };

    /* Listen to INADDR(6)_ANY if BINDINTERFACE unset. */
    char *ptr = NULL;
    if (BINDINTERFACE[0] != '\0')
    {
        ptr = BINDINTERFACE;
    }

    char servname[PRINTSIZE(CFENGINE_PORT)];
    xsnprintf(servname, sizeof(servname), "%d", CFENGINE_PORT);

    /* Resolve listening interface. */
    int gres;
    if ((gres = getaddrinfo(ptr, servname, &query, &response)) != 0)
    {
        Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)",
            gai_strerror(gres));
        if (response)
        {
            freeaddrinfo(response);
        }
        return -1;
    }

    int sd = -1;
    for (ap = response; ap != NULL; ap = ap->ai_next)
    {
        sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
        if (sd == -1)
        {
            continue;
        }

       #ifdef IPV6_V6ONLY
        /* Properly implemented getaddrinfo(AI_PASSIVE) should return the IPV6
           loopback address first. Some platforms (notably Windows) don't
           listen to both address families when binding to it and need this
           flag. Some other platforms won't even honour this flag
           (openbsd). */
        if (BINDINTERFACE[0] == '\0' && ap->ai_family == AF_INET6)
        {
            int no = 0;
            if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY,
                           &no, sizeof(no)) == -1)
            {
                Log(LOG_LEVEL_VERBOSE,
                    "Failed to clear IPv6-only flag on listening socket"
                    " (setsockopt: %s)",
                    GetErrorStr());
            }
        }
        #endif

        int yes = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
                       &yes, sizeof(yes)) == -1)
        {
            Log(LOG_LEVEL_VERBOSE,
                "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)",
                GetErrorStr());
        }

        struct linger cflinger = {
            .l_onoff = 1,
            .l_linger = 60
        };
        if (setsockopt(sd, SOL_SOCKET, SO_LINGER,
                       &cflinger, sizeof(cflinger)) == -1)
        {
            Log(LOG_LEVEL_INFO,
                "Socket option SO_LINGER was not accepted. (setsockopt: %s)",
                GetErrorStr());
        }

        if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1)
        {
            if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
            {
                /* Convert IP address to string, no DNS lookup performed. */
                char txtaddr[CF_MAX_IP_LEN] = "";
                getnameinfo(ap->ai_addr, ap->ai_addrlen,
                            txtaddr, sizeof(txtaddr),
                            NULL, 0, NI_NUMERICHOST);
                Log(LOG_LEVEL_DEBUG, "Bound to address '%s' on '%s' = %d", txtaddr,
                    CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS);
            }
            break;
        }
        Log(LOG_LEVEL_INFO,
            "Could not bind server address. (bind: %s)",
            GetErrorStr());
        cf_closesocket(sd);
        sd = -1;
    }

    assert(response != NULL);               /* getaddrinfo() was successful */
    freeaddrinfo(response);
    return sd;
}

static int InitServer(size_t queue_size)
{
    int sd = OpenReceiverChannel();

    if (sd == -1)
    {
        Log(LOG_LEVEL_ERR, "Unable to start server");
    }
    else if (listen(sd, queue_size) == -1)
    {
        Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr());
        cf_closesocket(sd);
    }
    else
    {
        return sd;
    }

    exit(EXIT_FAILURE);
}
Exemple #4
0
void ServerEntryPoint(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info)
{
    time_t now;

    Log(LOG_LEVEL_VERBOSE,
        "Obtained IP address of '%s' on socket %d from accept",
        ipaddr, ConnectionInfoSocket(info));

    /* TODO change nonattackerlist, attackerlist and especially connectionlist
     *      to binary searched lists, or remove them from the main thread! */
    if ((SV.nonattackerlist) && (!IsMatchItemIn(SV.nonattackerlist, ipaddr)))
    {
        Log(LOG_LEVEL_ERR,
            "Remote host '%s' not in allowconnects, denying connection",
            ipaddr);
        cf_closesocket(ConnectionInfoSocket(info));
        ConnectionInfoDestroy(&info);
        return;
    }

    if (IsMatchItemIn(SV.attackerlist, ipaddr))
    {
        Log(LOG_LEVEL_ERR,
            "Remote host '%s' is in denyconnects, denying connection",
            ipaddr);
        cf_closesocket(ConnectionInfoSocket(info));
        ConnectionInfoDestroy(&info);
        return;
    }

    if ((now = time(NULL)) == -1)
    {
       now = 0;
    }

    PurgeOldConnections(&SV.connectionlist, now);

    if (!IsMatchItemIn(SV.multiconnlist, ipaddr))
    {
        if (!ThreadLock(cft_count))
        {
            cf_closesocket(ConnectionInfoSocket(info));
            ConnectionInfoDestroy(&info);
            return;
        }

        if (IsItemIn(SV.connectionlist, ipaddr))
        {
            ThreadUnlock(cft_count);
            Log(LOG_LEVEL_ERR,
                "Remote host '%s' is not in allowallconnects, denying second simultaneous connection",
                ipaddr);
            cf_closesocket(ConnectionInfoSocket(info));
            ConnectionInfoDestroy(&info);
            return;
        }

        ThreadUnlock(cft_count);
    }

    char intime[PRINTSIZE(now)];
    snprintf(intime, sizeof(intime), "%jd", (intmax_t) now);

    if (!ThreadLock(cft_count))
    {
        cf_closesocket(ConnectionInfoSocket(info));
        ConnectionInfoDestroy(&info);
        return;
    }

    PrependItem(&SV.connectionlist, ipaddr, intime);
    ThreadUnlock(cft_count);

    SpawnConnection(ctx, ipaddr, info);
}