Example #1
0
static void test_purge_old_connections_purge_middle(void)
{
    const time_t time_now = 100000;

    Item *connections = NULL;
    char time_str[64];

    snprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS);
    PrependItem(&connections, "123.123.123.3", time_str);

    snprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS - 1);
    PrependItem(&connections, "123.123.123.2", time_str);

    snprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 100);
    PrependItem(&connections, "123.123.123.1", time_str);

    assert_int_equal(ListLen(connections), 3);

    PurgeOldConnections(&connections, time_now);

    assert_int_equal(ListLen(connections), 2);

    assert_true(IsItemIn(connections, "123.123.123.1"));
    assert_false(IsItemIn(connections, "123.123.123.2"));
    assert_true(IsItemIn(connections, "123.123.123.3"));

    DeleteItemList(connections);
}
Example #2
0
void EvalContextHeapAddAbort(EvalContext *ctx, const char *context, const char *activated_on_context)
{
    if (!IsItemIn(ctx->heap_abort, context))
    {
        AppendItem(&ctx->heap_abort, context, activated_on_context);
    }
}
Example #3
0
static SyntaxTypeMatch CheckParseOpts(const char *lval, const char *s, const char *range)
{
    Item *split;

/* List/menu types are separated by comma str "a,b,c,..." */

    CfDebug("\nCheckParseOpts(%s => %s/%s)\n", lval, s, range);

    if (IsNakedVar(s, '@') || IsNakedVar(s, '$'))
    {
        return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED;
    }

    split = SplitString(range, ',');

    if (!IsItemIn(split, s))
    {
        DeleteItemList(split);
        return SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE;
    }

    DeleteItemList(split);

    return SYNTAX_TYPE_MATCH_OK;
}
Example #4
0
void EvalContextHeapAddAbortCurrentBundle(EvalContext *ctx, const char *context, const char *activated_on_context)
{
    if (!IsItemIn(ctx->heap_abort_current_bundle, context))
    {
        AppendItem(&ctx->heap_abort_current_bundle, context, activated_on_context);
    }
}
Example #5
0
int RelevantBundle(char *agent,char *blocktype)

{   struct Item *ip;

    if (strcmp(agent,CF_AGENTTYPES[cf_common]) == 0 || strcmp(CF_COMMONC,P.blocktype) == 0)
    {
        return true;
    }

    /* Here are some additional bundle types handled by cfAgent */

    ip = SplitString("edit_line,edit_xml",',');

    if (strcmp(agent,CF_AGENTTYPES[cf_agent]) == 0)
    {
        if (IsItemIn(ip,blocktype))
        {
            DeleteItemList(ip);
            return true;
        }
    }

    DeleteItemList(ip);
    return false;
}
Example #6
0
void AddInstallable(char *classlist)

{ char *sp, currentitem[CF_MAXVARSIZE];

if (classlist == NULL)
   {
   return;
   }

Debug("AddInstallable(%s)\n",classlist);
  
 for (sp = classlist; *sp != '\0'; sp++)
   {
   currentitem[0] = '\0';

   sscanf(sp,"%[^,:.]",currentitem);

   sp += strlen(currentitem);

   if (! IsItemIn(VALLADDCLASSES,currentitem))
      {
      AppendItem(&VALLADDCLASSES,currentitem,NULL);
      }

   if (*sp == '\0')
      {
      break;
      }
   }
}
Example #7
0
int ArchiveToRepository(const char *file, Attributes attr, Promise *pp, const ReportContext *report_context)
 /* Returns true if the file was backup up and false if not */
{
    char destination[CF_BUFSIZE];
    struct stat sb, dsb;

    if (!GetRepositoryPath(file, attr, destination))
    {
        return false;
    }

    if (attr.copy.backup == cfa_nobackup)
    {
        return true;
    }

    if (IsItemIn(VREPOSLIST, file))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "",
              "The file %s has already been moved to the repository once. Multiple update will cause loss of backup.",
              file);
        return true;
    }

    ThreadLock(cft_getaddr);
    PrependItemList(&VREPOSLIST, file);
    ThreadUnlock(cft_getaddr);

    CfDebug("Repository(%s)\n", file);
    
    JoinPath(destination, CanonifyName(file));

    if (!MakeParentDirectory(destination, attr.move_obstructions, report_context))
    {
    }

    if (cfstat(file, &sb) == -1)
    {
        CfDebug("File %s promised to archive to the repository but it disappeared!\n", file);
        return true;
    }

    cfstat(destination, &dsb);

    CheckForFileHoles(&sb, pp);

    if (pp && CopyRegularFileDisk(file, destination, pp->makeholes))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Moved %s to repository location %s\n", file, destination);
        return true;
    }
    else
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Failed to move %s to repository location %s\n", file, destination);
        return false;
    }
}
static void IncrementCounter(Item **list, char *name)
{
    if (!IsItemIn(*list, name))
    {
        AppendItem(list, name, "");
    }

    IncrementItemListCounter(*list, name);
}
Example #9
0
int AllowedUser(char *user)
{
    if (IsItemIn(SV.allowuserlist, user))
    {
        Log(LOG_LEVEL_VERBOSE, "User %s granted connection privileges", user);
        return true;
    }

    Log(LOG_LEVEL_VERBOSE, "User %s is not allowed on this server", user);
    return false;
}
Example #10
0
int ArchiveToRepository(const char *file, Attributes attr)
 /* Returns true if the file was backup up and false if not */
{
    char destination[CF_BUFSIZE];
    struct stat sb, dsb;

    if (!GetRepositoryPath(file, attr, destination))
    {
        return false;
    }

    if (attr.copy.backup == BACKUP_OPTION_NO_BACKUP)
    {
        return true;
    }

    if (IsItemIn(VREPOSLIST, file))
    {
        Log(LOG_LEVEL_INFO,
            "The file '%s' has already been moved to the repository once. Multiple update will cause loss of backup.",
              file);
        return true;
    }

    ThreadLock(cft_getaddr);
    PrependItemList(&VREPOSLIST, file);
    ThreadUnlock(cft_getaddr);
    
    JoinPath(destination, CanonifyName(file));

    if (!MakeParentDirectory(destination, attr.move_obstructions))
    {
    }

    if (stat(file, &sb) == -1)
    {
        Log(LOG_LEVEL_DEBUG, "File '%s' promised to archive to the repository but it disappeared!", file);
        return true;
    }

    stat(destination, &dsb);

    if (CopyRegularFileDisk(file, destination))
    {
        Log(LOG_LEVEL_INFO, "Moved '%s' to repository location '%s'", file, destination);
        return true;
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Failed to move '%s' to repository location '%s'", file, destination);
        return false;
    }
}
Example #11
0
static bool GetSysUsers( int *userListSz, int *numRootProcs, int *numOtherProcs)
{
    FILE *fp;
    char user[CF_BUFSIZE];
    char vbuff[CF_BUFSIZE];
    char cbuff[CF_BUFSIZE];

#if defined(__sun)
    xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user > %s/users.txt", CFWORKDIR);
#elif defined(_AIX)
    xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -N -eo user > %s/users.txt", CFWORKDIR);
#elif defined(__linux__)
    xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user > %s/users.txt", CFWORKDIR);
#else
    assert_true(1);
    return false;
#endif

    Item *userList = NULL;
    system(cbuff);
    xsnprintf(cbuff, CF_BUFSIZE, "%s/users.txt", CFWORKDIR);
    if ((fp = fopen(cbuff, "r")) == NULL)
    {
        return false;
    }
    while (fgets(vbuff, CF_BUFSIZE, fp) != NULL)
    {
        sscanf(vbuff, "%s", user);

        if (strcmp(user, "USER") == 0)
        {
            continue;
        }

        if (!IsItemIn(userList, user))
        {
            PrependItem(&userList, user, NULL);
            (*userListSz)++;
        }

        if (strcmp(user, "root") == 0)
        {
            (*numRootProcs)++;
        }
        else
        {
            (*numOtherProcs)++;
        }
    }
    fclose(fp);
    return true;
}
Example #12
0
static void SetNetworkEntropyClasses(const char *service, const char *direction, const Item *list)
{
    const Item *ip;
    Item *addresses = NULL;
    double entropy;

    for (ip = list; ip != NULL; ip = ip->next)
    {
        if (strlen(ip->name) > 0)
        {
            char local[CF_BUFSIZE];
            char remote[CF_BUFSIZE];
            char vbuff[CF_BUFSIZE];
            char *sp;

            if (strncmp(ip->name, "tcp", 3) == 0)
            {
                sscanf(ip->name, "%*s %*s %*s %s %s", local, remote);   /* linux-like */
            }
            else
            {
                sscanf(ip->name, "%s %s", local, remote);       /* solaris-like */
            }

            strncpy(vbuff, remote, CF_BUFSIZE - 1);
            vbuff[CF_BUFSIZE-1] = '\0';

            for (sp = vbuff + strlen(vbuff) - 1; isdigit((int) *sp) && (sp > vbuff); sp--)
            {
            }

            *sp = '\0';

            if (!IsItemIn(addresses, vbuff))
            {
                AppendItem(&addresses, vbuff, "");
            }

            IncrementItemListCounter(addresses, vbuff);
        }
    }

    entropy = MonEntropyCalculate(addresses);
    MonEntropyClassesSet(service, direction, entropy);
    DeleteItemList(addresses);
}
Example #13
0
bool ListsCompare(const Item *list1, const Item *list2)
{
    if (ListLen(list1) != ListLen(list2))
    {
        return false;
    }

    for (const Item *ptr = list1; ptr != NULL; ptr = ptr->next)
    {
        if (IsItemIn(list2, ptr->name) == false)
        {
            return false;
        }
    }

    return true;
}
static int Unix_GatherProcessUsers(struct Item **userList, int *userListSz, int *numRootProcs, int *numOtherProcs)
{
FILE *pp;
char pscomm[CF_BUFSIZE];
char user[CF_MAXVARSIZE];
char vbuff[CF_BUFSIZE];

snprintf(pscomm,CF_BUFSIZE,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],VPSOPTS[VSYSTEMHARDCLASS]);

if ((pp = cf_popen(pscomm,"r")) == NULL)
   {
   return false;
   }

CfReadLine(vbuff,CF_BUFSIZE,pp); 

while (!feof(pp))
   {
   CfReadLine(vbuff,CF_BUFSIZE,pp);
   sscanf(vbuff,"%s",user);

   if (strcmp(user,"USER") == 0)
      {
      continue;
      }

   if (!IsItemIn(*userList,user))
      {
      PrependItem(userList,user,NULL);
      (*userListSz)++;
      }

   if (strcmp(user,"root") == 0)
      {
      (*numRootProcs)++;
      }
   else
      {
      (*numOtherProcs)++;
      }
   }

cf_pclose(pp);
return true;
}
/**
 * Checks whether list1 is a subset of list2, i.e. every entry in list1 must
 * be found in list2.
 */
bool ListSubsetOfList(const Item *list1, const Item *list2)
{
    const Item *list1_ptr = list1;
    CYCLE_DECLARE(list1_ptr, slow, toggle);

    while (list1_ptr != NULL)
    {
        if (!IsItemIn(list2, list1_ptr->name))
        {
            return false;
        }

        list1_ptr = list1_ptr->next;
        CYCLE_CHECK(list1_ptr, slow, toggle);
    }

    return true;               /* all elements of list1 were found in list2 */
}
Example #16
0
bool ListsCompare(const Item *list1, const Item *list2)
{
    if (ListLen(list1) != ListLen(list2))
    {
        return false;
    }

    const Item *ptr = list1;
    CYCLE_DECLARE(ptr, slow, toggle);
    while (ptr != NULL)
    {
        if (IsItemIn(list2, ptr->name) == false)
        {
            return false;
        }
        ptr = ptr->next;
        CYCLE_CHECK(ptr, slow, toggle);
    }

    return true;
}
Example #17
0
File: syntax.c Project: dnaeon/core
static void CheckParseOpts(char *lval, char *s, const char *range)
{
    Item *split;
    int err = false;
    char output[CF_BUFSIZE];

/* List/menu types are separated by comma str "a,b,c,..." */

    CfDebug("\nCheckParseOpts(%s => %s/%s)\n", lval, s, range);

    if (s == NULL)
    {
        return;
    }

    if (IsNakedVar(s, '@') || IsNakedVar(s, '$'))
    {
        CfDebug("Validation: Unable to verify variable expansion of %s at this stage\n", s);
        return;
    }

    split = SplitString(range, ',');

    if (!IsItemIn(split, s))
    {
        snprintf(output, CF_BUFSIZE,
                 "Selection on rhs of lval \'%s\' given as \'%s\' is out of bounds, should be in [%s]", lval, s, range);
        ReportError(output);
        err = true;
    }

    DeleteItemList(split);

    if (!err)
    {
        CfDebug("CheckParseOpts - syntax verified\n\n");
    }
}
Example #18
0
static void ShowState(char *type)
{
    struct stat statbuf;
    char buffer[CF_BUFSIZE], vbuff[CF_BUFSIZE], assemble[CF_BUFSIZE];
    Item *addresses = NULL, *saddresses = NULL, *ip;
    int i = 0, tot = 0, min_signal_diversity = 1, conns = 1;
    int maxlen = 0, count;
    double *dist = NULL, S = 0.0;
    char *offset = NULL;
    FILE *fp;

    CfDebug("ShowState(%s)\n", type);

    snprintf(buffer, CF_BUFSIZE - 1, "%s/state/cf_%s", CFWORKDIR, type);

    if (cfstat(buffer, &statbuf) == 0)
    {
        if ((fp = fopen(buffer, "r")) == NULL)
        {
            CfOut(cf_inform, "fopen", "Could not open state memory %s\n", buffer);
            return;
        }

        while (!feof(fp))
        {
            char local[CF_BUFSIZE], remote[CF_BUFSIZE];

            buffer[0] = local[0] = remote[0] = '\0';

            memset(vbuff, 0, CF_BUFSIZE);
            fgets(buffer, CF_BUFSIZE, fp);

            if (strlen(buffer) > 0)
            {
                CfOut(cf_verbose, "", "(%2d) %s", conns, buffer);

                if (IsSocketType(type))
                {
                    if (strncmp(type, "incoming", 8) == 0 || strncmp(type, "outgoing", 8) == 0)
                    {
                        if (strncmp(buffer, "tcp", 3) == 0)
                        {
                            sscanf(buffer, "%*s %*s %*s %s %s", local, remote); /* linux-like */
                        }
                        else
                        {
                            sscanf(buffer, "%s %s", local, remote);     /* solaris-like */
                        }

                        strncpy(vbuff, remote, CF_BUFSIZE - 1);
                        DePort(vbuff);
                    }
                }
                else if (IsTCPType(type))
                {
                    count = 1;
                    sscanf(buffer, "%d %[^\n]", &count, remote);
                    AppendItem(&addresses, remote, "");
                    SetItemListCounter(addresses, remote, count);
                    conns += count;
                    continue;
                }
                else
                {
                    /* If we get here this is a process thing */
                    if (offset == NULL)
                    {
                        if ((offset = strstr(buffer, "CMD")))
                        {
                        }
                        else if ((offset = strstr(buffer, "COMMAND")))
                        {
                        }

                        if (offset == NULL)
                        {
                            continue;
                        }
                    }

                    strncpy(vbuff, offset, CF_BUFSIZE - 1);
                    Chop(vbuff);
                }

                if (!IsItemIn(addresses, vbuff))
                {
                    conns++;
                    AppendItem(&addresses, vbuff, "");
                    IncrementItemListCounter(addresses, vbuff);
                }
                else
                {
                    conns++;
                    IncrementItemListCounter(addresses, vbuff);
                }
            }
        }

        fclose(fp);
        conns--;

        CfOut(cf_error, "", "\n");
        CfOut(cf_error, "", "R: The peak measured state was q = %d:\n", conns);

        if (IsSocketType(type) || IsTCPType(type))
        {
            for (ip = addresses; ip != NULL; ip = ip->next)
            {
                tot += ip->counter;

                buffer[0] = '\0';
                sscanf(ip->name, "%s", buffer);

                if (!IsIPV4Address(buffer) && !IsIPV6Address(buffer))
                {
                    CfOut(cf_verbose, "", "Rejecting address %s\n", ip->name);
                    continue;
                }

                CfOut(cf_error, "", "R: DNS key: %s = %s (%d/%d)\n", buffer, IPString2Hostname(buffer), ip->counter,
                      conns);

                if (strlen(ip->name) > maxlen)
                {
                    maxlen = strlen(ip->name);
                }
            }

            if (addresses != NULL)
            {
                printf("R: -\n");
            }
        }
        else
        {
            for (ip = addresses; ip != NULL; ip = ip->next)
            {
                tot += ip->counter;
            }
        }

        addresses = SortItemListCounters(addresses);
        saddresses = addresses;

        for (ip = saddresses; ip != NULL; ip = ip->next)
        {
            int s;

            if (maxlen > 17)    /* ipv6 */
            {
                snprintf(assemble, CF_BUFSIZE, "Frequency: %-40s|", ip->name);
            }
            else
            {
                snprintf(assemble, CF_BUFSIZE, "Frequency: %-17s|", ip->name);
            }

            for (s = 0; (s < ip->counter) && (s < 50); s++)
            {
                if (s < 48)
                {
                    strcat(assemble, "*");
                }
                else
                {
                    strcat(assemble, "+");
                }
            }

            CfOut(cf_error, "", "R: %s \t(%d/%d)\n", assemble, ip->counter, conns);
        }

        dist = xmalloc((tot + 1) * sizeof(double));

        if (conns > min_signal_diversity)
        {
            for (i = 0, ip = addresses; ip != NULL; i++, ip = ip->next)
            {
                dist[i] = ((double) (ip->counter)) / ((double) tot);

                S -= dist[i] * log(dist[i]);
            }

            CfOut(cf_error, "", "R: Variability/entropy of addresses = %.1f %%\n", S / log((double) tot) * 100.0);
            CfOut(cf_error, "", "R: (Entropy = 0 for single source, 100 for flatly distributed source)\n -\n");
        }

        CfOut(cf_error, "", "\n");
        CfOut(cf_error, "", "R: State of %s peaked at %s\n", type, cf_ctime(&statbuf.st_mtime));
    }
    else
    {
        CfOut(cf_inform, "", "R: State parameter %s is not known or recorded\n", type);
    }

    DeleteItemList(addresses);

    if (dist)
    {
        free((char *) dist);
    }
}
Example #19
0
bool FileInRepository(const char *filename)
{
    return IsItemIn(VREPOSLIST, filename);
}
Example #20
0
void KeepPromises(Policy *policy, ExecConfig *config)
{
    bool schedule_is_specified = false;

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);

            if (IsExcluded(cp->classes, NULL))
            {
                continue;
            }

            Rval retval;
            if (GetVariable("control_executor", cp->lval, &retval) == DATA_TYPE_NONE)
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in exec control body", cp->lval);
                continue;
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailfrom].lval) == 0)
            {
                free(config->mail_from_address);
                config->mail_from_address = SafeStringDuplicate(retval.item);
                CfDebug("mailfrom = %s\n", config->mail_from_address);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailto].lval) == 0)
            {
                free(config->mail_to_address);
                config->mail_to_address = SafeStringDuplicate(retval.item);
                CfDebug("mailto = %s\n", config->mail_to_address);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_smtpserver].lval) == 0)
            {
                free(config->mail_server);
                config->mail_server = SafeStringDuplicate(retval.item);
                CfDebug("smtpserver = %s\n", config->mail_server);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_execcommand].lval) == 0)
            {
                free(config->exec_command);
                config->exec_command = SafeStringDuplicate(retval.item);
                CfDebug("exec_command = %s\n", config->exec_command);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_agent_expireafter].lval) == 0)
            {
                config->agent_expireafter = IntFromString(retval.item);
                CfDebug("agent_expireafter = %d\n", config->agent_expireafter);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_executorfacility].lval) == 0)
            {
                SetFacility(retval.item);
                continue;
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_mailmaxlines].lval) == 0)
            {
                config->mail_max_lines = IntFromString(retval.item);
                CfDebug("maxlines = %d\n", config->mail_max_lines);
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_splaytime].lval) == 0)
            {
                int time = IntFromString(RvalScalarValue(retval));

                SPLAYTIME = (int) (time * SECONDS_PER_MINUTE * GetSplay());
            }

            if (strcmp(cp->lval, CFEX_CONTROLBODY[cfex_schedule].lval) == 0)
            {
                CfDebug("Loading user-defined schedule...\n");
                DeleteItemList(SCHEDULE);
                SCHEDULE = NULL;
                schedule_is_specified = true;

                for (const Rlist *rp = retval.item; rp; rp = rp->next)
                {
                    if (!IsItemIn(SCHEDULE, rp->item))
                    {
                        AppendItem(&SCHEDULE, rp->item, NULL);
                    }
                }
            }
        }
    }

    if (!schedule_is_specified)
    {
        LoadDefaultSchedule();
    }
}
Example #21
0
static bool GetSysUsers( int *userListSz, int *numRootProcs, int *numOtherProcs)
{
    FILE *fp;
    char user[CF_BUFSIZE];
    char vbuff[CF_BUFSIZE];
    char cbuff[CF_BUFSIZE];

    /*
     * The best would be to ask only "user" field from ps, but we are asking
     * for "user,pid". The reason is that we try to mimic cf-monitord's
     * behaviour, else a different number of users might be detected by the
     * test, as printing "user,pid" truncates the user column.  TODO fix the
     * ps command to use only "-o user" in both mon_processes.c and this test.
     */
#if defined(__sun)
    xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user,pid > %s/users.txt", CFWORKDIR);
#elif defined(_AIX)
    xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -N -eo user,pid > %s/users.txt", CFWORKDIR);
#elif defined(__hpux)
    xsnprintf(cbuff, CF_BUFSIZE, "UNIX95=1  /bin/ps -eo user,pid > %s/users.txt", CFWORKDIR);
    /* SKIP on HP-UX since cf-monitord doesn't count processes correctly! */
    return false;
#else
    xsnprintf(cbuff, CF_BUFSIZE, "ps -eo user:30,pid > %s/users.txt", CFWORKDIR);
#endif

    Item *userList = NULL;
    system(cbuff);
    xsnprintf(cbuff, CF_BUFSIZE, "%s/users.txt", CFWORKDIR);
    if ((fp = fopen(cbuff, "r")) == NULL)
    {
        return false;
    }
    while (fgets(vbuff, CF_BUFSIZE, fp) != NULL)
    {
        int ret = sscanf(vbuff, " %s ", user);

        if (ret != 1 ||
            strcmp(user, "") == 0 ||
            strcmp(user, "USER") == 0 ||
            isdigit(user[0]))
        {
            continue;
        }

        if (!IsItemIn(userList, user))
        {
            PrependItem(&userList, user, NULL);
            (*userListSz)++;
        }

        if (strcmp(user, "root") == 0)
        {
            (*numRootProcs)++;
        }
        else
        {
            (*numOtherProcs)++;
        }
    }
    fclose(fp);

    if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
    {
        char *s = ItemList2CSV(userList);
        Log(LOG_LEVEL_DEBUG, "Users in the process table detected from the test: (%s)", s);
        free(s);
    }
    DeleteItemList(userList);
    return true;
}
Example #22
0
/**
 * @brief check whether the lastseen DB is coherent or not
 * 
 * A DB is coherent mainly if all the entries are valid and if there is
 * a strict one-to-one correspondance between hosts and key digests
 * (whether in MD5 or SHA1 format).
 *
 * @retval true if the lastseen DB is coherent, false otherwise
 */
bool IsLastSeenCoherent(void)
{
    DBHandle *db;
    DBCursor *cursor;
    bool res = true;

    if (!OpenDB(&db, dbid_lastseen))
    {
        Log(LOG_LEVEL_ERR, "Unable to open lastseen database");
        return false;
    }

    if (!NewDBCursor(db, &cursor))
    {
        Log(LOG_LEVEL_ERR, "Unable to create lastseen database cursor");
        CloseDB(db);
        return false;
    }

    char *key;
    void *value;
    int ksize, vsize;

    Item *qkeys=NULL;
    Item *akeys=NULL;
    Item *kkeys=NULL;
    Item *ahosts=NULL;
    Item *khosts=NULL;

    char val[CF_BUFSIZE];
    while (NextDB(cursor, &key, &ksize, &value, &vsize))
    {
        if (key[0] != 'k' && key[0] != 'q' && key[0] != 'a' )
        {
            continue;
        }

        if (key[0] == 'q' )
        {
            if (strncmp(key,"qiSHA=",5)==0 || strncmp(key,"qoSHA=",5)==0 ||
                strncmp(key,"qiMD5=",5)==0 || strncmp(key,"qoMD5=",5)==0)
            {
                if (IsItemIn(qkeys, key+2)==false)
                {
                    PrependItem(&qkeys, key+2, NULL);
                }
            }
        }

        if (key[0] == 'k' )
        {
            if (strncmp(key, "kSHA=", 4)==0 || strncmp(key, "kMD5=", 4)==0)
            {
                if (IsItemIn(kkeys, key+1)==false)
                {
                    PrependItem(&kkeys, key+1, NULL);
                }
                if (ReadDB(db, key, &val, vsize))
                {
                    if (IsItemIn(khosts, val)==false)
                    {
                        PrependItem(&khosts, val, NULL);
                    }
                }
            }
        }

        if (key[0] == 'a' )
        {
            if (IsItemIn(ahosts, key+1)==false)
            {
                PrependItem(&ahosts, key+1, NULL);
            }
            if (ReadDB(db, key, &val, vsize))
            {
                if (IsItemIn(akeys, val)==false)
                {
                    PrependItem(&akeys, val, NULL);
                }
            }
        }
    }

    DeleteDBCursor(cursor);
    CloseDB(db);

    if (ListsCompare(ahosts, khosts) == false)
    {
        res = false;
        goto clean;
    }
    if (ListsCompare(akeys, kkeys) == false)
    {
        res = false;
        goto clean;
    }

clean:
    DeleteItemList(qkeys);
    DeleteItemList(akeys);
    DeleteItemList(kkeys);
    DeleteItemList(ahosts);
    DeleteItemList(khosts);

    return res;
}
int ArchiveToRepository(char *file,struct Attributes attr,struct Promise *pp)

 /* Returns true if the file was backup up and false if not */

{ char destination[CF_BUFSIZE];
  char localrepository[CF_BUFSIZE]; 
  char node[CF_BUFSIZE];
  struct stat sb, dsb;
  char *sp;

if (attr.repository == NULL && VREPOSITORY == NULL)
   {
   return false;
   }

if (attr.repository != NULL)
   {
   strncpy(localrepository,attr.repository,CF_BUFSIZE);
   }
else if (VREPOSITORY != NULL)
   {
   strncpy(localrepository,VREPOSITORY,CF_BUFSIZE);
   }

if (attr.copy.backup == cfa_nobackup)
   {
   return true;
   }

if (IsItemIn(VREPOSLIST,file))
   {
   CfOut(cf_inform,"","The file %s has already been moved to the repository once. Multiple update will cause loss of backup.",file);
   return true;
   }

ThreadLock(cft_getaddr);
PrependItemList(&VREPOSLIST,file);
ThreadUnlock(cft_getaddr);

Debug("Repository(%s)\n",file);

strcpy (node,file);

destination[0] = '\0';

for (sp = node; *sp != '\0'; sp++)
   {
   if (*sp == FILE_SEPARATOR)
      {
      *sp = REPOSCHAR;
      }
   }

strncpy(destination,localrepository,CF_BUFSIZE-2);

if (!JoinPath(destination,node))
   {
   CfOut(cf_error,"","Internal limit: Buffer ran out of space for long filename\n");
   return false;
   }

if (!MakeParentDirectory(destination,attr.move_obstructions))
   {
   }

if (cfstat(file,&sb) == -1)
   {
   Debug("File %s promised to archive to the repository but it disappeared!\n",file);
   return true;
   }

cfstat(destination,&dsb);

attr.copy.servers = NULL;
attr.copy.backup = cfa_repos_store; // cfa_nobackup;
attr.copy.stealth = false;
attr.copy.verify = false;
attr.copy.preserve = false;

CheckForFileHoles(&sb,pp);

if (CopyRegularFileDisk(file,destination,attr,pp))
   {
   CfOut(cf_inform,"","Moved %s to repository location %s\n",file,destination);
   return true;
   }
else
   {
   CfOut(cf_inform,"","Failed to move %s to repository location %s\n",file,destination);
   return false;
   }
}
Example #24
0
static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config)
{
    CFD_MAXPROCESSES = 30;
    MAXTRIES = 5;
    DENYBADCLOCKS = true;
    CFRUNCOMMAND[0] = '\0';
    SetChecksumUpdatesDefault(ctx, true);

    /* Keep promised agent behaviour - control bodies */

    Banner("Server control promises..");

    PolicyResolve(ctx, policy, config);

    /* Now expand */

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);
#define IsControlBody(e) (strcmp(cp->lval, CFS_CONTROLBODY[e].lval) == 0)

            if (!IsDefinedClass(ctx, cp->classes))
            {
                continue;
            }

            VarRef *ref = VarRefParseFromScope(cp->lval, "control_server");
            const void *value = EvalContextVariableGet(ctx, ref, NULL);
            VarRefDestroy(ref);

            if (!value)
            {
                Log(LOG_LEVEL_ERR,
                    "Unknown lval '%s' in server control body",
                    cp->lval);
            }
            else if (IsControlBody(SERVER_CONTROL_SERVER_FACILITY))
            {
                SetFacility(value);
            }
            else if (IsControlBody(SERVER_CONTROL_DENY_BAD_CLOCKS))
            {
                DENYBADCLOCKS = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting denybadclocks to '%s'",
                    DENYBADCLOCKS ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS))
            {
                LOGENCRYPT = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting logencrypt to '%s'",
                    LOGENCRYPT ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_LOG_ALL_CONNECTIONS))
            {
                SV.logconns = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns);
            }
            else if (IsControlBody(SERVER_CONTROL_MAX_CONNECTIONS))
            {
                CFD_MAXPROCESSES = (int) IntFromString(value);
                MAXTRIES = CFD_MAXPROCESSES / 3;
                Log(LOG_LEVEL_VERBOSE,
                    "Setting maxconnections to %d",
                    CFD_MAXPROCESSES);
                /* The handling of max_readers in LMDB is not ideal, but
                 * here is how it is right now: We know that both cf-serverd and
                 * cf-hub will access the lastseen database. Worst case every
                 * single thread and process will do it at the same time, and
                 * this has in fact been observed. So we add the maximum of
                 * those two values together to provide a safe ceiling. In
                 * addition, cf-agent can access the database occasionally as
                 * well, so add a few extra for that too. */
                DBSetMaximumConcurrentTransactions(CFD_MAXPROCESSES
                                                   + EnterpriseGetMaxCfHubProcesses() + 10);
                continue;
            }
            else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_INTERVAL))
            {
                COLLECT_INTERVAL = (int) 60 * IntFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting call_collect_interval to %d (seconds)",
                    COLLECT_INTERVAL);
            }
            else if (IsControlBody(SERVER_CONTROL_LISTEN))
            {
                SERVER_LISTEN = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting server listen to '%s' ",
                    SERVER_LISTEN ? "true" : "false");
            }
            else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_WINDOW))
            {
                COLLECT_WINDOW = (int) IntFromString(value);
                Log(LOG_LEVEL_VERBOSE,
                    "Setting collect_window to %d (seconds)",
                    COLLECT_INTERVAL);
            }
            else if (IsControlBody(SERVER_CONTROL_CF_RUN_COMMAND))
            {
                strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND));
                Log(LOG_LEVEL_VERBOSE,
                    "Setting cfruncommand to '%s'",
                    CFRUNCOMMAND);
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_DENY_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_SKIP_VERIFY))
            {
                /* Skip. */
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_ALL_CONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOW_USERS))
            {
                Log(LOG_LEVEL_VERBOSE, "SET Allowing users ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_TRUST_KEYS_FROM))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOWLEGACYCONNECTS))
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp)))
                    {
                        PrependItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes);
                    }
                }
            }
            else if (IsControlBody(SERVER_CONTROL_PORT_NUMBER))
            {
                CFENGINE_PORT = IntFromString(value);
                strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR));
                Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d",
                    CFENGINE_PORT);
            }
            else if (IsControlBody(SERVER_CONTROL_BIND_TO_INTERFACE))
            {
                strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE));
                Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE);
            }
            else if (IsControlBody(SERVER_CONTROL_ALLOWCIPHERS))
            {

                SV.allowciphers = xstrdup(value);
                Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers);
            }
#undef IsControlBody
        }
    }

    const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST);
    if (value)
    {
        /* Don't resolve syslog_host now, better do it per log request. */
        if (!SetSyslogHost(value))
        {
            Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value);
        }
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT);
    if (value)
    {
        SetSyslogPort(IntFromString(value));
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE);
    if (value)
    {
        FIPS_MODE = BooleanFromString(value);
        Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false");
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER);
    if (value)
    {
        LASTSEENEXPIREAFTER = IntFromString(value) * 60;
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BWLIMIT);
    if (value)
    {
        double bval;
        if (DoubleFromString(value, &bval))
        {
            bwlimit_kbytes = (uint32_t) ( bval / 1000.0);
            Log(LOG_LEVEL_VERBOSE, "Setting rate limit to %d kBytes/sec", bwlimit_kbytes);
        }
    }

}
Example #25
0
SyntaxTypeMatch CheckConstraintTypeMatch(const char *lval, Rval rval, DataType dt, const char *range, int level)
{
 Rlist *rp;
 Item *checklist;

/* Get type of lval */

 switch (rval.type)
    {
    case RVAL_TYPE_SCALAR:
        switch (dt)
           {
           case CF_DATA_TYPE_STRING_LIST:
           case CF_DATA_TYPE_INT_LIST:
           case CF_DATA_TYPE_REAL_LIST:
           case CF_DATA_TYPE_CONTEXT_LIST:
           case CF_DATA_TYPE_OPTION_LIST:
               if (level == 0)
                  {
                  return SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR;
                  }
               break;
           default:
               /* Only lists are incompatible with scalars */
               break;
           }
        break;

    case RVAL_TYPE_LIST:

        switch (dt)
           {
           case CF_DATA_TYPE_STRING_LIST:
           case CF_DATA_TYPE_INT_LIST:
           case CF_DATA_TYPE_REAL_LIST:
           case CF_DATA_TYPE_CONTEXT_LIST:
           case CF_DATA_TYPE_OPTION_LIST:
               break;
           default:
               return SYNTAX_TYPE_MATCH_ERROR_GOT_LIST;
           }

        for (rp = (Rlist *) rval.item; rp != NULL; rp = rp->next)
           {
           SyntaxTypeMatch err = CheckConstraintTypeMatch(lval, rp->val, dt, range, 1);
           switch (err)
              {
              case SYNTAX_TYPE_MATCH_OK:
              case SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED:
                  break;

              default:
                  return err;
              }
           }

        return SYNTAX_TYPE_MATCH_OK;

    case RVAL_TYPE_FNCALL:

        /* Fn-like objects are assumed to be parameterized bundles in these... */

        checklist = SplitString("bundlesequence,edit_line,edit_xml,usebundle,service_bundle,home_bundle", ',');

        if (!IsItemIn(checklist, lval))
           {
           SyntaxTypeMatch err = CheckFnCallType(RvalFnCallValue(rval)->name, dt);
           DeleteItemList(checklist);
           return err;
           }

        DeleteItemList(checklist);
        return SYNTAX_TYPE_MATCH_OK;

    case RVAL_TYPE_CONTAINER:
        break;

    case RVAL_TYPE_NOPROMISEE:
        return SYNTAX_TYPE_MATCH_ERROR_GOT_NULL;
    }

/* If we get here, we have a literal scalar type */

 switch (dt)
    {
    case CF_DATA_TYPE_STRING:
    case CF_DATA_TYPE_STRING_LIST:
        return CheckParseString(lval, (const char *) rval.item, range);

    case CF_DATA_TYPE_INT:
    case CF_DATA_TYPE_INT_LIST:
        return CheckParseInt(lval, (const char *) rval.item, range);

    case CF_DATA_TYPE_REAL:
    case CF_DATA_TYPE_REAL_LIST:
        return CheckParseReal(lval, (const char *) rval.item, range);

    case CF_DATA_TYPE_BODY:
    case CF_DATA_TYPE_BUNDLE:
    case CF_DATA_TYPE_CONTAINER:
        break;

    case CF_DATA_TYPE_OPTION:
    case CF_DATA_TYPE_OPTION_LIST:
        return CheckParseOpts(RvalScalarValue(rval), range);

    case CF_DATA_TYPE_CONTEXT:
    case CF_DATA_TYPE_CONTEXT_LIST:
        return CheckParseContext((const char *) rval.item, range);

    case CF_DATA_TYPE_INT_RANGE:
        return CheckParseIntRange(lval, (const char *) rval.item, range);

    case CF_DATA_TYPE_REAL_RANGE:
        return CheckParseRealRange(lval, (char *) rval.item, range);

    default:
        ProgrammingError("Unknown (unhandled) datatype for lval = %s (CheckConstraintTypeMatch)", lval);
        break;
    }

 return SYNTAX_TYPE_MATCH_OK;
}
Example #26
0
File: server.c Project: tzz/core
void ServerEntryPoint(EvalContext *ctx, char *ipaddr, ConnectionInfo *info)
{
    char intime[64];
    time_t now;

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

    if ((SV.nonattackerlist) && (!IsMatchItemIn(SV.nonattackerlist, MapAddress(ipaddr))))
    {
        Log(LOG_LEVEL_ERR, "Not allowing connection from non-authorized IP '%s'", ipaddr);
        cf_closesocket(ConnectionInfoSocket(info));
        ConnectionInfoDestroy(&info);
        return;
    }

    if (IsMatchItemIn(SV.attackerlist, MapAddress(ipaddr)))
    {
        Log(LOG_LEVEL_ERR, "Denying connection from non-authorized IP '%s'", ipaddr);
        cf_closesocket(ConnectionInfoSocket(info));
        ConnectionInfoDestroy(&info);
        return;
    }

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

    PurgeOldConnections(&SV.connectionlist, now);

    if (!IsMatchItemIn(SV.multiconnlist, MapAddress(ipaddr)))
    {
        if (!ThreadLock(cft_count))
        {
            return;
        }

        if (IsItemIn(SV.connectionlist, MapAddress(ipaddr)))
        {
            ThreadUnlock(cft_count);
            Log(LOG_LEVEL_ERR, "Denying repeated connection from '%s'", ipaddr);
            cf_closesocket(ConnectionInfoSocket(info));
            ConnectionInfoDestroy(&info);
            return;
        }

        ThreadUnlock(cft_count);
    }

    if (SV.logconns)
    {
        Log(LOG_LEVEL_INFO, "Accepting connection from %s", ipaddr);
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Accepting connection from %s", ipaddr);
    }

    snprintf(intime, 63, "%d", (int) now);

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

    PrependItem(&SV.connectionlist, MapAddress(ipaddr), intime);

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

    SpawnConnection(ctx, ipaddr, info);

}
Example #27
0
static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config)
{
    CFD_MAXPROCESSES = 30;
    MAXTRIES = 5;
    DENYBADCLOCKS = true;
    CFRUNCOMMAND[0] = '\0';
    SetChecksumUpdatesDefault(ctx, true);

/* Keep promised agent behaviour - control bodies */

    Banner("Server control promises..");

    PolicyResolve(ctx, policy, config);

/* Now expand */

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);

            if (!IsDefinedClass(ctx, cp->classes))
            {
                continue;
            }

            VarRef *ref = VarRefParseFromScope(cp->lval, "control_server");
            const void *value = EvalContextVariableGet(ctx, ref, NULL);
            VarRefDestroy(ref);

            if (!value)
            {
                Log(LOG_LEVEL_ERR, "Unknown lval '%s' in server control body", cp->lval);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SERVER_FACILITY].lval) == 0)
            {
                SetFacility(value);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_BAD_CLOCKS].lval) == 0)
            {
                DENYBADCLOCKS = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting denybadclocks to '%s'", DENYBADCLOCKS ? "true" : "false");
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS].lval) == 0)
            {
                LOGENCRYPT = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting logencrypt to '%s'", LOGENCRYPT ? "true" : "false");
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ALL_CONNECTIONS].lval) == 0)
            {
                SV.logconns = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_MAX_CONNECTIONS].lval) == 0)
            {
                CFD_MAXPROCESSES = (int) IntFromString(value);
                MAXTRIES = CFD_MAXPROCESSES / 3;
                Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFD_MAXPROCESSES);
#ifdef LMDB
                static int LSD_MAXREADERS = 0;
                if (LSD_MAXREADERS < CFD_MAXPROCESSES)
                {
                    int rc = UpdateLastSeenMaxReaders(CFD_MAXPROCESSES);
                    if (rc == 0)
                    {
                        LSD_MAXREADERS = CFD_MAXPROCESSES;
                    }
                }
#endif
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_INTERVAL].lval) == 0)
            {
                COLLECT_INTERVAL = (int) 60 * IntFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting call_collect_interval to %d (seconds)", COLLECT_INTERVAL);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LISTEN].lval) == 0)
            {
                SERVER_LISTEN = BooleanFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting server listen to '%s' ",
                      (SERVER_LISTEN)? "true":"false");
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_WINDOW].lval) == 0)
            {
                COLLECT_WINDOW = (int) IntFromString(value);
                Log(LOG_LEVEL_VERBOSE, "Setting collect_window to %d (seconds)", COLLECT_INTERVAL);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CF_RUN_COMMAND].lval) == 0)
            {
                strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND));
                Log(LOG_LEVEL_VERBOSE, "Setting cfruncommand to '%s'", CFRUNCOMMAND);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_CONNECTS].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_CONNECTS].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SKIP_VERIFY].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_ALL_CONNECTS].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_USERS].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "SET Allowing users ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_TRUST_KEYS_FROM].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWLEGACYCONNECTS].lval) == 0)
            {
                Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ...");

                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                {
                    if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp)))
                    {
                        AppendItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes);
                    }
                }

                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_PORT_NUMBER].lval) == 0)
            {
                CFENGINE_PORT = IntFromString(value);
                strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR));
                Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d",
                    CFENGINE_PORT);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_BIND_TO_INTERFACE].lval) == 0)
            {
                strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE));
                Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE);
                continue;
            }

            if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWCIPHERS].lval) == 0)
            {

                SV.allowciphers = xstrdup(value);
                Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers);
                continue;
            }
        }
    }

    const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST);
    if (value)
    {
        /* Don't resolve syslog_host now, better do it per log request. */
        if (!SetSyslogHost(value))
        {
            Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value);
        }
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT);
    if (value)
    {
        SetSyslogPort(IntFromString(value));
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE);
    if (value)
    {
        FIPS_MODE = BooleanFromString(value);
        Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false");
    }

    value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER);
    if (value)
    {
        LASTSEENEXPIREAFTER = IntFromString(value) * 60;
    }
}
Example #28
0
void NoteClassUsage(AlphaList baselist, int purge)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    void *stored;
    char *key;
    int ksize, vsize;
    Event e, entry, newe;
    double lsea = SECONDS_PER_WEEK * 52;        /* expire after (about) a year */
    time_t now = time(NULL);
    Item *list = NULL;
    const Item *ip;
    double lastseen;
    double vtrue = 1.0;         /* end with a rough probability */

/* Only do this for the default policy, too much "downgrading" otherwise */

    if (MINUSF)
    {
        return;
    }

    AlphaListIterator it = AlphaListIteratorInit(&baselist);

    for (ip = AlphaListIteratorNext(&it); ip != NULL; ip = AlphaListIteratorNext(&it))
    {
        if ((IGNORECLASS(ip->name)))
        {
            CfDebug("Ignoring class %s (not packing)", ip->name);
            continue;
        }

        IdempPrependItem(&list, ip->name, NULL);
    }

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

/* First record the classes that are in use */

    for (ip = list; ip != NULL; ip = ip->next)
    {
        if (ReadDB(dbp, ip->name, &e, sizeof(e)))
        {
            CfDebug("FOUND %s with %lf\n", ip->name, e.Q.expect);
            lastseen = now - e.t;
            newe.t = now;

            newe.Q = QAverage(e.Q, vtrue, 0.7);
        }
        else
        {
            lastseen = 0.0;
            newe.t = now;
            /* With no data it's 50/50 what we can say */
            newe.Q = QDefinite(0.5 * vtrue);
        }

        if (lastseen > lsea)
        {
            CfDebug("Class usage record %s expired\n", ip->name);
            DeleteDB(dbp, ip->name);
        }
        else
        {
            WriteDB(dbp, ip->name, &newe, sizeof(newe));
        }
    }

/* Then update with zero the ones we know about that are not active */

    if (purge)
    {
/* Acquire a cursor for the database and downgrade classes that did not
 get defined this time*/

        if (!NewDBCursor(dbp, &dbcp))
        {
            CfOut(cf_inform, "", " !! Unable to scan class db");
            CloseDB(dbp);
            DeleteItemList(list);
            return;
        }

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

        while (NextDB(dbp, dbcp, &key, &ksize, &stored, &vsize))
        {
            time_t then;
            char eventname[CF_BUFSIZE];

            memset(eventname, 0, CF_BUFSIZE);
            strncpy(eventname, (char *) key, ksize);

            if (stored != NULL)
            {
                memcpy(&entry, stored, sizeof(entry));

                then = entry.t;
                lastseen = now - then;

                if (lastseen > lsea)
                {
                    CfDebug("Class usage record %s expired\n", eventname);
                    DBCursorDeleteEntry(dbcp);
                }
                else if (!IsItemIn(list, eventname))
                {
                    newe.t = then;

                    newe.Q = QAverage(entry.Q, 0, 0.5);

                    if (newe.Q.expect <= 0.0001)
                    {
                        CfDebug("Deleting class %s as %lf is zero\n", eventname, newe.Q.expect);
                        DBCursorDeleteEntry(dbcp);
                    }
                    else
                    {
                        CfDebug("Downgrading class %s from %lf to %lf\n", eventname, entry.Q.expect, newe.Q.expect);
                        DBCursorWriteEntry(dbcp, &newe, sizeof(newe));
                    }
                }
            }
        }

        DeleteDBCursor(dbp, dbcp);
    }

    CloseDB(dbp);
    DeleteItemList(list);
}
Example #29
0
void RotateFiles(char *name, int number)
{
    int i, fd;
    struct stat statbuf;
    char from[CF_BUFSIZE], to[CF_BUFSIZE];

    if (IsItemIn(ROTATED, name))
    {
        return;
    }

    PrependItem(&ROTATED, name, NULL);

    if (stat(name, &statbuf) == -1)
    {
        Log(LOG_LEVEL_VERBOSE, "No access to file %s", name);
        return;
    }

    for (i = number - 1; i > 0; i--)
    {
        snprintf(from, CF_BUFSIZE, "%s.%d", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.gz", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.gz", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.Z", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.Z", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.bz", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.bz", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.bz2", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.bz2", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }
    }

    snprintf(to, CF_BUFSIZE, "%s.1", name);

    if (CopyRegularFileDisk(name, to) == false)
    {
        Log(LOG_LEVEL_DEBUG, "Copy failed in RotateFiles '%s' -> '%s'", name, to);
        return;
    }

    safe_chmod(to, statbuf.st_mode);
    if (safe_chown(to, statbuf.st_uid, statbuf.st_gid))
    {
        UnexpectedError("Failed to chown %s", to);
    }
    safe_chmod(name, 0600);       /* File must be writable to empty .. */

    if ((fd = safe_creat(name, statbuf.st_mode)) == -1)
    {
        Log(LOG_LEVEL_ERR, "Failed to create new '%s' in disable(rotate). (creat: %s)",
            name, GetErrorStr());
    }
    else
    {
        if (safe_chown(name, statbuf.st_uid, statbuf.st_gid))  /* NT doesn't have fchown */
        {
            UnexpectedError("Failed to chown '%s'", name);
        }
        fchmod(fd, statbuf.st_mode);
        close(fd);
    }
}
Example #30
0
int ConsiderFile(const char *nodename, char *path, Attributes attr, Promise *pp)
{
    int i;
    struct stat statbuf;
    char vbuff[CF_BUFSIZE];
    const char *sp;

    static char *skipfiles[] =
{
        ".",
        "..",
        "lost+found",
        ".cfengine.rm",
        NULL
    };

    if (strlen(nodename) < 1)
    {
        CfOut(cf_error, "", "Empty (null) filename detected in %s\n", path);
        return true;
    }

    if (IsItemIn(SUSPICIOUSLIST, nodename))
    {
        struct stat statbuf;

        if (cfstat(nodename, &statbuf) != -1)
        {
            if (S_ISREG(statbuf.st_mode))
            {
                CfOut(cf_error, "", "Suspicious file %s found in %s\n", nodename, path);
                return false;
            }
        }
    }

    if (strcmp(nodename, "...") == 0)
    {
        CfOut(cf_verbose, "", "Possible DFS/FS cell node detected in %s...\n", path);
        return true;
    }

    for (i = 0; skipfiles[i] != NULL; i++)
    {
        if (strcmp(nodename, skipfiles[i]) == 0)
        {
            CfDebug("Filename %s/%s is classified as ignorable\n", path, nodename);
            return false;
        }
    }

    if ((strcmp("[", nodename) == 0) && (strcmp("/usr/bin", path) == 0))
    {
        if (VSYSTEMHARDCLASS == linuxx)
        {
            return true;
        }
    }

    for (sp = nodename; *sp != '\0'; sp++)
    {
        if ((*sp > 31) && (*sp < 127))
        {
            break;
        }
    }

    strcpy(vbuff, path);
    AddSlash(vbuff);
    strcat(vbuff, nodename);

    for (sp = nodename; *sp != '\0'; sp++)      /* Check for files like ".. ." */
    {
        if ((*sp != '.') && !isspace(*sp))
        {
            return true;
        }
    }

    if (cf_lstat(vbuff, &statbuf, attr, pp) == -1)
    {
        CfOut(cf_verbose, "lstat", "Couldn't stat %s", vbuff);
        return true;
    }

    if (statbuf.st_size == 0 && !(VERBOSE || INFORM))   /* No sense in warning about empty files */
    {
        return false;
    }

    CfOut(cf_error, "", "Suspicious looking file object \"%s\" masquerading as hidden file in %s\n", nodename, path);
    CfDebug("Filename looks suspicious\n");

    if (S_ISLNK(statbuf.st_mode))
    {
        CfOut(cf_inform, "", "   %s is a symbolic link\n", nodename);
    }
    else if (S_ISDIR(statbuf.st_mode))
    {
        CfOut(cf_inform, "", "   %s is a directory\n", nodename);
    }

    CfOut(cf_verbose, "", "[%s] has size %ld and full mode %o\n", nodename, (unsigned long) (statbuf.st_size),
          (unsigned int) (statbuf.st_mode));
    return true;
}