コード例 #1
0
Item *SelectProcesses(const Item *processes, const char *process_name, ProcessSelect a, bool attrselect)
{
    Item *result = NULL;

    if (processes == NULL)
    {
        return result;
    }

    char *names[CF_PROCCOLS];
    int start[CF_PROCCOLS];
    int end[CF_PROCCOLS];

    GetProcessColumnNames(processes->name, &names[0], start, end);

    pcre *rx = CompileRegex(process_name);
    if (rx)
    {
        /* TODO: use actual time of ps-run, as time(NULL) may be later. */
        time_t pstime = time(NULL);

        for (Item *ip = processes->next; ip != NULL; ip = ip->next)
        {
            int s, e;

            if (StringMatchWithPrecompiledRegex(rx, ip->name, &s, &e))
            {
                if (NULL_OR_EMPTY(ip->name))
                {
                    continue;
                }

                if (attrselect && !SelectProcess(ip->name, pstime, names, start, end, a))
                {
                    continue;
                }

                pid_t pid = ExtractPid(ip->name, names, end);

                if (pid == -1)
                {
                    Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name);
                    continue;
                }

                PrependItem(&result, ip->name, "");
                result->counter = (int)pid;
            }
        }

        pcre_free(rx);
    }

    for (int i = 0; i < CF_PROCCOLS; i++)
    {
        free(names[i]);
    }

    return result;
}
コード例 #2
0
ファイル: processes_select.c プロジェクト: atsaloli/core
bool IsProcessNameRunning(char *procNameRegex)
{
    char *colHeaders[CF_PROCCOLS];
    int start[CF_PROCCOLS] = { 0 };
    int end[CF_PROCCOLS] = { 0 };
    bool matched = false;
    int i;

    memset(colHeaders, 0, sizeof(colHeaders));

    if (PROCESSTABLE == NULL)
    {
        Log(LOG_LEVEL_ERR, "IsProcessNameRunning: PROCESSTABLE is empty");
        return false;
    }
    /* TODO: use actual time of ps-run, not time(NULL), which may be later. */
    time_t pstime = time(NULL);

    GetProcessColumnNames(PROCESSTABLE->name, colHeaders, start, end);

    for (const Item *ip = PROCESSTABLE->next; !matched && ip != NULL; ip = ip->next) // iterate over ps lines
    {
        char *lineSplit[CF_PROCCOLS];
        memset(lineSplit, 0, sizeof(lineSplit));

        if (NULL_OR_EMPTY(ip->name))
        {
            continue;
        }

        if (!SplitProcLine(ip->name, pstime, colHeaders, start, end,
                           PS_COLUMN_ALGORITHM[VPSHARDCLASS], lineSplit))
        {
            Log(LOG_LEVEL_ERR, "IsProcessNameRunning: Could not split process line '%s'", ip->name);
            goto loop_cleanup;
        }

        ApplyPlatformExtraTable(colHeaders, lineSplit);

        if (SelectProcRegexMatch("CMD", "COMMAND", procNameRegex, true, colHeaders, lineSplit))
        {
            matched = true;
        }

   loop_cleanup:
        for (i = 0; lineSplit[i] != NULL; i++)
        {
            free(lineSplit[i]);
        }
    }

    for (i = 0; colHeaders[i] != NULL; i++)
    {
        free(colHeaders[i]);
    }

    return matched;
}
コード例 #3
0
ファイル: string_lib.c プロジェクト: dardevelin/core-1
bool CompareStringOrRegex(const char *value, const char *compareTo, bool regex)
{
    if (regex)
    {
        if (!NULL_OR_EMPTY(compareTo) && !StringMatchFull(compareTo, value))
        {
            return false;
        }
    }
    else
    {
        if (!NULL_OR_EMPTY(compareTo)  && strcmp(compareTo, value) != 0)
        {
            return false;
        }
    }
    return true;
}
コード例 #4
0
ファイル: processes_select.c プロジェクト: zined/core
bool IsProcessNameRunning(EvalContext *ctx, char *procNameRegex)
{
    char *colHeaders[CF_PROCCOLS];
    Item *ip;
    int start[CF_PROCCOLS] = { 0 };
    int end[CF_PROCCOLS] = { 0 };
    bool matched = false;
    int i;

    if (PROCESSTABLE == NULL)
    {
        Log(LOG_LEVEL_ERR, "IsProcessNameRunning: PROCESSTABLE is empty");
        return false;
    }

    GetProcessColumnNames(PROCESSTABLE->name, (char **) colHeaders, start, end);

    for (ip = PROCESSTABLE->next; ip != NULL; ip = ip->next)    // iterate over ps lines
    {
        char *lineSplit[CF_PROCCOLS];

        if (NULL_OR_EMPTY(ip->name))
        {
            continue;
        }

        if (!SplitProcLine(ip->name, colHeaders, start, end, lineSplit))
        {
            Log(LOG_LEVEL_ERR, "IsProcessNameRunning: Could not split process line '%s'", ip->name);
            continue;
        }

        if (SelectProcRegexMatch(ctx, "CMD", "COMMAND", procNameRegex, colHeaders, lineSplit))
        {
            matched = true;
            break;
        }

        i = 0;
        while (lineSplit[i] != NULL)
        {
            free(lineSplit[i]);
            i++;
        }
    }

    i = 0;
    while (colHeaders[i] != NULL)
    {
        free(colHeaders[i]);
        i++;
    }

    return matched;
}
コード例 #5
0
ファイル: matching.c プロジェクト: TheDreamer/cfengine-3.5.x
void AnchorRegex(const char *regex, char *out, int outSz)
{
    if (NULL_OR_EMPTY(regex))
    {
        memset(out, 0, outSz);
    }
    else
    {
        snprintf(out, outSz, "^(%s)$", regex);
    }
}
コード例 #6
0
ファイル: matching.c プロジェクト: TheDreamer/cfengine-3.5.x
char *AnchorRegexNew(const char *regex)
{
    if (NULL_OR_EMPTY(regex))
    {
        return xstrdup("^$");
    }

    char *ret = NULL;
    xasprintf(&ret, "^(%s)$", regex);

    return ret;
}
コード例 #7
0
ファイル: cf-agent.c プロジェクト: cf-gary/core
int main(int argc, char *argv[])
{
    int ret = 0;

    GenericAgentConfig *config = CheckOpts(argc, argv);
#ifdef HAVE_AVAHI_CLIENT_CLIENT_H
#ifdef HAVE_AVAHI_COMMON_ADDRESS_H
    if (NULL_OR_EMPTY(POLICY_SERVER) && BOOTSTRAP)
    {
        int ret = AutomaticBootstrap();

        if (ret < 0)
        {
            return 1;
        }
    }
#endif
#endif
    ReportContext *report_context = OpenReports(config->agent_type);

    GenericAgentDiscoverContext(config, report_context);
    Policy *policy = GenericAgentLoadPolicy(config, report_context, ALWAYS_VALIDATE);

    CheckLicenses();

    ThisAgentInit();
    BeginAudit();
    KeepPromises(policy, config, report_context);
    CloseReports("agent", report_context);

    // only note class usage when default policy is run
    if (!config->input_file)
    {
        NoteClassUsage(VHEAP, true);
        NoteClassUsage(VHARDHEAP, true);
    }
#ifdef HAVE_NOVA
    Nova_NoteVarUsageDB();
    Nova_TrackExecution(config->input_file);
#endif
    PurgeLocks();

    if (BOOTSTRAP && !VerifyBootstrap())
    {
        ret = 1;
    }

    EndAudit(CFA_BACKGROUND);
    GenericAgentConfigDestroy(config);

    return ret;
}
コード例 #8
0
ファイル: processes_select.c プロジェクト: nickanderson/core
Item *SelectProcesses(const char *process_name, const ProcessSelect *a, bool attrselect)
{
    assert(a != NULL);
    const Item *processes = PROCESSTABLE;
    Item *result = NULL;

    if (processes == NULL)
    {
        return result;
    }

    char *names[CF_PROCCOLS];
    int start[CF_PROCCOLS];
    int end[CF_PROCCOLS];

    GetProcessColumnNames(processes->name, names, start, end);

    /* TODO: use actual time of ps-run, as time(NULL) may be later. */
    time_t pstime = time(NULL);

    for (Item *ip = processes->next; ip != NULL; ip = ip->next)
    {
        if (NULL_OR_EMPTY(ip->name))
        {
            continue;
        }

        if (!SelectProcess(ip->name, pstime, names, start, end, process_name, a, attrselect))
        {
            continue;
        }

        pid_t pid = ExtractPid(ip->name, names, end);

        if (pid == -1)
        {
            Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name);
            continue;
        }

        PrependItem(&result, ip->name, "");
        result->counter = (int)pid;
    }

    for (int i = 0; i < CF_PROCCOLS; i++)
    {
        free(names[i]);
    }

    return result;
}
コード例 #9
0
ファイル: processes_select.c プロジェクト: zined/core
Item *SelectProcesses(EvalContext *ctx, const Item *processes, const char *process_name, ProcessSelect a, bool attrselect)
{
    Item *result = NULL;

    if (processes == NULL)
    {
        return result;
    }

    char *names[CF_PROCCOLS];
    int start[CF_PROCCOLS];
    int end[CF_PROCCOLS];

    GetProcessColumnNames(processes->name, &names[0], start, end);

    for (Item *ip = processes->next; ip != NULL; ip = ip->next)
    {
        int s, e;

        if (BlockTextMatch(ctx, process_name, ip->name, &s, &e))
        {
            if (NULL_OR_EMPTY(ip->name))
            {
                continue;
            }

            if (attrselect && !SelectProcess(ctx, ip->name, names, start, end, a))
            {
                continue;
            }

            pid_t pid = ExtractPid(ip->name, names, end);

            if (pid == -1)
            {
                Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name);
                continue;
            }

            PrependItem(&result, ip->name, "");
            result->counter = (int)pid;
        }
    }

    for (int i = 0; i < CF_PROCCOLS; i++)
    {
        free(names[i]);
    }

    return result;
}
コード例 #10
0
ファイル: dsn.c プロジェクト: ajinkya93/netbsd-src
DSN    *dsn_create(const char *status, const char *action, const char *reason,
		           const char *dtype, const char *dtext,
		           const char *mtype, const char *mname)
{
    const char *myname = "dsn_create";
    DSN    *dsn;

    dsn = (DSN *) mymalloc(sizeof(*dsn));

    /*
     * Status and reason must not be empty. Other members may be empty
     * strings.
     * 
     * Early implementations represented unavailable information with null
     * pointers. This resulted in code that was difficult to maintain. We now
     * use empty strings instead. For safety sake we keep the null pointer
     * test for input, but we always convert to empty string on output.
     */
#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)

    if (NULL_OR_EMPTY(status))
	msg_panic("%s: null dsn status", myname);
    else
	dsn->status = mystrdup(status);

    if (NULL_OR_EMPTY(action))
	dsn->action = mystrdup("");
    else
	dsn->action = mystrdup(action);

    if (NULL_OR_EMPTY(reason))
	msg_panic("%s: null dsn reason", myname);
    else
	dsn->reason = mystrdup(reason);

    if (NULL_OR_EMPTY(dtype) || NULL_OR_EMPTY(dtext)) {
	dsn->dtype = mystrdup("");
	dsn->dtext = mystrdup("");
    } else {
	dsn->dtype = mystrdup(dtype);
	dsn->dtext = mystrdup(dtext);
    }
    if (NULL_OR_EMPTY(mtype) || NULL_OR_EMPTY(mname)) {
	dsn->mtype = mystrdup("");
	dsn->mname = mystrdup("");
    } else {
	dsn->mtype = mystrdup(mtype);
	dsn->mname = mystrdup(mname);
    }
    return (dsn);
}
コード例 #11
0
ファイル: bootstrap.c プロジェクト: dstam/core
/**
 * @brief Sets both internal C variables as well as policy sys variables.
 *
 * Called at bootstrap and after reading policy_server.dat.
 * Changes sys.policy_hub and sys.policy_hub_port.
 * NULL is an acceptable value for new_policy_server. Could happen when an
 * already bootstrapped server re-parses its policies, and the
 * policy_server.dat file has been removed. Then this function will be called
 * with NULL as new_policy_server, and cf-serverd will keep running even
 * without a policy server set.
 *
 * @param ctx EvalContext is used to set related variables
 * @param new_policy_server can be 'host:port', same as policy_server.dat
 */
void EvalContextSetPolicyServer(EvalContext *ctx, const char *new_policy_server)
{
    // Remove variables if undefined policy server:
    if ( NULL_OR_EMPTY(new_policy_server) )
    {
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub" );
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub_port" );
        return;
    }

    PolicyServerSet(new_policy_server);
    const char *ip = PolicyServerGetIP();

    // Set the sys.policy_hub variable:
    if ( ip != NULL )
    {
        EvalContextVariablePutSpecial(  ctx,  SPECIAL_SCOPE_SYS,
                                        "policy_hub", ip,
                                        CF_DATA_TYPE_STRING,
                                        "source=bootstrap" );
    }
    else
    {
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub" );
    }

    // Set the sys.policy_hub_port variable:
    if (PolicyServerGetPort() != NULL)
    {
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS,
                                      "policy_hub_port", PolicyServerGetPort(),
                                      CF_DATA_TYPE_STRING,
                                      "source=bootstrap" );
    }
    else // Default value (CFENGINE_PORT_STR = "5308") is set
    {
        EvalContextVariablePutSpecial( ctx, SPECIAL_SCOPE_SYS,
                                       "policy_hub_port",
                                       CFENGINE_PORT_STR,
                                       CF_DATA_TYPE_STRING,
                                       "source=bootstrap" );
    }
}
コード例 #12
0
ファイル: loading.c プロジェクト: kkaempf/core
static void RenameMainBundle(EvalContext *ctx, Policy *policy)
{
    assert(policy != NULL);
    assert(ctx != NULL);
    assert(policy->bundles != NULL);
    char *const entry_point = GetRealPath(EvalContextGetEntryPoint(ctx));
    if (NULL_OR_EMPTY(entry_point))
    {
        free(entry_point);
        return;
    }
    Seq *bundles = policy->bundles;
    int length = SeqLength(bundles);
    bool removed = false;
    for (int i = 0; i < length; ++i)
    {
        Bundle *const bundle = SeqAt(bundles, i);
        if (StringSafeEqual(bundle->name, "__main__"))
        {
            char *abspath = GetRealPath(bundle->source_path);
            if (StringSafeEqual(abspath, entry_point))
            {
                Log(LOG_LEVEL_VERBOSE,
                    "Redefining __main__ bundle from file %s to be main",
                    abspath);
                strncpy(bundle->name, "main", 4+1);
                // "__main__" is always big enough for "main"
            }
            else
            {
                Log(LOG_LEVEL_VERBOSE,
                    "Dropping __main__ bundle from file %s (entry point: %s)",
                    abspath,
                    entry_point);
                removed = true;
                SeqSet(bundles, i, NULL); // SeqSet calls destroy function
            }
            free(abspath);
        }
    }
    if (removed)
    {
        SeqRemoveNulls(bundles);
    }
    free(entry_point);
}
コード例 #13
0
bool IsProcessNameRunning(char *procNameRegex)
{
    char *colHeaders[CF_PROCCOLS];
    Item *ip;
    int start[CF_PROCCOLS] = { 0 };
    int end[CF_PROCCOLS] = { 0 };
    bool matched = false;

    if (PROCESSTABLE == NULL)
    {
        CfOut(cf_error, "", "!! IsProcessNameRunning: PROCESSTABLE is empty");
        return false;
    }

    GetProcessColumnNames(PROCESSTABLE->name, (char **) colHeaders, start, end);

    for (ip = PROCESSTABLE->next; ip != NULL; ip = ip->next)    // iterate over ps lines
    {
        char *lineSplit[CF_PROCCOLS];

        if (NULL_OR_EMPTY(ip->name))
        {
            continue;
        }

        if (!SplitProcLine(ip->name, colHeaders, start, end, lineSplit))
        {
            CfOut(cf_error, "", "!! IsProcessNameRunning: Could not split process line \"%s\"", ip->name);
            continue;
        }

        if (SelectProcRegexMatch("CMD", "COMMAND", procNameRegex, colHeaders, lineSplit))
        {
            matched = true;
            break;
        }
    }

    return matched;
}
コード例 #14
0
ファイル: cf-agent.c プロジェクト: cf-gary/core
static bool VerifyBootstrap(void)
{
    struct stat sb;
    char filePath[CF_MAXVARSIZE];

    if (NULL_OR_EMPTY(POLICY_SERVER))
    {
        CfOut(cf_error, "", "!! Bootstrapping failed, no policy server is specified");
        return false;
    }

    // we should at least have gotten promises.cf from the policy hub
    snprintf(filePath, sizeof(filePath), "%s/inputs/promises.cf", CFWORKDIR);
    MapName(filePath);

    if (cfstat(filePath, &sb) == -1)
    {
        CfOut(cf_error, "", "!! Bootstrapping failed, no input file at %s after bootstrap", filePath);
        return false;
    }

    // embedded failsafe.cf (bootstrap.c) contains a promise to start cf-execd (executed while running this cf-agent)
    DeleteItemList(PROCESSTABLE);
    PROCESSTABLE = NULL;
    LoadProcessTable(&PROCESSTABLE);

    if (!IsProcessNameRunning(".*cf-execd.*"))
    {
        CfOut(cf_error, "", "!! Bootstrapping failed, cf-execd is not running");
        return false;
    }

    CfOut(cf_cmdout, "", "-> Bootstrap to %s completed successfully", POLICY_SERVER);

    return true;
}
コード例 #15
0
ファイル: cf-agent.c プロジェクト: FancsalMelinda/core
int main(int argc, char *argv[])
{
    int ret = 0;

    GenericAgentConfig *config = CheckOpts(argc, argv);
#ifdef HAVE_AVAHI_CLIENT_CLIENT_H
#ifdef HAVE_AVAHI_COMMON_ADDRESS_H
    if (NULL_OR_EMPTY(POLICY_SERVER) && BOOTSTRAP)
    {
        int ret = AutomaticBootstrap();

        if (ret < 0)
        {
            return 1;
        }
    }
#endif
#endif
    ReportContext *report_context = OpenReports(config->agent_type);

    GenericAgentDiscoverContext(config, report_context);

    Policy *policy = NULL;
    if (GenericAgentCheckPolicy(config, report_context, ALWAYS_VALIDATE))
    {
        policy = GenericAgentLoadPolicy(config->agent_type, config, report_context);
    }
    else if (config->tty_interactive)
    {
        FatalError("CFEngine was not able to get confirmation of promises from cf-promises, please verify input file\n");
    }
    else
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe\n");
        HardClass("failsafe_fallback");
        GenericAgentConfigSetInputFile(config, "failsafe.cf");
        policy = GenericAgentLoadPolicy(config->agent_type, config, report_context);
    }

    CheckLicenses();

    ThisAgentInit();
    BeginAudit();
    KeepPromises(policy, config, report_context);
    CloseReports("agent", report_context);

    // only note class usage when default policy is run
    if (!config->input_file)
    {
        NoteClassUsage(VHEAP, true);
        NoteClassUsage(VHARDHEAP, true);
    }
#ifdef HAVE_NOVA
    Nova_NoteVarUsageDB();
    Nova_TrackExecution(config->input_file);
#endif
    PurgeLocks();

    if (BOOTSTRAP && !VerifyBootstrap())
    {
        ret = 1;
    }

    EndAudit(CFA_BACKGROUND);
    GenericAgentConfigDestroy(config);

    return ret;
}
コード例 #16
0
ファイル: bootstrap.c プロジェクト: fbettag/core
void SetPolicyServer(char *name)
/*
 * If name contains a string, it's written to file,
 * if not, name is filled with the contents of file.
 */
{
    char file[CF_BUFSIZE];
    FILE *fout, *fin;
    char fileContents[CF_MAXVARSIZE] = { 0 };

    snprintf(file, CF_BUFSIZE - 1, "%s/policy_server.dat", CFWORKDIR);
    MapName(file);

    if ((fin = fopen(file, "r")) != NULL)
    {
        fscanf(fin, "%1023s", fileContents);
        fclose(fin);
    }

    // update file if different and we know what to put there

    if ((NULL_OR_EMPTY(name)) && (!NULL_OR_EMPTY(fileContents)))
    {
        snprintf(name, CF_MAXVARSIZE, "%s", fileContents);
    }
    else if ((!NULL_OR_EMPTY(name)) && (strcmp(name, fileContents) != 0))
    {
        if ((fout = fopen(file, "w")) == NULL)
        {
            CfOut(cf_error, "fopen", "Unable to write policy server file! (%s)", file);
            return;
        }

        fprintf(fout, "%s", name);
        fclose(fout);
    }

    if (NULL_OR_EMPTY(name))
    {
        // avoids "Scalar item in servers => {  } in rvalue is out of bounds ..."
        // when NovaBase is checked with unprivileged (not bootstrapped) cf-promises
        NewScalar("sys", "policy_hub", "undefined", cf_str);
    }
    else
    {
        NewScalar("sys", "policy_hub", name, cf_str);
    }

// Get the timestamp on policy update

    snprintf(file, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
    MapName(file);

    struct stat sb;

    if ((cfstat(file, &sb)) != 0)
    {
        return;
    }

    char timebuf[26];
    cf_strtimestamp_local(sb.st_mtime, timebuf);

    NewScalar("sys", "last_policy_update", timebuf, cf_str);
}
コード例 #17
0
static int FindPidMatches(Item *procdata, Item **killlist, Attributes a, Promise *pp)
{
    Item *ip;
    int pid = -1, matches = 0, i, s, e, promised_zero;
    pid_t cfengine_pid = getpid();
    char *names[CF_PROCCOLS];   /* ps headers */
    int start[CF_PROCCOLS];
    int end[CF_PROCCOLS];

    if (procdata == NULL)
    {
        return 0;
    }

    GetProcessColumnNames(procdata->name, (char **) names, start, end);

    for (ip = procdata->next; ip != NULL; ip = ip->next)
    {
        CF_OCCUR++;

        if (BlockTextMatch(pp->promiser, ip->name, &s, &e))
        {
            if (NULL_OR_EMPTY(ip->name))
            {
                continue;
            }

            if (!SelectProcess(ip->name, names, start, end, a, pp))
            {
                continue;
            }

            pid = ExtractPid(ip->name, names, start, end);

            if (pid == -1)
            {
                CfOut(cf_verbose, "", "Unable to extract pid while looking for %s\n", pp->promiser);
                continue;
            }

            CfOut(cf_verbose, "", " ->  Found matching pid %d\n     (%s)", pid, ip->name);

            matches++;

            if (pid == 1)
            {
                if ((RlistLen(a.signals) == 1) && IsStringIn(a.signals, "hup"))
                {
                    CfOut(cf_verbose, "", "(Okay to send only HUP to init)\n");
                }
                else
                {
                    continue;
                }
            }

            if (pid < 4 && a.signals)
            {
                CfOut(cf_verbose, "", "Will not signal or restart processes 0,1,2,3 (occurred while looking for %s)\n",
                      pp->promiser);
                continue;
            }

            promised_zero = a.process_count.min_range == 0 && a.process_count.max_range == 0;

            if (a.transaction.action == cfa_warn && promised_zero)
            {
                CfOut(cf_error, "", "Process alert: %s\n", procdata->name);     /* legend */
                CfOut(cf_error, "", "Process alert: %s\n", ip->name);
                continue;
            }

            if (pid == cfengine_pid && a.signals)
            {
                CfOut(cf_verbose, "", " !! cf-agent will not signal itself!\n");
                continue;
            }

            PrependItem(killlist, ip->name, "");
            (*killlist)->counter = pid;
        }
    }

// Free up allocated memory

    for (i = 0; i < CF_PROCCOLS; i++)
    {
        if (names[i] != NULL)
        {
            free(names[i]);
        }
    }

    return matches;
}
コード例 #18
0
ファイル: cf-runagent.c プロジェクト: kkaempf/core
static void HailExec(AgentConnection *conn, char *peer)
{
    char sendbuf[CF_BUFSIZE - CF_INBAND_OFFSET] = "EXEC";
    size_t sendbuf_len = strlen(sendbuf);

    if (!NULL_OR_EMPTY(DEFINECLASSES))
    {
        StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, " -D", 0);
        StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, DEFINECLASSES, 0);
    }
    if (!NULL_OR_EMPTY(REMOTEBUNDLES))
    {
        StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, " -b ", 0);
        StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, REMOTEBUNDLES, 0);
    }

    if (sendbuf_len >= sizeof(sendbuf))
    {
        Log(LOG_LEVEL_ERR, "Command longer than maximum transaction packet");
        DisconnectServer(conn);
        return;
    }

    if (SendTransaction(conn->conn_info, sendbuf, 0, CF_DONE) == -1)
    {
        Log(LOG_LEVEL_ERR, "Transmission rejected. (send: %s)", GetErrorStr());
        DisconnectServer(conn);
        return;
    }

    /* TODO we are sending class data right after EXEC, when the server might
     * have already rejected us with BAD reply. So this class data with the
     * CFD_TERMINATOR will be interpreted by the server as a new, bogus
     * protocol command, and the server will complain. */
    SendClassData(conn);

    char recvbuffer[CF_BUFSIZE];
    FILE *fp = NewStream(peer);
    while (true)
    {
        memset(recvbuffer, 0, sizeof(recvbuffer));

        if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1)
        {
            break;
        }
        if (strncmp(recvbuffer, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0)
        {
            break;
        }

        const size_t recv_len = strlen(recvbuffer);
        const char   *ipaddr  = conn->remoteip;

        if (strncmp(recvbuffer, "BAD:", 4) == 0)
        {
            fprintf(fp, "%s> !! %s\n", ipaddr, recvbuffer + 4);
        }
        /* cf-serverd >= 3.7 quotes command output with "> ". */
        else if (strncmp(recvbuffer, "> ", 2) == 0)
        {
            fprintf(fp, "%s> -> %s", ipaddr, &recvbuffer[2]);
        }
        else
        {
            fprintf(fp, "%s> %s", ipaddr, recvbuffer);
        }

        if (recv_len > 0 && recvbuffer[recv_len - 1] != '\n')
        {
            /* We'll be printing double newlines here with new cf-serverd
             * versions, so check for already trailing newlines. */
            /* TODO deprecate this path in a couple of versions. cf-serverd is
             * supposed to munch the newlines so we must always append one. */
            fputc('\n', fp);
        }
    }

    if (fp != stdout)
    {
        fclose(fp);
    }
    DisconnectServer(conn);
}
コード例 #19
0
ファイル: conversion.c プロジェクト: gsprint/core
void IPString2KeyDigest(char *ipv4, char *result)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    char *key;
    void *value;
    KeyHostSeen entry;
    int ksize, vsize;
    unsigned char digest[EVP_MAX_MD_SIZE + 1];

    result[0] = '\0';

    if (strcmp(ipv4, "127.0.0.1") == 0 || strcmp(ipv4, "::1") == 0 || strcmp(ipv4, VIPADDRESS) == 0)
    {
        if (PUBKEY)
        {
            HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST);
            snprintf(result, CF_MAXVARSIZE, "%s", HashPrint(CF_DEFAULT_DIGEST, digest));
        }
        return;
    }

    if (!OpenDB(&dbp, dbid_lastseen))
    {
        return;
    }

    if (!NewDBCursor(dbp, &dbcp))
    {
        CfOut(cf_inform, "", " !! Unable to scan last-seen database");
        CloseDB(dbp);
        return;
    }

    /* Initialize the key/data return pair. */

    memset(&entry, 0, sizeof(entry));

    /* Walk through the database and print out the key/data pairs. */

    while (NextDB(dbp, dbcp, &key, &ksize, &value, &vsize))
    {
        if (value != NULL)
        {
            memcpy(&entry, value, sizeof(entry));

            // Warning this is not 1:1

            if (strcmp(ipv4, MapAddress((char *) entry.address)) == 0)
            {
                CfOut(cf_verbose, "", " -> Matched IP %s to key %s", ipv4, key + 1);
                strncpy(result, key + 1, CF_MAXVARSIZE - 1);
                break;
            }
        }
    }

    DeleteDBCursor(dbp, dbcp);
    CloseDB(dbp);

    if (NULL_OR_EMPTY(result))
    {
        CfOut(cf_verbose, "", "!! Unable to find a key for ip %s", ipv4);
    }
}
コード例 #20
0
ファイル: crypto.c プロジェクト: chrishiestand/core
void LoadSecretKeys()
{
    FILE *fp;
    static char *passphrase = "Cfengine passphrase", name[CF_BUFSIZE], source[CF_BUFSIZE];
    char guard[CF_MAXVARSIZE];
    unsigned char digest[EVP_MAX_MD_SIZE + 1];
    unsigned long err;
    struct stat sb;

    if ((fp = fopen(PrivateKeyFile(), "r")) == NULL)
    {
        CfOut(OUTPUT_LEVEL_INFORM, "fopen", "Couldn't find a private key (%s) - use cf-key to get one", PrivateKeyFile());
        return;
    }

    if ((PRIVKEY = PEM_read_RSAPrivateKey(fp, (RSA **) NULL, NULL, passphrase)) == NULL)
    {
        err = ERR_get_error();
        CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err));
        PRIVKEY = NULL;
        fclose(fp);
        return;
    }

    fclose(fp);

    CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded private key %s\n", PrivateKeyFile());

    if ((fp = fopen(PublicKeyFile(), "r")) == NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Couldn't find a public key (%s) - use cf-key to get one", PublicKeyFile());
        return;
    }

    if ((PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL)
    {
        err = ERR_get_error();
        CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err));
        PUBKEY = NULL;
        fclose(fp);
        return;
    }

    CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded public key %s\n", PublicKeyFile());
    fclose(fp);

    if ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e)))
    {
        FatalError("RSA Exponent too small or not odd");
    }

    if (NULL_OR_EMPTY(POLICY_SERVER))
    {
        snprintf(name, CF_MAXVARSIZE - 1, "%s%cpolicy_server.dat", CFWORKDIR, FILE_SEPARATOR);

        if ((fp = fopen(name, "r")) != NULL)
        {
            if (fscanf(fp, "%4095s", POLICY_SERVER) != 1)
            {
                CfDebug("Couldn't read string from policy_server.dat");
            }
            fclose(fp);
        }
    }

/* Check that we have our own SHA key form of the key in the IP on the hub */

    char buffer[EVP_MAX_MD_SIZE * 4];

    HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST);
    snprintf(name, CF_MAXVARSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(CF_DEFAULT_DIGEST, digest, buffer));
    MapName(name);

    snprintf(source, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR);
    MapName(source);

// During bootstrap we need the pre-registered IP/hash pair on the hub

    snprintf(guard, sizeof(guard), "%s/state/am_policy_hub", CFWORKDIR);
    MapName(guard);

// need to use cf_stat

    if ((stat(name, &sb) == -1) && (stat(guard, &sb) != -1))
        // copy localhost.pub to root-HASH.pub on policy server
    {
        LastSaw(POLICY_SERVER, digest, LAST_SEEN_ROLE_CONNECT);

        if (!LinkOrCopy(source, name, false))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", " -> Unable to clone server's key file as %s\n", name);
        }
    }

}