Пример #1
0
void test_iter_delete_entry(void **state)
{
    /* Test that deleting entry under cursor does not interrupt iteration */

    CF_DB *db;
    assert_int_equal(OpenDB(&db, dbid_classes), true);

    assert_int_equal(WriteDB(db, "foobar", "abc", 3), true);
    assert_int_equal(WriteDB(db, "bazbaz", "def", 3), true);
    assert_int_equal(WriteDB(db, "booo", "ghi", 3), true);

    CF_DBC *cursor;
    assert_int_equal(NewDBCursor(db, &cursor), true);

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

    assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true);

    assert_int_equal(DBCursorDeleteEntry(cursor), true);

    assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true);
    assert_int_equal(NextDB(db, cursor, &key, &ksize, &value, &vsize), true);

    assert_int_equal(DeleteDBCursor(db, cursor), true);

    CloseDB(db);
}
Пример #2
0
static void test_no_migration(void)
{
    DBHandle *db = setup(true);

    CloseDB(db);

    /* Migration on empty DB should produce single "version" key */

    assert_int_equal(OpenDB(&db, dbid_lastseen), true);

    DBCursor *cursor;
    assert_int_equal(NewDBCursor(db, &cursor), true);

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

    while (NextDB(cursor, &key, &ksize, &value, &vsize))
    {
        assert_int_equal(ksize, strlen("version") + 1);
        assert_string_equal(key, "version");
        assert_int_equal(vsize, 2);
        assert_string_equal(value, "1");
    }

    assert_int_equal(DeleteDBCursor(cursor), true);

    CloseDB(db);
}
static bool PurgeCurrentLastSeen()
{
    CF_DB *db_conn = NULL;
    CF_DBC *db_cursor = NULL;
    char *key = NULL;
    void *value = NULL;
    int ksize = 0, vsize = 0;

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

    if (!NewDBCursor(db_conn, &db_cursor))
    {
        Log(LOG_LEVEL_ERR, "Unable to scan lastseen db");
        CloseDB(db_conn);
        return false;
    }

    while (NextDB(db_cursor, &key, &ksize, &value, &vsize))
    {
        /* Only read the 'quality of connection' entries */
        if (key[0] != 'q')
        {
            continue;
        }

        time_t then = 0;

        if (value != NULL)
        {
            if (sizeof(KeyHostSeen) < vsize)
            {
                Log(LOG_LEVEL_ERR, "Invalid entry in lastseen database.");
                continue;
            }

            KeyHostSeen entry = { 0 };
            memcpy(&entry, value, vsize);

            then = entry.lastseen;
        }

        if (then - START_TIME > NHOSTS)
        {
            DBCursorDeleteEntry(db_cursor);
            Log(LOG_LEVEL_DEBUG, "Deleting expired entry for %s", key);
            continue;
        }
    }
    DeleteDBCursor(db_cursor);
    CloseDB(db_conn);

    return true;
}
Пример #4
0
static void TestCursorIteration(CF_DB *db)
{
    CF_DBC *dbc;

    if(!NewDBCursor(db, &dbc))
    {
        FatalError("Test: could not create cursor");
        pthread_exit((void*)STATUS_ERROR);
    }

    char *key;
    void *value;
    int key_sz, value_sz;

    int count = 0;
    while(NextDB(db, dbc, &key, &key_sz, &value, &value_sz))
    {
        int key_num = *(int *)key;
        int value_num = *(int *)value;

        //int key_num = atoi(key);
        //int value_num = atoi(value);

        if(key_num >= 0 && key_num < RECORD_COUNT_JUNK)
        {
            if((key_num + VALUE_OFFSET1 != value_num) && (key_num + VALUE_OFFSET2 != value_num))
            {
                printf("Error: key,value %d,%d are inconsistent\n", key_num, value_num);
            }
        }
        else if(key_num == READWRITEKEY)
        {
            if(!ReadWriteDataIsValid(value))
            {
                printf("Error: ReadWrite data is invalid\n");
            }
        }
        else
        {
            printf("Error: invalid key \"%s\"", key);
        }

        count++;
    }

    if(count != RECORD_COUNT_TOTAL)
    {
        printf("Error: During iteration count was %d (expected %d)\n", count, RECORD_COUNT_TOTAL);
    }

    if(!DeleteDBCursor(db, dbc))
    {
        FatalError("Test: could not delete cursor");
    }

}
Пример #5
0
static bool BundlesMigrationVersion0(DBHandle *db)
{
    bool errors = false;
    DBCursor *cursor;

    if (!NewDBCursor(db, &cursor))
    {
        return false;
    }

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

    while (NextDB(cursor, &key, &ksize, &value, &vsize))
    {
        if (ksize == 0)
        {
            Log(LOG_LEVEL_INFO, "BundlesMigrationVersion0: Database structure error -- zero-length key.");
            continue;
        }

        if (strchr(key, '.')) // is qualified name?
        {
            continue;
        }

        char *fqname = StringConcatenate(3, "default", ".", key);
        if (!WriteDB(db, fqname, value, vsize))
        {
            Log(LOG_LEVEL_INFO, "Unable to write version 1 bundle entry for '%s'", key);
            errors = true;
            continue;
        }

        if (!DBCursorDeleteEntry(cursor))
        {
            Log(LOG_LEVEL_INFO, "Unable to delete version 0 bundle entry for '%s'", key);
            errors = true;
        }
    }

    if (DeleteDBCursor(cursor) == false)
    {
        Log(LOG_LEVEL_ERR, "BundlesMigrationVersion0: Unable to close cursor");
        errors = true;
    }

    if ((!errors) && (!WriteDB(db, "version", "1", sizeof("1"))))
    {
        errors = true;
    }

    return !errors;
}
Пример #6
0
static void Mon_DumpSlowlyVaryingObservations(void)
{
 CF_DB *dbp;
 CF_DBC *dbcp;
 FILE *fout;
 char *key;
 void *stored;
 int ksize, vsize;
 char name[CF_BUFSIZE];
 
 if (!OpenDB(&dbp, dbid_static))
    {
    return;
    }
 
 snprintf(name, CF_BUFSIZE - 1, "%s%cstate%cstatic_data", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR);
 
 if ((fout = fopen(name, "w")) == NULL)
    {
    Log(LOG_LEVEL_ERR, "Unable to save discovery data in '%s'. (fopen: %s)", name, GetErrorStr());
    CloseDB(dbp);
    return;
    }
 
/* Acquire a cursor for the database. */
 
 if (!NewDBCursor(dbp, &dbcp))
    {
    Log(LOG_LEVEL_INFO, "Unable to scan class db");
    CloseDB(dbp);
    return;
    }
 
 while (NextDB(dbcp, &key, &ksize, &stored, &vsize))
    {
    char buf[CF_MAXVARSIZE], lval[CF_MAXVARSIZE], rval[CF_BUFSIZE];
    
    strncpy(buf, key, CF_MAXVARSIZE - 1);
    
    sscanf(buf, "%s:", lval);
    
    if (stored != NULL)
       {
       strncpy(rval, stored, CF_BUFSIZE - 1);
       fprintf(fout, "%s:%s\n", lval, rval);
       }
    }
 
 DeleteDBCursor(dbcp);
 CloseDB(dbp);
 fclose(fout);
}
Пример #7
0
/*
 * Provides empty lastseen DB
 */
static DBHandle *setup(bool clean)
{
    char cmd[CF_BUFSIZE];
    xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'/*", CFWORKDIR);
    system(cmd);

    DBHandle *db;
    OpenDB(&db, dbid_lastseen);

    if (clean)
    {
        /* There is no way to disable hook in OpenDB yet, so just undo
         * everything */

        DBCursor *cursor;
        if (!NewDBCursor(db, &cursor))
        {
            return NULL;
        }

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

        while (NextDB(cursor, &key, &ksize, &value, &vsize))
        {
            DBCursorDeleteEntry(cursor);
        }

        if (!DeleteDBCursor(cursor))
        {
            return NULL;
        }
    }

    return db;
}
Пример #8
0
int LastSeenHostKeyCount(void)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    QPoint entry;
    char *key;
    void *value;
    int ksize, vsize;

    int count = 0;

    if (OpenDB(&dbp, dbid_lastseen))
    {
        memset(&entry, 0, sizeof(entry));

        if (NewDBCursor(dbp, &dbcp))
        {
            while (NextDB(dbcp, &key, &ksize, &value, &vsize))
            {
                /* Only look for valid "hostkey" entries */

                if ((key[0] != 'k') || (value == NULL))
                {
                    continue;
                }

                count++;
            }

            DeleteDBCursor(dbcp);
        }

        CloseDB(dbp);
    }

    return count;
}
Пример #9
0
bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx)
{
    DBHandle *db;
    DBCursor *cursor;

    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;

    while (NextDB(cursor, &key, &ksize, &value, &vsize))
    {
        /* Only look for "keyhost" entries */
        if (key[0] != 'k')
        {
            continue;
        }

        const char *hostkey = key + 1;
        const char *address = value;

        char incoming_key[CF_BUFSIZE];
        snprintf(incoming_key, CF_BUFSIZE, "qi%s", hostkey);
        KeyHostSeen incoming;

        if (ReadDB(db, incoming_key, &incoming, sizeof(incoming)))
        {
            if (!(*callback)(hostkey, address, true, &incoming, ctx))
            {
                break;
            }
        }

        char outgoing_key[CF_BUFSIZE];
        snprintf(outgoing_key, CF_BUFSIZE, "qo%s", hostkey);
        KeyHostSeen outgoing;

        if (ReadDB(db, outgoing_key, &outgoing, sizeof(outgoing)))
        {
            if (!(*callback)(hostkey, address, false, &outgoing, ctx))
            {
                break;
            }
        }
    }

    DeleteDBCursor(cursor);
    CloseDB(db);

    return true;
}
Пример #10
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;
}
Пример #11
0
static void VerifyFriendConnections(int hours,struct Attributes a,struct Promise *pp)

/* Go through the database of recent connections and check for
   Long Time No See ...*/

{ CF_DB *dbp;
  CF_DBC *dbcp;
  char *key;
  void *value;
  int ksize,vsize;
  int secs = SECONDS_PER_HOUR*hours, criterion, overdue;
  time_t now = time(NULL),lsea = (time_t)CF_WEEK, tthen, then;
  char name[CF_BUFSIZE],hostname[CF_BUFSIZE],datebuf[CF_MAXVARSIZE];
  char addr[CF_BUFSIZE],type[CF_BUFSIZE],output[CF_BUFSIZE];
  struct QPoint entry;
  double average = 0.0, var = 0.0, ticksperminute = 60.0;
  double ticksperhour = (double)SECONDS_PER_HOUR;

CfOut(cf_verbose,"","CheckFriendConnections(%d)\n",hours);
snprintf(name,CF_BUFSIZE-1,"%s/lastseen/%s",CFWORKDIR,CF_LASTDB_FILE);
MapName(name);

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

/* Acquire a cursor for the database. */

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

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

while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize))
   {
   memset(&entry, 0, sizeof(entry)); 

   strncpy(hostname,(char *)key,ksize);

   if (value != NULL)
      {
      memcpy(&entry,value,sizeof(entry));
      then = (time_t)entry.q;
      average = (double)entry.expect;
      var = (double)entry.var;
      }
   else
      {
      continue;
      }

   if (then == 0)
      {
      continue; // No data
      }
   
   /* Got data, now get expiry criterion */

   if (secs == 0)
      {
      /* Twice the average delta is significant */
      criterion = (now - then > (int)(average+2.0*sqrt(var)+0.5));
      overdue = now - then - (int)(average);
      }
   else
      {
      criterion = (now - then > secs);
      overdue =  (now - then - secs);
      }

   if (LASTSEENEXPIREAFTER < 0)
      {
      lsea = (time_t)CF_WEEK;
      }
   else
      {
      lsea = LASTSEENEXPIREAFTER;
      }

   if (a.report.friend_pattern)
      {
      if (FullTextMatch(a.report.friend_pattern,IPString2Hostname(hostname+1)))
         {
         CfOut(cf_verbose,"","Not judging friend %s\n",hostname);
         criterion = false;
         lsea = CF_INFINITY;
         }
      }
   
   tthen = (time_t)then;

   snprintf(datebuf,CF_MAXVARSIZE-1,"%s",cf_ctime(&tthen));
   datebuf[strlen(datebuf)-9] = '\0';                     /* Chop off second and year */

   snprintf(addr,15,"%s",hostname+1);

   switch(*hostname)
      {
      case '+':
          snprintf(type,CF_BUFSIZE,"last responded to hails");
          break;
      case'-':
          snprintf(type,CF_BUFSIZE,"last hailed us");
          break;
      }

   snprintf(output,CF_BUFSIZE,"Host %s i.e. %s %s @ [%s] (overdue by %d mins)",
            IPString2Hostname(hostname+1),
            addr,
            type,
            datebuf,
            overdue/(int)ticksperminute);

   if (criterion)
      {
      CfOut(cf_error,"",output);
      }
   else
      {
      CfOut(cf_verbose,"",output);
      }

   snprintf(output,CF_BUFSIZE,"i.e. (%.2f) hrs ago, Av %.2f +/- %.2f hrs\n",
            ((double)(now-then))/ticksperhour,
            average/ticksperhour,
            sqrt(var)/ticksperhour);
   
   if (criterion)
      {
      CfOut(cf_error,"",output);
      }
   else
      {
      CfOut(cf_verbose,"",output);
      }

   if (now - then > lsea)
      {
      CfOut(cf_error,"","Giving up on host %s -- %d hours since last seen",IPString2Hostname(hostname+1),hours);
      DeleteDB(dbp,hostname);
      }
  
   memset(&value,0,sizeof(value));
   memset(&key,0,sizeof(key)); 
   }

DeleteDBCursor(dbp,dbcp);
CloseDB(dbp);
}
Пример #12
0
static void VerifyFriendReliability(struct Attributes a,struct Promise *pp)

{ CF_DB *dbp;
  CF_DBC *dbcp;
  int i,ksize,vsize;
  char *key;
  void *value;
  double n[CF_RELIABLE_CLASSES],n_av[CF_RELIABLE_CLASSES],total;
  double p[CF_RELIABLE_CLASSES],p_av[CF_RELIABLE_CLASSES];
  char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE];
  struct QPoint entry;
  struct Item *ip, *hostlist = NULL;
  double average,var,sum,sum_av,expect,actual;
  time_t now = time(NULL), then, lastseen = CF_WEEK;

CfOut(cf_verbose,"","CheckFriendReliability()\n");
snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE);

average = (double) CF_HOUR;  /* It will take a week for a host to be deemed reliable */
var = 0;

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

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

while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize))
   {
   strcpy(hostname,IPString2Hostname((char *)key+1));

   if (!IsItemIn(hostlist,hostname))
      {
      /* Check hostname not recorded twice with +/- */
      AppendItem(&hostlist,hostname,NULL);
      CfOut(cf_verbose,""," Measuring reliability of %s\n",hostname);
      }
   }

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

/* Now go through each host and recompute entropy */

for (ip = hostlist; ip != NULL; ip=ip->next)
   {
   snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name);
   MapName(name);

   if (!OpenDB(name,&dbp))
      {
      return;
      }
   
   for (i = 0; i < CF_RELIABLE_CLASSES; i++)
      {
      n[i] = n_av[i] = 0.0;
      }

   total = 0.0;

   for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL)
      {
      strcpy(timekey,GenTimeKey(now));
      
      if (ReadDB(dbp,timekey,&value,sizeof(entry)))
         {
         memcpy(&entry,value,sizeof(entry));
         then = (time_t)entry.q;
         lastseen = now - then;
         if (lastseen < 0)
            {
            lastseen = 0; /* Never seen before, so pretend */
            }
         average = (double)entry.expect;
         var = (double)entry.var;
         Debug("%s => then = %ld, lastseen = %ld, average=%.2f\n",hostname,then,lastseen,average);
         }
      else
         {
         /* If we have no data, it means no contact for whatever reason.
            It could be unable to respond unwilling to respond, policy etc.
            Assume for argument that we expect regular responses ... */
         
         lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */
         }

      for (i = 0; i < CF_RELIABLE_CLASSES; i++)
         {
         if (lastseen >= i*CF_HOUR && lastseen < (i+1)*CF_HOUR)
            {
            n[i]++;
            }
         
         if (average >= (double)(i*CF_HOUR) && average < (double)((i+1)*CF_HOUR))
            {
            n_av[i]++;
            }
         }
       
      total++;
      }

   sum = sum_av = 0.0;
   
   for (i = 0; i < CF_RELIABLE_CLASSES; i++)
      {
      p[i]    = n[i]/total;
      p_av[i] = n_av[i]/total;
      sum += p[i];
      sum_av += p_av[i];
      }

   Debug("Reliabilities sum to %.2f av %.2f\n\n",sum,sum_av);

   sum = sum_av = 0.0;
   
   for (i = 0; i < CF_RELIABLE_CLASSES; i++)
      {
      if (p[i] == 0.0)
         {
         continue;
         }
      sum -= p[i] * log(p[i]);
      }

   for (i = 0; i < CF_RELIABLE_CLASSES; i++)
      {
      if (p_av[i] == 0.0)
         {
         continue;
         }
      sum_av -= p_av[i] * log(p_av[i]);
      }

   actual = sum/log((double)CF_RELIABLE_CLASSES)*100.0;
   expect = sum_av/log((double)CF_RELIABLE_CLASSES)*100.0;
   
   CfOut(cf_verbose,"","Scaled entropy for %s = %.1f %%\n",ip->name,actual);
   CfOut(cf_verbose,"","Expected entropy for %s = %.1f %%\n\n",ip->name,expect);

   if (actual > expect)
      {
      CfOut(cf_inform,""," !! The reliability of %s deteriorated\n",ip->name);
      }

   if (actual > 50.0)
      {
      CfOut(cf_error,"","FriendStatus reports the intermittency of %s above 50%% (SEUs)\n",ip->name);
      }

   if (expect > actual)
      {
      CfOut(cf_inform,"","The reliability of %s is improved\n",ip->name);
      }

   CloseDB(dbp);
   }

DeleteItemList(hostlist);
}
Пример #13
0
void PurgeHashes(char *path, Attributes attr, Promise *pp)
/* Go through the database and purge records about non-existent files */
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    struct stat statbuf;
    int ksize, vsize;
    char *key;
    void *value;

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

    if (path)
    {
        if (cfstat(path, &statbuf) == -1)
        {
            DeleteDB(dbp, path);
        }
        CloseDB(dbp);
        return;
    }

/* Acquire a cursor for the database. */

    if (!NewDBCursor(dbp, &dbcp))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", " !! Unable to scan hash database");
        CloseDB(dbp);
        return;
    }

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

    while (NextDB(dbp, dbcp, &key, &ksize, &value, &vsize))
    {
        char *obj = (char *) key + CF_INDEX_OFFSET;

        if (cfstat(obj, &statbuf) == -1)
        {
            if (attr.change.update)
            {
                DBCursorDeleteEntry(dbcp);
            }
            else
            {
                cfPS(OUTPUT_LEVEL_ERROR, CF_WARN, "", pp, attr, "ALERT: File %s no longer exists!", obj);
            }

            LogHashChange(obj, cf_file_removed, "File removed", pp);
        }

        memset(&key, 0, sizeof(key));
        memset(&value, 0, sizeof(value));
    }

    DeleteDBCursor(dbp, dbcp);
    CloseDB(dbp);
}
Пример #14
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);
}
Пример #15
0
PromiseResult PurgeHashes(EvalContext *ctx, char *path, Attributes attr, const Promise *pp)
/* Go through the database and purge records about non-existent files */
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    struct stat statbuf;
    int ksize, vsize;
    char *key;
    void *value;

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

    if (path)
    {
        if (stat(path, &statbuf) == -1)
        {
            DeleteDB(dbp, path);
        }
        CloseDB(dbp);
        return PROMISE_RESULT_NOOP;
    }

/* Acquire a cursor for the database. */

    if (!NewDBCursor(dbp, &dbcp))
    {
        Log(LOG_LEVEL_INFO, "Unable to scan hash database");
        CloseDB(dbp);
        return PROMISE_RESULT_NOOP;
    }

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

    PromiseResult result = PROMISE_RESULT_NOOP;
    while (NextDB(dbcp, &key, &ksize, &value, &vsize))
    {
        char *obj = (char *) key + CF_INDEX_OFFSET;

        if (stat(obj, &statbuf) == -1)
        {
            if (attr.change.update)
            {
                DBCursorDeleteEntry(dbcp);
            }
            else
            {
                cfPS(ctx, LOG_LEVEL_NOTICE, PROMISE_RESULT_WARN, pp, attr, "File '%s' no longer exists", obj);
                result = PromiseResultUpdate(result, PROMISE_RESULT_WARN);
            }

            LogHashChange(obj, FILE_STATE_REMOVED, "File removed", pp);
        }
    }

    DeleteDBCursor(dbcp);
    CloseDB(dbp);

    return result;
}
Пример #16
0
void UpdateLastSeen() // This function is temporarily or permanently deprecated

{ double lsea = LASTSEENEXPIREAFTER;
  int intermittency = false,qsize,ksize;
  struct CfKeyHostSeen q,newq; 
  double lastseen,delta2;
  void *stored;
  CF_DB *dbp = NULL,*dbpent = NULL;
  CF_DBC *dbcp;
  char name[CF_BUFSIZE],*key;
  struct Rlist *rp;
  struct CfKeyBinding *kp;
  time_t now = time(NULL);
  static time_t then;
  
if (now < then + 300 && then > 0 && then <= now + 300)
   {
   // Rate limiter
   return;
   }

then = now;

CfOut(cf_verbose,""," -> Writing last-seen observations");

ThreadLock(cft_server_keyseen);

if (SERVER_KEYSEEN == NULL)
   {
   ThreadUnlock(cft_server_keyseen);
   CfOut(cf_verbose,""," -> Keyring is empty");
   return;
   }

if (BooleanControl("control_agent",CFA_CONTROLBODY[cfa_intermittency].lval))
   {
   CfOut(cf_inform,""," -> Recording intermittency");
   intermittency = true;
   }

snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE);
MapName(name);

if (!OpenDB(name,&dbp))
   {
   ThreadUnlock(cft_server_keyseen);
   return;
   }

/* First scan for hosts that have moved address and purge their records so that
   the database always has a 1:1 relationship between keyhash and IP address    */

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

while(NextDB(dbp,dbcp,&key,&ksize,&stored,&qsize))
   {
   memcpy(&q,stored,sizeof(q));

   lastseen = (double)now - q.Q.q;

   if (lastseen > lsea)
      {
      CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",key,lastseen/3600,lsea/3600);
      DeleteDB(dbp,key);
      }

   for (rp = SERVER_KEYSEEN; rp !=  NULL; rp=rp->next)
      {
      kp = (struct CfKeyBinding *) rp->item;
      
      if ((strcmp(q.address,kp->address) == 0) && (strcmp(key+1,kp->name+1) != 0))
         {
         CfOut(cf_verbose,""," ! Deleting %s's address (%s=%d) as this host %s seems to have moved elsewhere (%s=5d)",key,kp->address,strlen(kp->address),kp->name,q.address,strlen(q.address));
         DeleteDB(dbp,key);
         }
      }

   }

DeleteDBCursor(dbp,dbcp);

/* Now perform updates with the latest data */

for (rp = SERVER_KEYSEEN; rp !=  NULL; rp=rp->next)
   {
   kp = (struct CfKeyBinding *) rp->item;

   now = kp->timestamp;
   
   if (intermittency)
      {
      /* Open special file for peer entropy record - INRIA intermittency */
      snprintf(name,CF_BUFSIZE-1,"%s/lastseen/%s.%s",CFWORKDIR,CF_LASTDB_FILE,kp->name);
      MapName(name);
      
      if (!OpenDB(name,&dbpent))
         {
         continue;
         }
      }
   
   if (ReadDB(dbp,kp->name,&q,sizeof(q)))
      {
      lastseen = (double)now - q.Q.q;
      
      if (q.Q.q <= 0)
         {
         lastseen = 300;
         q.Q.expect = 0;
         q.Q.var = 0;
         }
      
      newq.Q.q = (double)now;
      newq.Q.expect = GAverage(lastseen,q.Q.expect,0.4);
      delta2 = (lastseen - q.Q.expect)*(lastseen - q.Q.expect);
      newq.Q.var = GAverage(delta2,q.Q.var,0.4);
      strncpy(newq.address,kp->address,CF_ADDRSIZE-1);
      }
   else
      {
      lastseen = 0.0;
      newq.Q.q = (double)now;
      newq.Q.expect = 0.0;
      newq.Q.var = 0.0;
      strncpy(newq.address,kp->address,CF_ADDRSIZE-1);
      }
   
   if (lastseen > lsea)
      {
      CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",kp->name,lastseen/3600,lsea/3600);
      DeleteDB(dbp,kp->name);
      }
   else
      {
      char timebuf[26];
      CfOut(cf_verbose,""," -> Last saw %s (alias %s) at %s (noexpiry %.1lf <= %.1lf)\n",kp->name,kp->address,cf_strtimestamp_local(now,timebuf),lastseen/3600,lsea/3600);

      WriteDB(dbp,kp->name,&newq,sizeof(newq));
      
      if (intermittency)
         {
         WriteDB(dbpent,GenTimeKey(now),&newq,sizeof(newq));
         }
      }
   
   if (intermittency && dbpent)
      {
      CloseDB(dbpent);
      }
   }

ThreadUnlock(cft_server_keyseen);
}
Пример #17
0
static void test_migration(void)
{
    CF_DB *db;
    Seq *list = SeqNew(NO_FILES, free);
    // Hand crafted from the new version of NewIndexKey().
    char checksum_key[NO_FILES][30] =
        {
            { 'H','_','M','D','5','\0','\0','\0','\0','\0',
              '/','e','t','c','/','h','o','s','t','s','\0' },
            { 'H','_','M','D','5','\0','\0','\0','\0','\0',
              '/','e','t','c','/','p','a','s','s','w','d','\0' },
            { 'H','_','M','D','5','\0','\0','\0','\0','\0',
              '/','f','i','l','e','1','\0' },
            { 'H','_','M','D','5','\0','\0','\0','\0','\0',
              '/','f','i','l','e','2','\0' },
        };
    char *filestat_key[NO_FILES] =
        {
            "S_/etc/hosts",
            "S_/etc/passwd",
            "S_/file1",
            "S_/file2",
        };

    // Should cause migration to happen.
    assert_true(FileChangesGetDirectoryList("/etc", list));
    assert_int_equal(SeqLength(list), 2);
    assert_string_equal(SeqAt(list, 0), "hosts");
    assert_string_equal(SeqAt(list, 1), "passwd");

    SeqClear(list);
    assert_true(FileChangesGetDirectoryList("/", list));
    assert_int_equal(SeqLength(list), 2);
    assert_string_equal(SeqAt(list, 0), "file1");
    assert_string_equal(SeqAt(list, 1), "file2");

    assert_true(OpenDB(&db, dbid_changes));
    for (int c = 0; c < NO_FILES; c++)
    {
        {
            int ksize = 2 + CHANGES_HASH_FILE_NAME_OFFSET
                + strlen(checksum_key[c] + 2 + CHANGES_HASH_FILE_NAME_OFFSET) + 1;
            int vsize = ValueSizeDB(db, checksum_key[c], ksize);
            assert_int_equal(vsize, strlen(CHECKSUM_VALUE[c]) + 1);
            char value[vsize];
            assert_true(ReadComplexKeyDB(db, checksum_key[c], ksize, value, vsize));
            assert_int_equal(memcmp(value, CHECKSUM_VALUE[c], vsize), 0);
        }

        {
            int vsize = ValueSizeDB(db, filestat_key[c], strlen(filestat_key[c]) + 1);
            assert_int_equal(vsize, sizeof(struct stat));
            char value[vsize];
            assert_true(ReadDB(db, filestat_key[c], value, vsize));
            assert_int_equal(memcmp(value, &filestat_value, vsize), 0);
        }
    }

    int db_entries = 0;
    CF_DBC *db_cursor;
    assert_true(NewDBCursor(db, &db_cursor));
    char *key, *value;
    int ksize, vsize;
    while (NextDB(db_cursor, &key, &ksize, (void **)&value, &vsize))
    {
        db_entries++;
    }
    DeleteDBCursor(db_cursor);
    // 2 x Directories ("/" and "/etc")
    // 4 x File hashes
    // 4 x File stats
    assert_int_equal(db_entries, 10);

    CloseDB(db);
}
Пример #18
0
void IPString2KeyDigest(char *ipv4, char *result)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    char *key;
    void *value;
    KeyHostSeen entry;
    int ksize, vsize;
    unsigned char digest[EVP_MAX_MD_SIZE + 1];

    result[0] = '\0';

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

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

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

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

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

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

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

            // Warning this is not 1:1

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

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

    if (NULL_OR_EMPTY(result))
    {
        CfOut(cf_verbose, "", "!! Unable to find a key for ip %s", ipv4);
    }
}
Пример #19
0
Item *ContextAccessControl(EvalContext *ctx, char *in, ServerConnectionState *conn, int encrypt)
{
    Auth *ap;
    int access = false;
    char client_regex[CF_BUFSIZE];
    CF_DB *dbp;
    CF_DBC *dbcp;
    int ksize, vsize;
    char *key;
    void *value;
    time_t now = time(NULL);
    CfState q;
    Item *ip, *matches = NULL, *candidates = NULL;

    sscanf(in, "CONTEXT %255[^\n]", client_regex);

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

    if (!NewDBCursor(dbp, &dbcp))
    {
        Log(LOG_LEVEL_INFO, "Unable to scan persistence cache");
        CloseDB(dbp);
        return NULL;
    }

    while (NextDB(dbcp, &key, &ksize, &value, &vsize))
    {
        memcpy((void *) &q, value, sizeof(CfState));

        if (now > q.expires)
        {
            Log(LOG_LEVEL_VERBOSE, " Persistent class %s expired", key);
            DBCursorDeleteEntry(dbcp);
        }
        else
        {
            if (FullTextMatch(ctx, client_regex, key))
            {
                Log(LOG_LEVEL_VERBOSE, " - Found key %s...", key);
                AppendItem(&candidates, key, NULL);
            }
        }
    }

    DeleteDBCursor(dbcp);
    CloseDB(dbp);

    for (ip = candidates; ip != NULL; ip = ip->next)
    {
        for (ap = SV.varadmit; ap != NULL; ap = ap->next)
        {
            int res = false;

            if (FullTextMatch(ctx, ap->path, ip->name))
            {
                res = true;
            }

            if (res)
            {
                Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", ip->name, ap->path);

                if (ap->classpattern == false)
                {
                    Log(LOG_LEVEL_ERR,
                          "Context %s requires a literal server item...cannot set variable directly by path",
                          ap->path);
                    access = false;
                    continue;
                }

                if ((!encrypt) && (ap->encrypt == true))
                {
                    Log(LOG_LEVEL_ERR, "Context %s requires encrypt connection...will not serve", ip->name);
                    access = false;
                    break;
                }
                else
                {
                    Log(LOG_LEVEL_DEBUG, "Checking whether to map root privileges");

                    if ((IsMatchItemIn(ctx, ap->maproot, MapAddress(conn->ipaddr)))
                        || (IsRegexItemIn(ctx, ap->maproot, conn->hostname)))
                    {
                        conn->maproot = true;
                        Log(LOG_LEVEL_VERBOSE, "Mapping root privileges");
                    }
                    else
                    {
                        Log(LOG_LEVEL_VERBOSE, "No root privileges granted");
                    }

                    if ((IsMatchItemIn(ctx, ap->accesslist, MapAddress(conn->ipaddr)))
                        || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)))
                    {
                        access = true;
                        Log(LOG_LEVEL_DEBUG, "Access privileges - match found");
                    }
                }
            }
        }

        for (ap = SV.vardeny; ap != NULL; ap = ap->next)
        {
            if (strcmp(ap->path, ip->name) == 0)
            {
                if ((IsMatchItemIn(ctx, ap->accesslist, MapAddress(conn->ipaddr)))
                    || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)))
                {
                    access = false;
                    Log(LOG_LEVEL_VERBOSE, "Host %s explicitly denied access to context %s", conn->hostname, ip->name);
                    break;
                }
            }
        }

        if (access)
        {
            Log(LOG_LEVEL_VERBOSE, "Host %s granted access to context '%s'", conn->hostname, ip->name);
            AppendItem(&matches, ip->name, NULL);

            if (encrypt && LOGENCRYPT)
            {
                /* Log files that were marked as requiring encryption */
                Log(LOG_LEVEL_INFO, "Host %s granted access to context '%s'", conn->hostname, ip->name);
            }
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Host %s denied access to context '%s'", conn->hostname, ip->name);
        }
    }

    DeleteItemList(candidates);
    return matches;
}
Пример #20
0
static void PurgeMultipleIPReferences(CF_DB *dbp, char *rkey, char *ipaddress)
{
    CF_DBC *dbcp;
    KeyHostSeen q;
    double lastseen, lsea = LASTSEENEXPIREAFTER;
    void *stored;
    char *key;
    time_t now = time(NULL);
    int qsize, ksize, update_address, keys_match;

// This is an expensive call, but it is the price we pay for consistency
// Make sure we only call it if we have to

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

    while (NextDB(dbp, dbcp, &key, &ksize, &stored, &qsize))
    {
        keys_match = false;

        if (strcmp(key + 1, rkey + 1) == 0)
        {
            keys_match = true;
        }

        memcpy(&q, stored, sizeof(q));

        lastseen = (double) now - q.Q.q;

        if (lastseen > lsea)
        {
            CfOut(cf_verbose, "", " -> Last-seen record for %s expired after %.1lf > %.1lf hours\n", key,
                  lastseen / 3600, lsea / 3600);
            DBCursorDeleteEntry(dbcp);
            continue;
        }

        // Avoid duplicate address/key pairs

        if (keys_match && strcmp(q.address, ipaddress) != 0)
        {
            CfOut(cf_verbose, "",
                  " ! Synchronizing %s's address as this host %s seems to have moved from location %s to %s", key, rkey,
                  q.address, ipaddress);
            strcpy(q.address, ipaddress);
            update_address = true;
        }
        else if (!keys_match && strcmp(q.address, ipaddress) == 0)
        {
            CfOut(cf_verbose, "", " ! Updating %s's address (%s) as this host %s seems to have gone off line", key,
                  ipaddress, rkey);
            strcpy(q.address, CF_UNKNOWN_IP);
            update_address = true;
        }
        else
        {
            update_address = false;
        }

        if (update_address)
        {
            DBCursorWriteEntry(dbcp, &q, sizeof(q));
        }
    }

    DeleteDBCursor(dbp, dbcp);
}
Пример #21
0
void SetMeasurementPromises(Item ** classlist)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    char eventname[CF_MAXVARSIZE], assignment[CF_BUFSIZE];
    Event entry;
    char *key;
    void *stored;
    int ksize, vsize;

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

    if (!NewDBCursor(dbp, &dbcp))
    {
        Log(LOG_LEVEL_INFO, "Unable to scan class db");
        CloseDB(dbp);
        return;
    }

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

    while (NextDB(dbcp, &key, &ksize, &stored, &vsize))
    {
        if (stored != NULL)
        {
            if (sizeof(entry) < vsize)
            {
                Log(LOG_LEVEL_ERR, "Invalid entry in measurements database. Expected size: %zu, actual size: %d", sizeof(entry), vsize);
                continue;
            }

            strcpy(eventname, (char *) key);
            memcpy(&entry, stored, MIN(vsize, sizeof(entry)));

            Log(LOG_LEVEL_VERBOSE, "Setting measurement event %s", eventname);

            // a.measure.data_type is not longer known here, so look for zero decimals

            if ((int) (entry.Q.q * 10) % 10 == 0)
            {
                snprintf(assignment, CF_BUFSIZE - 1, "value_%s=%.0lf", eventname, entry.Q.q);
            }
            else
            {
                snprintf(assignment, CF_BUFSIZE - 1, "value_%s=%.2lf", eventname, entry.Q.q);
            }

            AppendItem(classlist, assignment, NULL);

            snprintf(assignment, CF_BUFSIZE - 1, "av_%s=%.2lf", eventname, entry.Q.expect);
            AppendItem(classlist, assignment, NULL);
            snprintf(assignment, CF_BUFSIZE - 1, "dev_%s=%.2lf", eventname, sqrt(entry.Q.var));
            AppendItem(classlist, assignment, NULL);
        }
    }

    DeleteDBCursor(dbcp);
    CloseDB(dbp);
}
Пример #22
0
void ShowLastSeenHosts()

{ CF_DB *dbp;
  CF_DBC *dbcp;
  char *key;
  void *value;
  char name[CF_BUFSIZE],hostname[CF_BUFSIZE],address[CF_MAXVARSIZE];
  struct CfKeyHostSeen entry;
  int ksize,vsize;
  int count = 0;

snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE);
MapName(name);

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

/* Acquire a cursor for the database. */

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

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


printf("%9.9s %17.17s %-25.25s %15.15s\n","Direction","IP","Name","Key");

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

while(NextDB(dbp,dbcp,&key,&ksize,&value,&vsize))
   {
   if (value != NULL)
      {
      memset(&entry, 0, sizeof(entry));
      memset(hostname, 0, sizeof(hostname));
      memset(address, 0, sizeof(address));
      memcpy(&entry,value,sizeof(entry));
      strncpy(hostname,(char *)key,sizeof(hostname)-1);
      strncpy(address,(char *)entry.address,sizeof(address)-1);
      ++count;  
      }
   else
      {
      continue;
      }

   CfOut(cf_verbose,""," -> Reporting on %s",hostname);
      
   printf("%-9.9s %17.17s %-25.25s %s\n",
             hostname[0] == '+' ? "Outgoing" : "Incoming",
     	     address,	     
	     IPString2Hostname(address),
             hostname+1
          );
   }

printf("Total Entries: %d\n",count);
DeleteDBCursor(dbp,dbcp);
CloseDB(dbp);
}
Пример #23
0
void EvalContextHeapPersistentLoadAll(EvalContext *ctx)
{
    CF_DB *dbp;
    CF_DBC *dbcp;
    int ksize, vsize;
    char *key;
    void *value;
    time_t now = time(NULL);
    CfState q;

    if (LOOKUP)
    {
        return;
    }

    Banner("Loading persistent classes");

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

/* Acquire a cursor for the database. */

    if (!NewDBCursor(dbp, &dbcp))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", " !! Unable to scan persistence cache");
        return;
    }

    while (NextDB(dbcp, &key, &ksize, &value, &vsize))
    {
        memcpy((void *) &q, value, sizeof(CfState));

        CfDebug(" - Found key %s...\n", key);

        if (now > q.expires)
        {
            CfOut(OUTPUT_LEVEL_VERBOSE, "", " Persistent class %s expired\n", key);
            DBCursorDeleteEntry(dbcp);
        }
        else
        {
            CfOut(OUTPUT_LEVEL_VERBOSE, "", " Persistent class %s for %jd more minutes\n", key, (intmax_t)((q.expires - now) / 60));
            CfOut(OUTPUT_LEVEL_VERBOSE, "", " Adding persistent class %s to heap\n", key);
            if (strchr(key, CF_NS))
               {
               char ns[CF_MAXVARSIZE], name[CF_MAXVARSIZE];
               ns[0] = '\0';
               name[0] = '\0';
               sscanf(key, "%[^:]:%[^\n]", ns, name);
               EvalContextHeapAddSoft(ctx, name, ns);
               }
            else
               {
               EvalContextHeapAddSoft(ctx, key, NULL);
               }
        }
    }

    DeleteDBCursor(dbcp);
    CloseDB(dbp);

    Banner("Loaded persistent memory");
}
Пример #24
0
static bool LastseenMigrationVersion0(DBHandle *db)
{
    bool errors = false;
    DBCursor *cursor;

    if (!NewDBCursor(db, &cursor))
    {
        return false;
    }

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

    while (NextDB(cursor, &key, &ksize, &value, &vsize))
    {
        if (ksize == 0)
        {
            Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: Database structure error -- zero-length key.");
            continue;
        }

        /* Only look for old [+-]kH -> IP<QPoint> entries */
        if ((key[0] != '+') && (key[0] != '-'))
        {
            /* Warn about completely unexpected keys */

            if ((key[0] != 'q') && (key[0] != 'k') && (key[0] != 'a'))
            {
                Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: Malformed key found '%s'", key);
            }

            continue;
        }

        bool incoming = key[0] == '-';
        const char *hostkey = key + 1;

        /* Properly align the data */
        const char *old_data_address = (const char *)value;
        QPoint0 old_data_q;
        memcpy(&old_data_q, (const char *)value + QPOINT0_OFFSET, sizeof(QPoint0));

        /* Only migrate sane data */

        if (vsize != QPOINT0_OFFSET + sizeof(QPoint0))
        {
            Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: invalid value size for key '%s', entry is deleted",
                  key);
            DBCursorDeleteEntry(cursor);
            continue;
        }

        char hostkey_key[CF_BUFSIZE];
        snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);

        if (!WriteDB(db, hostkey_key, old_data_address, strlen(old_data_address) + 1))
        {
            Log(LOG_LEVEL_INFO, "Unable to write version 1 lastseen entry for '%s'", key);
            errors = true;
            continue;
        }

        char address_key[CF_BUFSIZE];
        snprintf(address_key, CF_BUFSIZE, "a%s", old_data_address);

        if (!WriteDB(db, address_key, hostkey, strlen(hostkey) + 1))
        {
            Log(LOG_LEVEL_INFO, "Unable to write version 1 reverse lastseen entry for '%s'", key);
            errors = true;
            continue;
        }

        char quality_key[CF_BUFSIZE];
        snprintf(quality_key, CF_BUFSIZE, "q%c%s", incoming ? 'i' : 'o', hostkey);

        /*
           Ignore malformed connection quality data
        */

        if ((!isfinite(old_data_q.q))
            || (old_data_q.q < 0)
            || (!isfinite(old_data_q.expect))
            || (!isfinite(old_data_q.var)))
        {
            Log(LOG_LEVEL_INFO, "Ignoring malformed connection quality data for '%s'", key);
            DBCursorDeleteEntry(cursor);
            continue;
        }

        KeyHostSeen data = {
            .lastseen = (time_t)old_data_q.q,
            .Q = {
                /*
                   Previously .q wasn't stored in database, but was calculated
                   every time as a difference between previous timestamp and a
                   new timestamp. Given we don't have this information during
                   the database upgrade, just assume that last reading is an
                   average one.
                */
                .q = old_data_q.expect,
                .dq = 0,
                .expect = old_data_q.expect,
                .var = old_data_q.var,
            }
        };

        if (!WriteDB(db, quality_key, &data, sizeof(data)))
        {
            Log(LOG_LEVEL_INFO, "Unable to write version 1 connection quality key for '%s'", key);
            errors = true;
            continue;
        }

        if (!DBCursorDeleteEntry(cursor))
        {
            Log(LOG_LEVEL_INFO, "Unable to delete version 0 lastseen entry for '%s'", key);
            errors = true;
        }
    }

    if (DeleteDBCursor(cursor) == false)
    {
        Log(LOG_LEVEL_ERR, "LastseenMigrationVersion0: Unable to close cursor");
        errors = true;
    }

    if ((!errors) && (!WriteDB(db, "version", "1", sizeof("1"))))
    {
        errors = true;
    }

    return !errors;
}