static void Cf3ParseFiles()

{ struct Rlist *rp,*sl;

PARSING = true;

PROMISETIME = time(NULL);

Cf3ParseFile(VINPUTFILE);

// Expand any lists in this list now

HashVariables(NULL);
HashControls();

if (VINPUTLIST != NULL)
   {
   for (rp = VINPUTLIST; rp != NULL; rp=rp->next)
      {
      if (rp->type != CF_SCALAR)
         {
         CfOut(cf_error,"","Non-file object in inputs list\n");
         }
      else
         {
         struct Rval returnval;

         if (strcmp(rp->item,CF_NULL_VALUE) == 0)
            {
            continue;
            }

         returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL);

         switch (returnval.rtype)
            {
            case CF_SCALAR:
                Cf3ParseFile((char *)returnval.item);
                break;

            case CF_LIST:
                for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next)
                   {
                   Cf3ParseFile((char *)sl->item);
                   }
                break;
            }

         DeleteRvalItem(returnval.item,returnval.rtype);
         }

      HashVariables(NULL);
      HashControls();
      }
   }

HashVariables(NULL);

PARSING = false;
}
Exemple #2
0
void DeleteAssoc(CfAssoc *ap)
{
    if (ap == NULL)
    {
        return;
    }

    CfDebug(" ----> Delete variable association %s\n", ap->lval);

    free(ap->lval);
    DeleteRvalItem(ap->rval);

    free(ap);

}
Exemple #3
0
Rlist *NewExpArgs(const FnCall *fp, const Promise *pp)
{
    int len;
    Rval rval;
    Rlist *newargs = NULL;
    FnCall *subfp;
    const FnCallType *fn = FindFunction(fp->name);

    len = RlistLen(fp->args);

    if (!fn->varargs)
    {
        if (len != FnNumArgs(fn))
        {
            CfOut(cf_error, "", "Arguments to function %s(.) do not tally. Expect %d not %d",
                  fp->name, FnNumArgs(fn), len);
            PromiseRef(cf_error, pp);
            exit(1);
        }
    }

    for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next)
    {
        switch (rp->type)
        {
        case CF_FNCALL:
            subfp = (FnCall *) rp->item;
            rval = EvaluateFunctionCall(subfp, pp).rval;
            break;
        default:
            rval = ExpandPrivateRval(CONTEXTID, (Rval) {rp->item, rp->type});
            break;
        }

        CfDebug("EXPARG: %s.%s\n", CONTEXTID, (char *) rval.item);
        AppendRlist(&newargs, rval.item, rval.rtype);
        DeleteRvalItem(rval);
    }

    return newargs;
}
Exemple #4
0
void DeRefListsInHashtable(char *scope, Rlist *namelist, Rlist *dereflist)
// Go through scope and for each variable in name-list, replace with a
// value from the deref "lol" (list of lists) clock
{
    int len;
    Scope *ptr;
    Rlist *rp;
    CfAssoc *cplist;
    HashIterator i;
    CfAssoc *assoc;

    if ((len = RlistLen(namelist)) != RlistLen(dereflist))
    {
        CfOut(cf_error, "", " !! Name list %d, dereflist %d\n", len, RlistLen(dereflist));
        FatalError("Software Error DeRefLists... correlated lists not same length");
    }

    if (len == 0)
    {
        return;
    }

    ptr = GetScope(scope);
    i = HashIteratorInit(ptr->hashtable);

    while ((assoc = HashIteratorNext(&i)))
    {
        for (rp = dereflist; rp != NULL; rp = rp->next)
        {
            cplist = (CfAssoc *) rp->item;

            if (strcmp(cplist->lval, assoc->lval) == 0)
            {
                /* Link up temp hash to variable lol */

                if (rp->state_ptr == NULL || rp->state_ptr->type == CF_FNCALL)
                {
                    /* Unexpanded function, or blank variable must be skipped. */
                    return;
                }

                if (rp->state_ptr)
                {
                    CfDebug("Rewriting expanded type for %s from %s to %s\n", assoc->lval, CF_DATATYPES[assoc->dtype],
                            (char *) rp->state_ptr->item);

                    // must first free existing rval in scope, then allocate new (should always be string)
                    DeleteRvalItem(assoc->rval);

                    // avoids double free - borrowing value from lol (freed in DeleteScope())
                    assoc->rval.item = xstrdup(rp->state_ptr->item);
                }

                switch (assoc->dtype)
                {
                case cf_slist:
                    assoc->dtype = cf_str;
                    assoc->rval.rtype = CF_SCALAR;
                    break;
                case cf_ilist:
                    assoc->dtype = cf_int;
                    assoc->rval.rtype = CF_SCALAR;
                    break;
                case cf_rlist:
                    assoc->dtype = cf_real;
                    assoc->rval.rtype = CF_SCALAR;
                    break;
                default:
                    /* Only lists need to be converted */
                    break;
                }

                CfDebug(" to %s\n", CF_DATATYPES[assoc->dtype]);
            }
        }
    }
}
Exemple #5
0
int AddVariableHash(const char *scope, const char *lval, Rval rval, enum cfdatatype dtype, const char *fname,
                    int lineno)
{
    Scope *ptr;
    const Rlist *rp;
    CfAssoc *assoc;

    if (rval.rtype == CF_SCALAR)
    {
        CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", scope, lval, (const char *) rval.item, CF_DATATYPES[dtype],
                rval.rtype);
    }
    else
    {
        CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", scope, lval, CF_DATATYPES[dtype], rval.rtype);
    }

    if (lval == NULL || scope == NULL)
    {
        CfOut(cf_error, "", "scope.value = %s.%s", scope, lval);
        ReportError("Bad variable or scope in a variable assignment");
        FatalError("Should not happen - forgotten to register a function call in fncall.c?");
    }

    if (rval.item == NULL)
    {
        CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n");
        return false;
    }

    if (strlen(lval) > CF_MAXVARSIZE)
    {
        ReportError("variable lval too long");
        return false;
    }

/* If we are not expanding a body template, check for recursive singularities */

    if (strcmp(scope, "body") != 0)
    {
        switch (rval.rtype)
        {
        case CF_SCALAR:

            if (StringContainsVar((char *) rval.item, lval))
            {
                CfOut(cf_error, "", "Scalar variable %s.%s contains itself (non-convergent): %s", scope, lval,
                      (char *) rval.item);
                return false;
            }
            break;

        case CF_LIST:

            for (rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (StringContainsVar((char *) rp->item, lval))
                {
                    CfOut(cf_error, "", "List variable %s contains itself (non-convergent)", lval);
                    return false;
                }
            }
            break;

        }
    }

    ptr = GetScope(scope);

    if (ptr == NULL)
    {
        return false;
    }

// Look for outstanding lists in variable rvals

    if (THIS_AGENT_TYPE == cf_common)
    {
        Rlist *listvars = NULL, *scalarvars = NULL;

        if (strcmp(CONTEXTID, "this") != 0)
        {
            MapIteratorsFromRval(CONTEXTID, &scalarvars, &listvars, rval, NULL);

            if (listvars != NULL)
            {
                CfOut(cf_error, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"",
                      lval, CONTEXTID);
            }

            DeleteRlist(scalarvars);
            DeleteRlist(listvars);
        }
    }

    assoc = HashLookupElement(ptr->hashtable, lval);

    if (assoc)
    {
        if (CompareVariableValue(rval, assoc) == 0)
        {
            /* Identical value, keep as is */
        }
        else
        {
            /* Different value, bark and replace */
            if (!UnresolvedVariables(assoc, rval.rtype))
            {
                CfOut(cf_inform, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval,
                      ptr->scope);
                if (fname)
                {
                    CfOut(cf_inform, "", " !! Rule from %s at/before line %d\n", fname, lineno);
                }
                else
                {
                    CfOut(cf_inform, "", " !! in bundle parameterization\n");
                }
            }
            DeleteRvalItem(assoc->rval);
            assoc->rval = CopyRvalItem(rval);
            assoc->dtype = dtype;
            CfDebug("Stored \"%s\" in context %s\n", lval, scope);
        }
    }
    else
    {
        if (!HashInsertElement(ptr->hashtable, lval, rval, dtype))
        {
            FatalError("Hash table is full");
        }
    }

    CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval, scope);
    return true;
}
int NewPromiseProposals()

{ struct Rlist *rp,*sl;
  struct stat sb;
  int result = false;
  char filename[CF_MAXVARSIZE];

if (MINUSF)
   {
   snprintf(filename,CF_MAXVARSIZE,"%s/state/validated_%s",CFWORKDIR,CanonifyName(VINPUTFILE));
   MapName(filename);   
   }
else
   {
   snprintf(filename,CF_MAXVARSIZE,"%s/masterfiles/cf_promises_validated",CFWORKDIR);
   MapName(filename);
   }
  
if (stat(filename,&sb) != -1)
   {
   PROMISETIME = sb.st_mtime;
   }
else
   {
   PROMISETIME = 0;
   }


// sanity check

if(PROMISETIME > time(NULL))
   {
   CfOut(cf_inform, "", "!! Clock seems to have jumped back in time - mtime of %s is newer than current time - touching it", filename);
   
   if(utime(filename,NULL) == -1)
      {
      CfOut(cf_error, "utime", "!! Could not touch %s", filename);
      }

   PROMISETIME = 0;
   return true;
   }

if (cfstat(InputLocation(VINPUTFILE),&sb) == -1)
   {
   CfOut(cf_verbose,"stat","There is no readable input file at %s",VINPUTFILE);
   return true;
   }

if (sb.st_mtime > PROMISETIME)
   {
   CfOut(cf_verbose,""," -> Promises seem to change");
   return true;
   }

// Check the directories first for speed and because non-input/data files should trigger an update

snprintf(filename,CF_MAXVARSIZE,"%s/inputs",CFWORKDIR);
MapName(filename);

if (IsNewerFileTree(filename,PROMISETIME))
   {
   CfOut(cf_verbose,""," -> Quick search detected file changes");
   return true;
   }

// Check files in case there are any abs paths

if (VINPUTLIST != NULL)
   {
   for (rp = VINPUTLIST; rp != NULL; rp=rp->next)
      {
      if (rp->type != CF_SCALAR)
         {
         CfOut(cf_error,"","Non file object %s in list\n",(char *)rp->item);
         }
      else
         {
         struct Rval returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL);

         switch (returnval.rtype)
            {
            case CF_SCALAR:

                if (cfstat(InputLocation((char *)returnval.item),&sb) == -1)
                   {
                   CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)returnval.item);
                   result = true;
                   break;
                   }

                if (sb.st_mtime > PROMISETIME)
                   {
                   result = true;
                   }

                break;

            case CF_LIST:

                for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next)
                   {
                   if (cfstat(InputLocation((char *)sl->item),&sb) == -1)
                      {
                      CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)sl->item);
                      result = true;
                      break;
                      }

                   if (sb.st_mtime > PROMISETIME)
                      {
                      result = true;
                      break;
                      }
                   }

                break;
            }

         DeleteRvalItem(returnval.item,returnval.rtype);

         if (result)
            {
            break;
            }
         }
      }
   }

// did policy server change (used in $(sys.policy_hub))?
snprintf(filename,CF_MAXVARSIZE,"%s/policy_server.dat",CFWORKDIR);
MapName(filename);

if ((cfstat(filename,&sb) != -1) && (sb.st_mtime > PROMISETIME))
   {
   result = true;
   }

return result | ALWAYS_VALIDATE;
}
static void CheckControlPromises(char *scope,char *agent,struct Constraint *controllist)

{ struct Constraint *cp;
  struct BodySyntax *bp = NULL;
  struct Rlist *rp;
  int i = 0;
  struct Rval returnval;
  char rettype;
  void *retval;

Debug("CheckControlPromises(%s)\n",agent);

for (i = 0; CF_ALL_BODIES[i].bs != NULL; i++)
   {
   bp = CF_ALL_BODIES[i].bs;

   if (strcmp(agent,CF_ALL_BODIES[i].btype) == 0)
      {
      break;
      }
   }

if (bp == NULL)
   {
   FatalError("Unknown agent");
   }

for (cp = controllist; cp != NULL; cp=cp->next)
   {
   if (IsExcluded(cp->classes))
      {
      continue;
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_bundlesequence].lval) == 0)
      {
      returnval = ExpandPrivateRval(CONTEXTID,cp->rval,cp->type);
      }
   else
      {
      returnval = EvaluateFinalRval(CONTEXTID,cp->rval,cp->type,true,NULL);
      }

   DeleteVariable(scope,cp->lval);

   if (!AddVariableHash(scope,cp->lval,returnval.item,returnval.rtype,GetControlDatatype(cp->lval,bp),cp->audit->filename,cp->lineno))
      {
      CfOut(cf_error,""," !! Rule from %s at/before line %d\n",cp->audit->filename,cp->lineno);
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_output_prefix].lval) == 0)
      {
      strncpy(VPREFIX,returnval.item,CF_MAXVARSIZE);
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_domain].lval) == 0)
      {
      strcpy(VDOMAIN,cp->rval);
      CfOut(cf_verbose,"","SET domain = %s\n",VDOMAIN);
      DeleteScalar("sys","domain");
      DeleteScalar("sys","fqhost");
      snprintf(VFQNAME,CF_MAXVARSIZE,"%s.%s",VUQNAME,VDOMAIN);
      NewScalar("sys","fqhost",VFQNAME,cf_str);
      NewScalar("sys","domain",VDOMAIN,cf_str);
      DeleteClass("undefined_domain");
      NewClass(VDOMAIN);
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_inputs].lval) == 0)
      {
      CfOut(cf_verbose,"","SET ignore_missing_inputs %s\n",cp->rval);
      IGNORE_MISSING_INPUTS = GetBoolean(cp->rval);
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_bundles].lval) == 0)
      {
      CfOut(cf_verbose,"","SET ignore_missing_bundles %s\n",cp->rval);
      IGNORE_MISSING_BUNDLES = GetBoolean(cp->rval);
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_goalpatterns].lval) == 0)
      {
      GOALS = NULL;
      for (rp = (struct Rlist *)returnval.item; rp != NULL; rp=rp->next)
         {
         PrependRScalar(&GOALS,rp->item,CF_SCALAR);
         }
      CfOut(cf_verbose,"","SET goal_patterns list\n");
      continue;
      }

   if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_goalcategories].lval) == 0)
      {
      GOALCATEGORIES = NULL;
      for (rp = (struct Rlist *)returnval.item; rp != NULL; rp=rp->next)
         {
         PrependRScalar(&GOALCATEGORIES,rp->item,CF_SCALAR);
         }

      CfOut(cf_verbose,"","SET goal_categories list\n");
      continue;
      }

   
   DeleteRvalItem(returnval.item,returnval.rtype);
   }
}
static int EvalClassExpression(struct Constraint *cp,struct Promise *pp)

{ int result_and = true;
  int result_or = false;
  int result_xor = 0;
  int result = 0,total = 0;
  char buffer[CF_MAXVARSIZE];
  struct Rlist *rp;
  double prob,cum = 0,fluct;
  struct Rval newret;
  struct FnCall *fp;

if (cp == NULL)
   {
   CfOut(cf_error,""," !! EvalClassExpression internal diagnostic discovered an ill-formed condition");
   }

if (!IsDefinedClass(pp->classes))
   {
   return false;
   }

if (pp->done)
   {
   return false;
   }

if (IsDefinedClass(pp->promiser))
   {
   return false;
   }

switch (cp->type) 
   {
   case CF_FNCALL:
       
       fp = (struct FnCall *)cp->rval;        /* Special expansion of functions for control, best effort only */
       newret = EvaluateFunctionCall(fp,pp);
       DeleteFnCall(fp);
       cp->rval = newret.item;
       cp->type = newret.rtype;
       break;

   case CF_LIST:
       for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next)
          {
          newret = EvaluateFinalRval("this",rp->item,rp->type,true,pp);
          DeleteRvalItem(rp->item,rp->type);
          rp->item = newret.item;
          rp->type = newret.rtype;
          }
       break;
       
   default:

       newret = ExpandPrivateRval("this",cp->rval,cp->type);
       DeleteRvalItem(cp->rval,cp->type);
       cp->rval = newret.item;
       cp->type = newret.rtype;
       break;
   }

if (strcmp(cp->lval,"expression") == 0)
   {
   if (cp->type != CF_SCALAR)
      {
      return false;
      }

   if (IsDefinedClass((char *)cp->rval))
      {
      return true;
      }
   else
      {
      return false;
      }
   }

if (strcmp(cp->lval,"not") == 0)
   {
   if (cp->type != CF_SCALAR)
      {
      return false;
      }

   if (IsDefinedClass((char *)cp->rval))
      {
      return false;
      }
   else
      {
      return true;
      }
   }

// Class selection

if (strcmp(cp->lval,"select_class") == 0)
   {
   char splay[CF_MAXVARSIZE];
   int i,n;
   double hash;
   
   total = 0;

   for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next)
      {
      total++;
      }

   if (total == 0)
      {
      CfOut(cf_error,""," !! No classes to select on RHS");
      PromiseRef(cf_error,pp);
      return false;      
      }

   snprintf(splay,CF_MAXVARSIZE,"%s+%s+%d",VFQNAME,VIPADDRESS,getuid());
   hash = (double)GetHash(splay);
   n = (int)(total*hash/(double)CF_HASHTABLESIZE);

   for (rp = (struct Rlist *)cp->rval,i = 0; rp != NULL; rp = rp->next,i++)
      {
      if (i == n)
         {
         NewClass(rp->item);
         return true;
         }
      }
   }

// Class distributions

if (strcmp(cp->lval,"dist") == 0)
   {
   for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next)
      {
      result = Str2Int(rp->item);
      
      if (result < 0)
         {
         CfOut(cf_error,""," !! Non-positive integer in class distribution");
         PromiseRef(cf_error,pp);
         return false;
         }
      
      total += result;
      }

   if (total == 0)
      {
      CfOut(cf_error,""," !! An empty distribution was specified on RHS");
      PromiseRef(cf_error,pp);
      return false;      
      }
   }

fluct = drand48(); /* Get random number 0-1 */
cum = 0.0;

/* If we get here, anything remaining on the RHS must be a clist */

if (cp->type != CF_LIST)
   {
   CfOut(cf_error,""," !! RHS of promise body attribute \"%s\" is not a list\n",cp->lval);
   PromiseRef(cf_error,pp);
   return true;
   }

for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next)
   {
   if (rp->type != CF_SCALAR)
      {
      return false;
      }

   result = IsDefinedClass((char *)(rp->item));

   result_and = result_and && result;
   result_or  = result_or || result;
   result_xor ^= result;

   if (total > 0) // dist class
      {
      prob = ((double)Str2Int(rp->item))/((double)total);
      cum += prob;

      if ((fluct < cum) || rp->next == NULL)
         {
         snprintf(buffer,CF_MAXVARSIZE-1,"%s_%s",pp->promiser,rp->item);
         *(pp->donep) = true;

         if (strcmp(pp->bundletype,"common") == 0)
            {
            NewClass(buffer);
            }
         else
            {
            NewBundleClass(buffer,pp->bundle);
            }

         Debug(" ?? \'Strategy\' distribution class interval -> %s\n",buffer);
         return true;
         }
      }
   }

// Class combinations

if (strcmp(cp->lval,"or") == 0)
   {
   return result_or;
   }

if (strcmp(cp->lval,"xor") == 0)
   {
   return (result_xor == 1) ? true : false;
   }

if (strcmp(cp->lval,"and") == 0)
   {
   return result_and;
   }

return false;
}