Example #1
0
static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range)
{
    Item *split, *rangep, *ip;
    double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val;
    int n;

    if (*s == '[' || *s == '(')
    {
        return SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED;
    }

    if (strcmp(s, "inf") == 0)
    {
        return SYNTAX_TYPE_MATCH_ERROR_REAL_INF;
    }

    if (IsCf3VarString(s))
    {
        return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED;
    }

/* Numeric types are registered by range separated by comma str "min,max" */

    split = SplitString(range, ',');

    if ((n = ListLen(split)) != 2)
    {
        ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n);
    }

    sscanf(split->name, "%lf", &min);
    sscanf(split->next->name, "%lf", &max);
    DeleteItemList(split);

    if (min == CF_HIGHINIT || max == CF_LOWINIT)
    {
        ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval);
    }

    rangep = SplitString(s, ',');

    if ((n = ListLen(rangep)) != 2)
    {
        return SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS;
    }

    for (ip = rangep; ip != NULL; ip = ip->next)
    {
        if (!DoubleFromString(ip->name, &val))
        {
            return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
        }

        if (val > max || val < min)
        {
            return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE;
        }
    }

    DeleteItemList(rangep);

    return SYNTAX_TYPE_MATCH_OK;
}
Example #2
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 DATA_TYPE_STRING_LIST:
        case DATA_TYPE_INT_LIST:
        case DATA_TYPE_REAL_LIST:
        case DATA_TYPE_CONTEXT_LIST:
        case 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 DATA_TYPE_STRING_LIST:
        case DATA_TYPE_INT_LIST:
        case DATA_TYPE_REAL_LIST:
        case DATA_TYPE_CONTEXT_LIST:
        case 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:
    case RVAL_TYPE_NOPROMISEE:
        break;
    }

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

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

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

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

    case DATA_TYPE_BODY:
    case DATA_TYPE_BUNDLE:
    case DATA_TYPE_CONTAINER:
        break;

    case DATA_TYPE_OPTION:
    case DATA_TYPE_OPTION_LIST:
        return CheckParseOpts(RvalScalarValue(rval), range);

    case DATA_TYPE_CONTEXT:
    case DATA_TYPE_CONTEXT_LIST:
        return CheckParseContext((const char *) rval.item, range);

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

    case 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 #3
0
static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range)
{
    Item *split, *ip, *rangep;
    int n;
    long max = CF_LOWINIT, min = CF_HIGHINIT, val;

    // Numeric types are registered by range separated by comma str "min,max"
    if (*s == '[' || *s == '(')
    {
        return SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED;
    }

    split = SplitString(range, ',');

    if ((n = ListLen(split)) != 2)
    {
        ProgrammingError("Format specifier %s for irange rvalues is not ok for lval %s - got %d items", range, lval, n);
    }

    sscanf(split->name, "%ld", &min);

    if (strcmp(split->next->name, "inf") == 0)
    {
        max = CF_INFINITY;
    }
    else
    {
        sscanf(split->next->name, "%ld", &max);
    }

    DeleteItemList(split);

    if (min == CF_HIGHINIT || max == CF_LOWINIT)
    {
        ProgrammingError("Could not parse irange format specifier for int rvalues for lval %s", lval);
    }

    if (IsCf3VarString(s))
    {
        return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED;
    }

    rangep = SplitString(s, ',');

    if ((n = ListLen(rangep)) != 2)
    {
        return SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS;
    }

    for (ip = rangep; ip != NULL; ip = ip->next)
    {
        val = IntFromString(ip->name);

        if (val > max || val < min)
        {
            return SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE;
        }
    }

    DeleteItemList(rangep);

    return SYNTAX_TYPE_MATCH_OK;
}
Example #4
0
static Item *MonReSample(EvalContext *ctx, int slot, Attributes a, const Promise *pp, PromiseResult *result)
{
 CfLock thislock;
 char eventname[CF_BUFSIZE];
 char comm[20];
 struct timespec start;
 FILE *fin = NULL;
 mode_t maskval = 0;
 
 if (a.measure.stream_type && strcmp(a.measure.stream_type, "pipe") == 0)
    {
    if (!IsExecutable(CommandArg0(pp->promiser)))
       {
       cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "%s promises to be executable but isn't\n", pp->promiser);
       *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL);
       return NULL;
       }
    else
       {
       Log(LOG_LEVEL_VERBOSE, "Promiser string contains a valid executable (%s) - ok", CommandArg0(pp->promiser));
       }
    }
 
 TransactionContext tc =
     {
     .expireafter = a.transaction.expireafter,
     .ifelapsed = MONITOR_RESTARTED ? 0 : a.transaction.ifelapsed, // Force a measurement if restarted
     };
 
 CFSTARTTIME = time(NULL);
 
 thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false);
 
 if (thislock.lock == NULL)
    {
    if (a.measure.history_type && (strcmp(a.measure.history_type, "log") == 0))
       {
       DeleteItemList(ENTERPRISE_DATA[slot].output);
       ENTERPRISE_DATA[slot].output = NULL;
       }
    else
       {
       /* If static or time-series, and too soon or busy then use a cached value
          to avoid artificial gaps in the history */
       }
    
    MONITOR_RESTARTED = false;
    return ENTERPRISE_DATA[slot].output;
    }
 else
    {
    DeleteItemList(ENTERPRISE_DATA[slot].output);
    ENTERPRISE_DATA[slot].output = NULL;
    
    Log(LOG_LEVEL_INFO, "Sampling \'%s\' ...(timeout=%d,owner=%ju,group=%ju)", pp->promiser, a.contain.timeout,
        (uintmax_t)a.contain.owner, (uintmax_t)a.contain.group);
    
    start = BeginMeasure();
    
    CommandPrefix(pp->promiser, comm);
    
    if (a.contain.timeout != 0)
       {
       SetTimeOut(a.contain.timeout);
       }
    
    /* Stream types */
    
    if (a.measure.stream_type && strcmp(a.measure.stream_type, "file") == 0)
       {
       long filepos = 0;
       struct stat sb;
       
       Log(LOG_LEVEL_VERBOSE, "Stream \"%s\" is a plain file", pp->promiser);
       
       if (stat(pp->promiser, &sb) == -1)
          {
          Log(LOG_LEVEL_INFO, "Unable to find stream '%s'. (stat: %s)", pp->promiser, GetErrorStr());
          YieldCurrentLock(thislock);
          MONITOR_RESTARTED = false;
          return NULL;
          }

       fin = safe_fopen(pp->promiser, "r");
       
       if (a.measure.growing)
          {
          filepos = Mon_RestoreFilePosition(pp->promiser);
          
          if (sb.st_size >= filepos)
             {
             fseek(fin, filepos, SEEK_SET);
             }
          }
       }
    else if (a.measure.stream_type && strcmp(a.measure.stream_type, "pipe") == 0)
       {
       Log(LOG_LEVEL_VERBOSE, "(Setting pipe umask to %jo)", (uintmax_t)a.contain.umask);
       maskval = umask(a.contain.umask);
       
       if (a.contain.umask == 0)
          {
          Log(LOG_LEVEL_VERBOSE, "Programming %s running with umask 0! Use umask= to set", pp->promiser);
          }
       
       
       // Mark: This is strange that we used these wrappers. Currently no way of setting these
       a.contain.owner = -1;
       a.contain.group = -1;
       a.contain.chdir = NULL;
       a.contain.chroot = NULL;
       // Mark: they were unset, and would fail for non-root(!)
       
       if (a.contain.shelltype == SHELL_TYPE_POWERSHELL)
          {
#ifdef __MINGW32__
          fin =
              cf_popen_powershell_setuid(pp->promiser, "r", a.contain.owner, a.contain.group, a.contain.chdir,
                                         a.contain.chroot, false);
#else // !__MINGW32__
          Log(LOG_LEVEL_ERR, "Powershell is only supported on Windows");
          YieldCurrentLock(thislock);
          MONITOR_RESTARTED = false;
          return NULL;
#endif // !__MINGW32__
          }
       else if (a.contain.shelltype == SHELL_TYPE_USE)
          {
          fin = cf_popen_shsetuid(pp->promiser, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot, false);
          }
       else
          {
          fin =
              cf_popensetuid(pp->promiser, "r", a.contain.owner, a.contain.group, a.contain.chdir,
                             a.contain.chroot, false);
          }
       }
    
    /* generic file stream */
    
    if (fin == NULL)
       {
       cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a,
            "Couldn't open pipe to command '%s'. (cf_popen: %s)", pp->promiser, GetErrorStr());
       *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL);
       YieldCurrentLock(thislock);
       MONITOR_RESTARTED = false;
       return ENTERPRISE_DATA[slot].output;
       }
    
    size_t line_size = CF_BUFSIZE;
    char *line = xmalloc(line_size);
    
    for (;;)
       {
       ssize_t res = CfReadLine(&line, &line_size, fin);
       if (res == -1)
          {
          if (!feof(fin))
             {
             cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_TIMEOUT, pp, a, "Sample stream '%s'. (fread: %s)",
                  pp->promiser, GetErrorStr());
             *result = PromiseResultUpdate(*result, PROMISE_RESULT_TIMEOUT);
             YieldCurrentLock(thislock);
             free(line);
             return ENTERPRISE_DATA[slot].output;
             }
          else
             {
             break;
             }
          }
       
       AppendItem(&(ENTERPRISE_DATA[slot].output), line, NULL);
       }
    
    free(line);
    
    if (a.measure.stream_type && strcmp(a.measure.stream_type, "file") == 0)
       {
       long fileptr = ftell(fin);
       
       fclose(fin);
       Mon_SaveFilePosition(pp->promiser, fileptr);
       }
    else if (a.measure.stream_type && strcmp(a.measure.stream_type, "pipe") == 0)
       {
       cf_pclose(fin);
       }
    }
 
 if (a.contain.timeout != 0)
    {
    alarm(0);
    signal(SIGALRM, SIG_DFL);
    }
 
 Log(LOG_LEVEL_INFO, "Collected sample of %s", pp->promiser);
 umask(maskval);
 YieldCurrentLock(thislock);
 MONITOR_RESTARTED = false;
 
 snprintf(eventname, CF_BUFSIZE - 1, "Sample(%s)", pp->promiser);
 EndMeasure(eventname, start);
 return ENTERPRISE_DATA[slot].output;
}

/************************************************************************************/

void HistoryUpdate(EvalContext *ctx, Averages newvals)
{
 CfLock thislock;
 time_t now = time(NULL);
 
/* We do this only once per hour - this should not be changed */
 
 Log(LOG_LEVEL_VERBOSE, "(Updating long-term history database)");
 
 Policy *history_db_policy = PolicyNew();
 Promise *pp = NULL;
 Bundle *bp = PolicyAppendBundle(history_db_policy, NamespaceDefault(), "history_db_bundle", "agent", NULL, NULL);
 PromiseType *tp = BundleAppendPromiseType(bp, "history_db");
 
 pp = PromiseTypeAppendPromise(tp, "the long term memory", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL);
 assert(pp);
 
 TransactionContext tc =
     {
         .expireafter = 0,
         .ifelapsed = 59
     };
 
 thislock = AcquireLock(ctx, pp->promiser, VUQNAME, now, tc, pp, false);
 
 if (thislock.lock == NULL)
    {
    PolicyDestroy(history_db_policy);
    return;
    }
 
/* Refresh the class context of the agent */
 
 EvalContextClear(ctx);
 
 DetectEnvironment(ctx);
 time_t t = SetReferenceTime();
 UpdateTimeClasses(ctx, t);
 
 EvalContextHeapPersistentLoadAll(ctx);
 LoadSystemConstants(ctx);
 
 YieldCurrentLock(thislock);
 PolicyDestroy(history_db_policy);
 
 Mon_HistoryUpdate(CFSTARTTIME, &newvals); 
 Mon_DumpSlowlyVaryingObservations();

}

/************************************************************************************/

static Item *MonGetMeasurementStream(EvalContext *ctx, Attributes a, const Promise *pp, PromiseResult *result)
{
 int i;
 
 for (i = 0; i < CF_DUNBAR_WORK; i++)
    {
    if (ENTERPRISE_DATA[i].path == NULL)
       {
       break;
       }
    
    if (strcmp(ENTERPRISE_DATA[i].path, pp->promiser) == 0)
       {
       ENTERPRISE_DATA[i].output = MonReSample(ctx, i, a, pp, result);
       return ENTERPRISE_DATA[i].output;
       }
    }
 
 ENTERPRISE_DATA[i].path = xstrdup(pp->promiser);
 ENTERPRISE_DATA[i].output = MonReSample(ctx, i, a, pp, result);
 return ENTERPRISE_DATA[i].output;
}
Example #5
0
static void MonLogSymbolicValue(EvalContext *ctx, const char *handle, Item *stream,
                                 Attributes a, const Promise *pp, PromiseResult *result)
{
 char value[CF_BUFSIZE], sdate[CF_MAXVARSIZE], filename[CF_BUFSIZE], *v;
 int count = 1, found = false, match_count = 0;
 Item *ip, *match = NULL, *matches = NULL;
 time_t now = time(NULL);
 FILE *fout;
 
 if (stream == NULL)
    {
    Log(LOG_LEVEL_VERBOSE, "No stream to measure");
    return;
    }
 
 Log(LOG_LEVEL_VERBOSE, "Locate and log sample ...");
 
 for (ip = stream; ip != NULL; ip = ip->next)
    {
    if (ip->name == NULL)
       {
       continue;
       }
    
    if (count == a.measure.select_line_number)
       {
       Log(LOG_LEVEL_VERBOSE, "Found line %d by number...", count);
       found = true;
       match_count = 1;
       match = ip;
       
       if (a.measure.extraction_regex)
          {
          Log(LOG_LEVEL_VERBOSE, "Now looking for a matching extractor \"%s\"", a.measure.extraction_regex);
          strncpy(value, ExtractFirstReference(a.measure.extraction_regex, match->name), CF_MAXVARSIZE - 1);
          Log(LOG_LEVEL_INFO, "Extracted value \"%s\" for promise \"%s\"", value, handle);
          AppendItem(&matches, value, NULL);
          
          }
       break;
       }
    
    if (a.measure.select_line_matching && StringMatchFull(a.measure.select_line_matching, ip->name))
       {
       Log(LOG_LEVEL_VERBOSE, "Found line %d by pattern...", count);
       found = true;
       match = ip;
       match_count++;
       
       if (a.measure.extraction_regex)
          {
          Log(LOG_LEVEL_VERBOSE, "Now looking for a matching extractor \"%s\"", a.measure.extraction_regex);
          strncpy(value, ExtractFirstReference(a.measure.extraction_regex, match->name), CF_MAXVARSIZE - 1);
          Log(LOG_LEVEL_INFO, "Extracted value \"%s\" for promise \"%s\"", value, handle);
          AppendItem(&matches, value, NULL);
          }
       }
    
    count++;
    }
 
 if (!found)
    {
    cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promiser '%s' found no matching line.", pp->promiser);
    *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL);
    return;
    }
 
 if (match_count > 1)
    {
    Log(LOG_LEVEL_INFO, "Warning: %d lines matched the line_selection \"%s\"- matching to last", match_count,
        a.measure.select_line_matching);
    }
 
 switch (a.measure.data_type)
    {
    case CF_DATA_TYPE_COUNTER:
        Log(LOG_LEVEL_VERBOSE, "Counted %d for %s", match_count, handle);
        snprintf(value, CF_MAXVARSIZE, "%d", match_count);
        break;
        
    case CF_DATA_TYPE_STRING_LIST:
        v = ItemList2CSV(matches);
        snprintf(value, CF_BUFSIZE, "%s", v);
        free(v);
        break;
        
    default:
        snprintf(value, CF_BUFSIZE, "%s", matches->name);
    }
 
 DeleteItemList(matches);
 
 if (a.measure.history_type && strcmp(a.measure.history_type, "log") == 0)
    {
    snprintf(filename, CF_BUFSIZE, "%s%cstate%c%s_measure.log", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, handle);
    
    if ((fout = fopen(filename, "a")) == NULL)
       {
       cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to open the output log \"%s\"", filename);
       *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL);
       PromiseRef(LOG_LEVEL_ERR, pp);
       return;
       }
    
    strncpy(sdate, ctime(&now), CF_MAXVARSIZE - 1);
    if (Chop(sdate, CF_EXPANDSIZE) == -1)
       {
       Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator");
       }
    
    fprintf(fout, "%s,%ld,%s\n", sdate, (long) now, value);
    Log(LOG_LEVEL_VERBOSE, "Logging: %s,%s to %s", sdate, value, filename);
    
    fclose(fout);
    }
 else                        // scalar or static
    {
    CF_DB *dbp;
    char id[CF_MAXVARSIZE];
    
    if (!OpenDB(&dbp, dbid_static))
       {
       return;
       }
    
    snprintf(id, CF_MAXVARSIZE - 1, "%s:%d", handle, a.measure.data_type);
    WriteDB(dbp, id, value, strlen(value) + 1);
    CloseDB(dbp);
    }
}
Example #6
0
File: unix.c Project: dnaeon/core
int Unix_LoadProcessTable(Item **procdata)
{
    FILE *prp;
    char pscomm[CF_MAXLINKSIZE], vbuff[CF_BUFSIZE], *sp;
    Item *rootprocs = NULL;
    Item *otherprocs = NULL;
    const char *psopts = GetProcessOptions();

    snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", VPSCOMM[VSYSTEMHARDCLASS], psopts);

    CfOut(cf_verbose, "", "Observe process table with %s\n", pscomm);

    if ((prp = cf_popen(pscomm, "r")) == NULL)
    {
        CfOut(cf_error, "popen", "Couldn't open the process list with command %s\n", pscomm);
        return false;
    }

    while (!feof(prp))
    {
        memset(vbuff, 0, CF_BUFSIZE);
        CfReadLine(vbuff, CF_BUFSIZE, prp);

        for (sp = vbuff + strlen(vbuff) - 1; sp > vbuff && isspace(*sp); sp--)
        {
            *sp = '\0';
        }

        if (ForeignZone(vbuff))
        {
            continue;
        }

        AppendItem(procdata, vbuff, "");
    }

    cf_pclose(prp);

/* Now save the data */

    snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_procs", CFWORKDIR);
    RawSaveItemList(*procdata, vbuff);

    CopyList(&rootprocs, *procdata);
    CopyList(&otherprocs, *procdata);

    while (DeleteItemNotContaining(&rootprocs, "root"))
    {
    }

    while (DeleteItemContaining(&otherprocs, "root"))
    {
    }

    if (otherprocs)
    {
        PrependItem(&rootprocs, otherprocs->name, NULL);
    }

    snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_rootprocs", CFWORKDIR);
    RawSaveItemList(rootprocs, vbuff);
    DeleteItemList(rootprocs);

    snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_otherprocs", CFWORKDIR);
    RawSaveItemList(otherprocs, vbuff);
    DeleteItemList(otherprocs);

    return true;
}
Example #7
0
File: unix.c Project: dnaeon/core
void Unix_FindV6InterfaceInfo(void)
{
    FILE *pp = NULL;
    char buffer[CF_BUFSIZE];

/* Whatever the manuals might say, you cannot get IPV6
   interface configuration from the ioctls. This seems
   to be implemented in a non standard way across OSes
   BSDi has done getifaddrs(), solaris 8 has a new ioctl, Stevens
   book shows the suggestion which has not been implemented...
*/

    CfOut(cf_verbose, "", "Trying to locate my IPv6 address\n");

    switch (VSYSTEMHARDCLASS)
    {
    case cfnt:
        /* NT cannot do this */
        return;

    case irix:
    case irix4:
    case irix64:

        if ((pp = cf_popen("/usr/etc/ifconfig -a", "r")) == NULL)
        {
            CfOut(cf_verbose, "", "Could not find interface info\n");
            return;
        }

        break;

    case hp:

        if ((pp = cf_popen("/usr/sbin/ifconfig -a", "r")) == NULL)
        {
            CfOut(cf_verbose, "", "Could not find interface info\n");
            return;
        }

        break;

    case aix:

        if ((pp = cf_popen("/etc/ifconfig -a", "r")) == NULL)
        {
            CfOut(cf_verbose, "", "Could not find interface info\n");
            return;
        }

        break;

    default:

        if ((pp = cf_popen("/sbin/ifconfig -a", "r")) == NULL)
        {
            CfOut(cf_verbose, "", "Could not find interface info\n");
            return;
        }

    }

/* Don't know the output format of ifconfig on all these .. hope for the best*/

    while (!feof(pp))
    {
        fgets(buffer, CF_BUFSIZE - 1, pp);

        if (ferror(pp))         /* abortable */
        {
            break;
        }

        if (strcasestr(buffer, "inet6"))
        {
            Item *ip, *list = NULL;
            char *sp;

            list = SplitStringAsItemList(buffer, ' ');

            for (ip = list; ip != NULL; ip = ip->next)
            {
                for (sp = ip->name; *sp != '\0'; sp++)
                {
                    if (*sp == '/')     /* Remove CIDR mask */
                    {
                        *sp = '\0';
                    }
                }

                if (IsIPV6Address(ip->name) && (strcmp(ip->name, "::1") != 0))
                {
                    CfOut(cf_verbose, "", "Found IPv6 address %s\n", ip->name);
                    AppendItem(&IPADDRESSES, ip->name, "");
                    NewClass(ip->name);
                }
            }

            DeleteItemList(list);
        }
    }

    cf_pclose(pp);
}
Example #8
0
void NoteClassUsage(StringSetIterator context_iterator, 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;
    }

    // TODO: stupid, please simplify
    {
        char *context = NULL;
        while ((context = StringSetIteratorNext(&context_iterator)))
        {
            if ((IsContextIgnorableForReporting(context)))
            {
                CfDebug("Ignoring class %s (not packing)", context);
                continue;
            }

            IdempPrependItem(&list, context, 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));
        }
    }

    CloseDB(dbp);

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

/* 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))
        {
            Log(LOG_LEVEL_INFO, "Unable to scan class db");
            CloseDB(dbp);
            DeleteItemList(list);
            return;
        }

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

        while (NextDB(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(dbcp);
    }

    CloseDB(dbp);
    DeleteItemList(list);
}
Example #9
0
int LoadProcessTable()
{
    FILE *prp;
    char pscomm[CF_MAXLINKSIZE];
    Item *rootprocs = NULL;
    Item *otherprocs = NULL;


    if (PROCESSTABLE)
    {
        Log(LOG_LEVEL_VERBOSE, "Reusing cached process table");
        return true;
    }

    LoadPlatformExtraTable();

    CheckPsLineLimitations();

    const char *psopts = GetProcessOptions();

    snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", VPSCOMM[VPSHARDCLASS], psopts);

    Log(LOG_LEVEL_VERBOSE, "Observe process table with %s", pscomm);

    if ((prp = cf_popen(pscomm, "r", false)) == NULL)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open the process list with command '%s'. (popen: %s)", pscomm, GetErrorStr());
        return false;
    }

    size_t vbuff_size = CF_BUFSIZE;
    char *vbuff = xmalloc(vbuff_size);

# ifdef HAVE_GETZONEID

    char *names[CF_PROCCOLS];
    int start[CF_PROCCOLS];
    int end[CF_PROCCOLS];
    Seq *pidlist = SeqNew(1, NULL);
    Seq *rootpidlist = SeqNew(1, NULL);
    bool global_zone = IsGlobalZone();

    if (global_zone)
    {
        int res = ZLoadProcesstable(pidlist, rootpidlist);

        if (res == false)
        {
            Log(LOG_LEVEL_ERR, "Unable to load solaris zone process table.");
            return false;
        }
    }

# endif

    ARG_UNUSED bool header = true;           /* used only if HAVE_GETZONEID */

    for (;;)
    {
        ssize_t res = CfReadLine(&vbuff, &vbuff_size, prp);
        if (res == -1)
        {
            if (!feof(prp))
            {
                Log(LOG_LEVEL_ERR, "Unable to read process list with command '%s'. (fread: %s)", pscomm, GetErrorStr());
                cf_pclose(prp);
                free(vbuff);
                return false;
            }
            else
            {
                break;
            }
        }
        Chop(vbuff, vbuff_size);

# ifdef HAVE_GETZONEID

        if (global_zone)
        {
            if (header)
            {   /* this is the banner so get the column header names for later use*/
                GetProcessColumnNames(vbuff, &names[0], start, end);
            }
            else
            {
               int gpid = ExtractPid(vbuff, names, end);

               if (!IsGlobalProcess(gpid, pidlist, rootpidlist))
               {
                    continue;
               }
            }
        }

# endif
        AppendItem(&PROCESSTABLE, vbuff, "");

        header = false;
    }

    cf_pclose(prp);

/* Now save the data */
    const char* const statedir = GetStateDir();

    snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_procs", statedir, FILE_SEPARATOR);
    RawSaveItemList(PROCESSTABLE, vbuff, NewLineMode_Unix);

# ifdef HAVE_GETZONEID
    if (global_zone) /* pidlist and rootpidlist are empty if we're not in the global zone */
    {
        Item *ip = PROCESSTABLE;
        while (ip != NULL)
        {
            ZCopyProcessList(&rootprocs, ip, rootpidlist, names, end);
            ip = ip->next;
        }
        ReverseItemList(rootprocs);
        ip = PROCESSTABLE;
        while (ip != NULL)
        {
            ZCopyProcessList(&otherprocs, ip, pidlist, names, end);
            ip = ip->next;
        }
        ReverseItemList(otherprocs);
    }
    else
# endif
    {
        CopyList(&rootprocs, PROCESSTABLE);
        CopyList(&otherprocs, PROCESSTABLE);

        while (DeleteItemNotContaining(&rootprocs, "root"))
        {
        }

        while (DeleteItemContaining(&otherprocs, "root"))
        {
        }
    }
    if (otherprocs)
    {
        PrependItem(&rootprocs, otherprocs->name, NULL);
    }

    snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_rootprocs", statedir, FILE_SEPARATOR);
    RawSaveItemList(rootprocs, vbuff, NewLineMode_Unix);
    DeleteItemList(rootprocs);

    snprintf(vbuff, CF_MAXVARSIZE, "%s%ccf_otherprocs", statedir, FILE_SEPARATOR);
    RawSaveItemList(otherprocs, vbuff, NewLineMode_Unix);
    DeleteItemList(otherprocs);

    free(vbuff);
    return true;
}
Example #10
0
static void ArmClasses(Averages av, char *timekey)
{
    double sigma;
    Item *ip,*classlist = NULL;
    int i, j, k;
    char buff[CF_BUFSIZE], ldt_buff[CF_BUFSIZE], name[CF_MAXVARSIZE];
    static int anomaly[CF_OBSERVABLES][LDT_BUFSIZE];
    extern Item *ALL_INCOMING;
    extern Item *MON_UDP4, *MON_UDP6, *MON_TCP4, *MON_TCP6;

    for (i = 0; i < CF_OBSERVABLES; i++)
    {
        char desc[CF_BUFSIZE];

        GetObservable(i, name, desc);
        sigma = SetClasses(name, CF_THIS[i], av.Q[i].expect, av.Q[i].var, LOCALAV.Q[i].expect, LOCALAV.Q[i].var, &classlist, timekey);
        SetVariable(name, CF_THIS[i], av.Q[i].expect, sigma, &classlist);

        /* LDT */

        ldt_buff[0] = '\0';

        anomaly[i][LDT_POS] = false;

        if (!LDT_FULL)
        {
            anomaly[i][LDT_POS] = false;
        }

        if (LDT_FULL && (CHI[i] > CHI_LIMIT[i]))
        {
            anomaly[i][LDT_POS] = true; /* Remember the last anomaly value */

            Log(LOG_LEVEL_VERBOSE, "LDT(%d) in %s chi = %.2f thresh %.2f ", LDT_POS, name, CHI[i], CHI_LIMIT[i]);

            /* Last printed element is now */

            for (j = LDT_POS + 1, k = 0; k < LDT_BUFSIZE; j++, k++)
            {
                if (j == LDT_BUFSIZE)   /* Wrap */
                {
                    j = 0;
                }

                if (anomaly[i][j])
                {
                    snprintf(buff, CF_BUFSIZE, " *%.2f*", LDT_BUF[i][j]);
                }
                else
                {
                    snprintf(buff, CF_BUFSIZE, " %.2f", LDT_BUF[i][j]);
                }

                strcat(ldt_buff, buff);
            }

            if (CF_THIS[i] > av.Q[i].expect)
            {
                snprintf(buff, CF_BUFSIZE, "%s_high_ldt", name);
            }
            else
            {
                snprintf(buff, CF_BUFSIZE, "%s_high_ldt", name);
            }

            AppendItem(&classlist, buff, "2");
            EvalContextHeapPersistentSave(buff, "measurements", CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE);
        }
        else
        {
            for (j = LDT_POS + 1, k = 0; k < LDT_BUFSIZE; j++, k++)
            {
                if (j == LDT_BUFSIZE)   /* Wrap */
                {
                    j = 0;
                }

                if (anomaly[i][j])
                {
                    snprintf(buff, CF_BUFSIZE, " *%.2f*", LDT_BUF[i][j]);
                }
                else
                {
                    snprintf(buff, CF_BUFSIZE, " %.2f", LDT_BUF[i][j]);
                }
                strcat(ldt_buff, buff);
            }
        }
    }

    SetMeasurementPromises(&classlist);

    // Report on the open ports, in various ways

    AddOpenPortsClasses("listening_ports", ALL_INCOMING, &classlist);
    AddOpenPortsClasses("listening_udp6_ports", MON_UDP6, &classlist);
    AddOpenPortsClasses("listening_udp4_ports", MON_UDP4, &classlist);
    AddOpenPortsClasses("listening_tcp6_ports", MON_TCP6, &classlist);
    AddOpenPortsClasses("listening_tcp4_ports", MON_TCP4, &classlist);

    // Port addresses

    if (ListLen(MON_TCP6) + ListLen(MON_TCP4) > 512)
    {
        Log(LOG_LEVEL_INFO, "Disabling address information of TCP ports in LISTEN state: more than 512 listening ports are detected");
    }
    else
    {
        for (ip = MON_TCP6; ip != NULL; ip=ip->next)
        {
            snprintf(buff,CF_BUFSIZE,"tcp6_port_addr[%s]=%s",ip->name,ip->classes);
            AppendItem(&classlist,buff,NULL);       
        }

        for (ip = MON_TCP4; ip != NULL; ip=ip->next)
        {
            snprintf(buff,CF_BUFSIZE,"tcp4_port_addr[%s]=%s",ip->name,ip->classes);
            AppendItem(&classlist,buff,NULL);       
        }
    }

    for (ip = MON_UDP6; ip != NULL; ip=ip->next)
    {
        snprintf(buff,CF_BUFSIZE,"udp6_port_addr[%s]=%s",ip->name,ip->classes);
        AppendItem(&classlist,buff,NULL);       
    }
    
    for (ip = MON_UDP4; ip != NULL; ip=ip->next)
    {
        snprintf(buff,CF_BUFSIZE,"udp4_port_addr[%s]=%s",ip->name,ip->classes);
        AppendItem(&classlist,buff,NULL);       
    }
    
    PublishEnvironment(classlist);

    DeleteItemList(classlist);
}
Example #11
0
static void VerifyProcessOp(Item *procdata, Attributes a, Promise *pp)
{
    int matches = 0, do_signals = true, out_of_range, killed = 0, need_to_restart = true;
    Item *killlist = NULL;

    CfDebug("VerifyProcessOp\n");

    matches = FindPidMatches(procdata, &killlist, a, pp);

/* promise based on number of matches */

    if (a.process_count.min_range != CF_NOINT)  /* if a range is specified */
    {
        if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range))
        {
            cfPS(OUTPUT_LEVEL_VERBOSE, CF_CHG, "", pp, a, " !! Process count for \'%s\' was out of promised range (%d found)\n", pp->promiser, matches);
            AddEphemeralClasses(a.process_count.out_of_range_define, pp->ns);
            out_of_range = true;
        }
        else
        {
            AddEphemeralClasses(a.process_count.in_range_define, pp->ns);
            cfPS(OUTPUT_LEVEL_VERBOSE, CF_NOP, "", pp, a, " -> Process promise for %s is kept", pp->promiser);
            out_of_range = false;
        }
    }
    else
    {
        out_of_range = true;
    }

    if (!out_of_range)
    {
        return;
    }

    if (a.transaction.action == cfa_warn)
    {
        do_signals = false;
    }
    else
    {
        do_signals = true;
    }

/* signal/kill promises for existing matches */

    if (do_signals && (matches > 0))
    {
        if (a.process_stop != NULL)
        {
            if (DONTDO)
            {
                cfPS(OUTPUT_LEVEL_ERROR, CF_WARN, "", pp, a,
                     " -- Need to keep process-stop promise for %s, but only a warning is promised", pp->promiser);
            }
            else
            {
                if (IsExecutable(CommandArg0(a.process_stop)))
                {
                    ShellCommandReturnsZero(a.process_stop, false);
                }
                else
                {
                    cfPS(OUTPUT_LEVEL_VERBOSE, CF_FAIL, "", pp, a,
                         "Process promise to stop %s could not be kept because %s the stop operator failed",
                         pp->promiser, a.process_stop);
                    DeleteItemList(killlist);
                    return;
                }
            }
        }

        killed = DoAllSignals(killlist, a, pp);
    }

/* delegated promise to restart killed or non-existent entries */

    need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0));

    DeleteItemList(killlist);

    if (!need_to_restart)
    {
        cfPS(OUTPUT_LEVEL_VERBOSE, CF_NOP, "", pp, a, " -> No restart promised for %s\n", pp->promiser);
        return;
    }
    else
    {
        if (a.transaction.action == cfa_warn)
        {
            cfPS(OUTPUT_LEVEL_ERROR, CF_WARN, "", pp, a,
                 " -- Need to keep restart promise for %s, but only a warning is promised", pp->promiser);
        }
        else
        {
            cfPS(OUTPUT_LEVEL_INFORM, CF_CHG, "", pp, a, " -> Making a one-time restart promise for %s", pp->promiser);
            NewClass(a.restart_class, pp->ns);
        }
    }
}
Example #12
0
static int FindPidMatches(Item *procdata, Item **killlist, Attributes a, const char *promiser)
{
    int matches = 0;
    pid_t cfengine_pid = getpid();

    Item *matched = SelectProcesses(procdata, promiser, a.process_select, a.haveselect);

    for (Item *ip = matched; ip != NULL; ip = ip->next)
    {
        if (a.transaction.action == cfa_warn)
        {
            Log(LOG_LEVEL_ERR, "Matched: %s", ip->name);
        }
        else
        {
            Log(LOG_LEVEL_INFO, "Matched: %s", ip->name);
        }

        pid_t pid = ip->counter;

        if (pid == 1)
        {
            if ((RlistLen(a.signals) == 1) && (RlistIsStringIn(a.signals, "hup")))
            {
                Log(LOG_LEVEL_VERBOSE, "(Okay to send only HUP to init)");
            }
            else
            {
                continue;
            }
        }

        if ((pid < 4) && (a.signals))
        {
            Log(LOG_LEVEL_VERBOSE, "Will not signal or restart processes 0,1,2,3 (occurred while looking for %s)",
                  promiser);
            continue;
        }

        bool promised_zero = (a.process_count.min_range == 0) && (a.process_count.max_range == 0);

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

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

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

    DeleteItemList(matched);

    return matches;
}
Example #13
0
static void VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, Promise *pp)
{
    int matches = 0, do_signals = true, out_of_range, killed = 0, need_to_restart = true;
    Item *killlist = NULL;

    CfDebug("VerifyProcessOp\n");

    matches = FindPidMatches(procdata, &killlist, a, pp->promiser);

/* promise based on number of matches */

    if (a.process_count.min_range != CF_NOINT)  /* if a range is specified */
    {
        if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range))
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Process count for \'%s\' was out of promised range (%d found)\n", pp->promiser, matches);
            for (const Rlist *rp = a.process_count.out_of_range_define; rp != NULL; rp = rp->next)
            {
                if (!EvalContextHeapContainsSoft(ctx, rp->item))
                {
                    EvalContextHeapAddSoft(ctx, rp->item, PromiseGetNamespace(pp));
                }
            }
            out_of_range = true;
        }
        else
        {
            for (const Rlist *rp = a.process_count.in_range_define; rp != NULL; rp = rp->next)
            {
                if (!EvalContextHeapContainsSoft(ctx, rp->item))
                {
                    EvalContextHeapAddSoft(ctx, rp->item, PromiseGetNamespace(pp));
                }
            }
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Process promise for %s is kept", pp->promiser);
            out_of_range = false;
        }
    }
    else
    {
        out_of_range = true;
    }

    if (!out_of_range)
    {
        return;
    }

    if (a.transaction.action == cfa_warn)
    {
        do_signals = false;
    }
    else
    {
        do_signals = true;
    }

/* signal/kill promises for existing matches */

    if (do_signals && (matches > 0))
    {
        if (a.process_stop != NULL)
        {
            if (DONTDO)
            {
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a,
                     " -- Need to keep process-stop promise for %s, but only a warning is promised", pp->promiser);
            }
            else
            {
                if (IsExecutable(CommandArg0(a.process_stop)))
                {
                    ShellCommandReturnsZero(a.process_stop, false);
                }
                else
                {
                    cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, pp, a,
                         "Process promise to stop %s could not be kept because %s the stop operator failed",
                         pp->promiser, a.process_stop);
                    DeleteItemList(killlist);
                    return;
                }
            }
        }

        killed = DoAllSignals(ctx, killlist, a, pp);
    }

/* delegated promise to restart killed or non-existent entries */

    need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0));

    DeleteItemList(killlist);

    if (!need_to_restart)
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No restart promised for %s\n", pp->promiser);
        return;
    }
    else
    {
        if (a.transaction.action == cfa_warn)
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a,
                 " -- Need to keep restart promise for %s, but only a warning is promised", pp->promiser);
        }
        else
        {
            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Making a one-time restart promise for %s", pp->promiser);
            EvalContextHeapAddSoft(ctx, a.restart_class, PromiseGetNamespace(pp));
        }
    }
}
int OpenReceiverChannel(void)
{
    struct addrinfo *response, *ap;
    struct addrinfo query = {
        .ai_flags = AI_PASSIVE,
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
    };

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

    char servname[10];
    snprintf(servname, 10, "%d", CFENGINE_PORT);

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

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

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

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

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

    if (sd < 0)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open/bind a socket");
        exit(1);
    }

    freeaddrinfo(response);
    return sd;
}

/*********************************************************************/
/* Level 3                                                           */
/*********************************************************************/

void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, time_t *last_policy_reload)
{
    time_t validated_at;

    Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file);

    validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config);

    if (*last_policy_reload < validated_at)
    {
        *last_policy_reload = validated_at;

        Log(LOG_LEVEL_VERBOSE, "New promises detected...");

        if (GenericAgentArePromisesValid(config))
        {
            Log(LOG_LEVEL_INFO, "Rereading policy file '%s'", config->input_file);

            /* Free & reload -- lock this to avoid access errors during reload */
            
            EvalContextClear(ctx);

            free(SV.allowciphers);
            SV.allowciphers = NULL;

            DeleteItemList(SV.trustkeylist);
            DeleteItemList(SV.attackerlist);
            DeleteItemList(SV.nonattackerlist);
            DeleteItemList(SV.multiconnlist);

            DeleteAuthList(SV.admit);
            DeleteAuthList(SV.deny);

            DeleteAuthList(SV.varadmit);
            DeleteAuthList(SV.vardeny);

            DeleteAuthList(SV.roles);

            strcpy(VDOMAIN, "undefined.domain");

            SV.admit = NULL;
            SV.admittop = NULL;

            SV.varadmit = NULL;
            SV.varadmittop = NULL;

            SV.deny = NULL;
            SV.denytop = NULL;

            SV.vardeny = NULL;
            SV.vardenytop = NULL;

            SV.roles = NULL;
            SV.rolestop = NULL;

            SV.trustkeylist = NULL;
            SV.attackerlist = NULL;
            SV.nonattackerlist = NULL;
            SV.multiconnlist = NULL;

            PolicyDestroy(*policy);
            *policy = NULL;

            {
                char *existing_policy_server = ReadPolicyServerFile(GetWorkDir());
                SetPolicyServer(ctx, existing_policy_server);
                free(existing_policy_server);
            }
            UpdateLastPolicyUpdateTime(ctx);

            DetectEnvironment(ctx);
            KeepHardClasses(ctx);

            EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent");

            time_t t = SetReferenceTime();
            UpdateTimeClasses(ctx, t);
            *policy = GenericAgentLoadPolicy(ctx, config);
            KeepPromises(ctx, *policy, config);
            Summarize();
        }
        else
        {
            Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring");
        }
    }
    else
    {
        Log(LOG_LEVEL_DEBUG, "No new promises found");
    }
}
Example #15
0
void MonNetworkGatherData(double *cf_this)
{
FILE *pp;
char local[CF_BUFSIZE],remote[CF_BUFSIZE],comm[CF_BUFSIZE];
struct Item *in[ATTR],*out[ATTR];
char *sp;
int i;
char vbuff[CF_BUFSIZE];

Debug("GatherSocketData()\n");

for (i = 0; i < ATTR; i++)
   {
   in[i] = out[i] = NULL;
   }

if (ALL_INCOMING != NULL)
   {
   DeleteItemList(ALL_INCOMING);
   ALL_INCOMING = NULL;
   }

if (ALL_OUTGOING != NULL)
   {
   DeleteItemList(ALL_OUTGOING);
   ALL_OUTGOING = NULL;
   }

sscanf(VNETSTAT[VSYSTEMHARDCLASS],"%s",comm);

strcat(comm," -n");

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

while (!feof(pp))
   {
   memset(local,0,CF_BUFSIZE);
   memset(remote,0,CF_BUFSIZE);

   CfReadLine(vbuff,CF_BUFSIZE,pp);

   if (strstr(vbuff,"UNIX"))
      {
      break;
      }

   if (!strstr(vbuff,"."))
      {
      continue;
      }

   /* Different formats here ... ugh.. */

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

   if (strlen(local) == 0)
      {
      continue;
      }

   for (sp = local+strlen(local); (*sp != '.') && (sp > local); sp--)
      {
      }

   sp++;

   if ((strlen(sp) < 5) &&!IsItemIn(ALL_INCOMING,sp))
      {
      PrependItem(&ALL_INCOMING,sp,NULL);
      }

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

   sp++;

   if ((strlen(sp) < 5) && !IsItemIn(ALL_OUTGOING,sp))
      {
      PrependItem(&ALL_OUTGOING,sp,NULL);
      }

   for (i = 0; i < ATTR; i++)
      {
      char *spend;

      for (spend = local+strlen(local)-1; isdigit((int)*spend); spend--)
         {
         }

      spend++;

      if (strcmp(spend,ECGSOCKS[i].portnr) == 0)
         {
         cf_this[ECGSOCKS[i].in]++;
         AppendItem(&in[i],vbuff,"");
         }

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

      spend++;

      if (strcmp(spend,ECGSOCKS[i].portnr) == 0)
         {
         cf_this[ECGSOCKS[i].out]++;
         AppendItem(&out[i],vbuff,"");
         }
      }
   }

cf_pclose(pp);

/* Now save the state for ShowState() cf2 version alert function IFF
   the state is not smaller than the last or at least 40 minutes
   older. This mirrors the persistence of the maxima classes */


for (i = 0; i < ATTR; i++)
   {
   struct stat statbuf;
   time_t now = time(NULL);

   Debug("save incoming %s\n",ECGSOCKS[i].name);
   snprintf(vbuff,CF_MAXVARSIZE,"%s/state/cf_incoming.%s",CFWORKDIR,ECGSOCKS[i].name);
   if (cfstat(vbuff,&statbuf) != -1)
      {
      if ((ByteSizeList(in[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60))
         {
         CfOut(cf_verbose,"","New state %s is smaller, retaining old for 40 mins longer\n",ECGSOCKS[i].name);
         DeleteItemList(in[i]);
         continue;
         }
      }

   SetNetworkEntropyClasses(ECGSOCKS[i].name,"in",in[i]);
   RawSaveItemList(in[i],vbuff);
   DeleteItemList(in[i]);
   Debug("Saved in netstat data in %s\n",vbuff);
   }

for (i = 0; i < ATTR; i++)
   {
   struct stat statbuf;
   time_t now = time(NULL);

   Debug("save outgoing %s\n",ECGSOCKS[i].name);
   snprintf(vbuff,CF_MAXVARSIZE,"%s/state/cf_outgoing.%s",CFWORKDIR,ECGSOCKS[i].name);

   if (cfstat(vbuff,&statbuf) != -1)
      {
      if ((ByteSizeList(out[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60))
         {
         CfOut(cf_verbose,"","New state %s is smaller, retaining old for 40 mins longer\n",ECGSOCKS[i].name);
         DeleteItemList(out[i]);
         continue;
         }
      }

   SetNetworkEntropyClasses(ECGSOCKS[i].name,"out",out[i]);
   RawSaveItemList(out[i],vbuff);
   Debug("Saved out netstat data in %s\n",vbuff);
   DeleteItemList(out[i]);
   }
}
Example #16
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;
}