Esempio n. 1
0
void EvalContextHeapAddHard(EvalContext *ctx, const char *context)
{
    char context_copy[CF_MAXVARSIZE];

    strcpy(context_copy, context);
    if (Chop(context_copy, CF_EXPANDSIZE) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator");
    }
    CanonifyNameInPlace(context_copy);

    CfDebug("EvalContextHeapAddHard(%s)\n", context_copy);

    if (strlen(context_copy) == 0)
    {
        return;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, context_copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle aborted on defined class \"%s\"\n", context_copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, context_copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\"\n", context_copy);
        exit(1);
    }

    if (EvalContextHeapContainsHard(ctx, context_copy))
    {
        return;
    }

    StringSetAdd(ctx->heap_hard, xstrdup(context_copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, NULL))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", ip->name, StackFrameOwnerName(LastStackFrame(ctx, 0)));
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, NULL))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -> Setting abort for \"%s\" when setting \"%s\"", ip->name, context_copy);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
Esempio n. 2
0
int ScheduleAgentOperations(struct Bundle *bp)

{ struct SubType *sp;
  struct Promise *pp;
  enum typesequence type;
  int pass;

if (PROCESSREFRESH == NULL || (PROCESSREFRESH && IsRegexItemIn(PROCESSREFRESH,bp->name)))
   {
   DeleteItemList(PROCESSTABLE);
   PROCESSTABLE = NULL;
   }

for (pass = 1; pass < CF_DONEPASSES; pass++)
   {
   for (type = 0; TYPESEQUENCE[type] != NULL; type++)
      {
      ClassBanner(type);

      if ((sp = GetSubTypeForBundle(TYPESEQUENCE[type],bp)) == NULL)
         {
         continue;      
         }

      BannerSubType(bp->name,sp->name,pass);
      SetScope(bp->name);

      if (!NewTypeContext(type))
         {
         continue;
         }

      for (pp = sp->promiselist; pp != NULL; pp=pp->next)
         {
         SaveClassEnvironment();

         ExpandPromise(cf_agent,bp->name,pp,KeepAgentPromise);

         if (Abort())
            {
            NoteClassUsage(VADDCLASSES);
            DeleteTypeContext(type);
            return false;
            }
         }

      DeleteTypeContext(type);      
      }
   }

NoteClassUsage(VADDCLASSES);

return true;
}
Esempio n. 3
0
void EvalContextStackFrameAddSoft(EvalContext *ctx, const char *context)
{
    assert(SeqLength(ctx->stack) > 0);

    StackFrameBundle frame;
    {
        StackFrame *last_frame = LastStackFrameBundle(ctx);
        if (!last_frame)
        {
            ProgrammingError("Attempted to add a soft class on the stack, but stack had no bundle frame");
        }
        frame = last_frame->data.bundle;
    }

    char copy[CF_BUFSIZE];
    if (strcmp(frame.owner->ns, "default") != 0)
    {
         snprintf(copy, CF_MAXVARSIZE, "%s:%s", frame.owner->ns, context);
    }
    else
    {
         strncpy(copy, context, CF_MAXVARSIZE);
    }

    if (Chop(copy, CF_EXPANDSIZE) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator");
    }

    if (strlen(copy) == 0)
    {
        return;
    }

    CfDebug("NewBundleClass(%s)\n", copy);
    
    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle %s aborted on defined class \"%s\"\n", frame.owner->name, copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, frame.owner->name);
        exit(1);
    }

    if (EvalContextHeapContainsSoft(ctx, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "WARNING - private class \"%s\" in bundle \"%s\" shadows a global class - you should choose a different name to avoid conflicts",
              copy, frame.owner->name);
    }

    if (EvalContextStackFrameContainsSoft(ctx, copy))
    {
        return;
    }

    StringSetAdd(frame.contexts, xstrdup(copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, frame.owner->ns))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, frame.owner->name);
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, frame.owner->ns))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -> Setting abort for \"%s\" when setting \"%s\"", ip->name, context);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
Esempio n. 4
0
void EvalContextHeapAddSoft(EvalContext *ctx, const char *context, const char *ns)
{
    char context_copy[CF_MAXVARSIZE];
    char canonified_context[CF_MAXVARSIZE];

    strcpy(canonified_context, context);
    if (Chop(canonified_context, CF_EXPANDSIZE) == -1)
    {
        Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator");
    }
    CanonifyNameInPlace(canonified_context);
    
    if (ns && strcmp(ns, "default") != 0)
    {
        snprintf(context_copy, CF_MAXVARSIZE, "%s:%s", ns, canonified_context);
    }
    else
    {
        strncpy(context_copy, canonified_context, CF_MAXVARSIZE);
    }

    if (strlen(context_copy) == 0)
    {
        return;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, context_copy))
    {
        Log(LOG_LEVEL_ERR, "Bundle aborted on defined class '%s'", context_copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, context_copy))
    {
        Log(LOG_LEVEL_ERR, "cf-agent aborted on defined class '%s'", context_copy);
        exit(1);
    }

    if (EvalContextHeapContainsSoft(ctx, context_copy))
    {
        return;
    }

    StringSetAdd(ctx->heap_soft, xstrdup(context_copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, ns))
        {
            Log(LOG_LEVEL_ERR, "cf-agent aborted on defined class '%s' defined in bundle '%s'", ip->name, StackFrameOwnerName(LastStackFrame(ctx, 0)));
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, ns))
            {
                Log(LOG_LEVEL_ERR, "Setting abort for '%s' when setting '%s'", ip->name, context_copy);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
Esempio n. 5
0
void NewBundleClass(EvalContext *ctx, const char *context, const char *bundle, const char *ns)
{
    char copy[CF_BUFSIZE];

    if (ns && strcmp(ns, "default") != 0)
    {
        snprintf(copy, CF_MAXVARSIZE, "%s:%s", ns, context);
    }
    else
    {
        strncpy(copy, context, CF_MAXVARSIZE);
    }

    if (Chop(copy, CF_EXPANDSIZE) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator");
    }

    if (strlen(copy) == 0)
    {
        return;
    }

    CfDebug("NewBundleClass(%s)\n", copy);
    
    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle %s aborted on defined class \"%s\"\n", bundle, copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, bundle);
        exit(1);
    }

    if (EvalContextHeapContainsSoft(ctx, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "WARNING - private class \"%s\" in bundle \"%s\" shadows a global class - you should choose a different name to avoid conflicts", copy, bundle);
    }

    if (EvalContextStackFrameContainsSoft(ctx, copy))
    {
        return;
    }

    EvalContextStackFrameAddSoft(ctx, copy);

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, ns))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, bundle);
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, ns))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -> Setting abort for \"%s\" when setting \"%s\"", ip->name, context);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
Esempio n. 6
0
int ScheduleAgentOperations(Bundle *bp, const ReportContext *report_context)
// NB - this function can be called recursively through "methods"
{
    SubType *sp;
    enum typesequence type;
    int pass;
    int save_pr_kept = PR_KEPT;
    int save_pr_repaired = PR_REPAIRED;
    int save_pr_notkept = PR_NOTKEPT;

    if (PROCESSREFRESH == NULL || (PROCESSREFRESH && IsRegexItemIn(PROCESSREFRESH, bp->name)))
    {
        DeleteItemList(PROCESSTABLE);
        PROCESSTABLE = NULL;
    }

    for (pass = 1; pass < CF_DONEPASSES; pass++)
    {
        for (type = 0; AGENT_TYPESEQUENCE[type] != NULL; type++)
        {
            ClassBanner(type);

            if ((sp = BundleGetSubType(bp, AGENT_TYPESEQUENCE[type])) == NULL)
            {
                continue;
            }

            BannerSubType(bp->name, sp->name, pass);
            SetScope(bp->name);

            if (!NewTypeContext(type))
            {
                continue;
            }

            for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++)
            {
                Promise *pp = SeqAt(sp->promises, ppi);

                if (ALLCLASSESREPORT)
                {
                    SaveClassEnvironment();
                }

                if (pass == 1)  // Count the number of promises modelled for efficiency
                {
                    CF_TOPICS++;
                }

                ExpandPromise(AGENT_TYPE_AGENT, bp->name, pp, KeepAgentPromise, report_context);

                if (Abort())
                {
                    NoteClassUsage(VADDCLASSES, false);
                    DeleteTypeContext(bp->parent_policy, type, report_context);
                    NoteBundleCompliance(bp, save_pr_kept, save_pr_repaired, save_pr_notkept);
                    return false;
                }
            }

            DeleteTypeContext(bp->parent_policy, type, report_context);
        }
    }

    NoteClassUsage(VADDCLASSES, false);
    return NoteBundleCompliance(bp, save_pr_kept, save_pr_repaired, save_pr_notkept);
}
Esempio n. 7
0
/* Checks the "varadmit" legacy ACL. */
static Item *ContextAccessControl(EvalContext *ctx, char *in, ServerConnectionState *conn, int encrypt)
{
    Auth *ap;
    int access = false;
    char client_regex[CF_BUFSIZE];
    Item *ip, *matches = NULL;

    int ret = sscanf(in, "CONTEXT %255[^\n]", client_regex);
    Item *persistent_classes = ListPersistentClasses();
    if (ret != 1 || persistent_classes == NULL)
    {
        return NULL;
    }

    for (ip = persistent_classes; ip != NULL; ip = ip->next)
    {
        /* Does the class match the regex that the agent requested? */
        if (StringMatchFull(client_regex, ip->name))
        {
            for (ap = SV.varadmit; ap != NULL; ap = ap->next)
            {
                /* Does the class match any of the regex in ACLs? */
                if (StringMatchFull(ap->path, ip->name))
                {
                    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(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(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(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(persistent_classes);
    return matches;
}
Esempio n. 8
0
/* Checks the "varadmit" legacy ACL. */
static int LiteralAccessControl(EvalContext *ctx, char *in, ServerConnectionState *conn, int encrypt)
{
    Auth *ap;
    int access = false;
    char name[CF_BUFSIZE];

    name[0] = '\0';

    if (strncmp(in, "VAR", 3) == 0)
    {
        sscanf(in, "VAR %255[^\n]", name);
    }
    else if (strncmp(in, "CALL_ME_BACK", strlen("CALL_ME_BACK")) == 0)
    {
        sscanf(in, "CALL_ME_BACK %255[^\n]", name);
    }
    else
    {
        sscanf(in, "QUERY %128s", name);
    }

    conn->maproot = false;

    for (ap = SV.varadmit; ap != NULL; ap = ap->next)
    {
        Log(LOG_LEVEL_VERBOSE, "Examining rule in access list (%s,%s)?", name, ap->path);

        if (strcmp(ap->path, name) == 0)                     /* exact match */
        {
            Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", name, ap->path);

            if ((!ap->literal) && (!ap->variable))
            {
                Log(LOG_LEVEL_ERR,
                    "Variable/query '%s' requires a literal server item...cannot set variable directly by path",
                      ap->path);
                access = false;
                break;
            }

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

                if ((IsMatchItemIn(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(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, name) == 0)
        {
            if ((IsMatchItemIn(ap->accesslist, MapAddress(conn->ipaddr)))
                || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)))
            {
                access = false;
                Log(LOG_LEVEL_VERBOSE, "Host %s explicitly denied access to %s", conn->hostname, name);
                break;
            }
        }
    }

    if (access)
    {
        Log(LOG_LEVEL_VERBOSE, "Host %s granted access to literal '%s'", conn->hostname, name);

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

    return access;
}
Esempio n. 9
0
static int AccessControl(EvalContext *ctx, const char *req_path, ServerConnectionState *conn, int encrypt)
{
    int access = false;
    char transrequest[CF_BUFSIZE];
    struct stat statbuf;
    char translated_req_path[CF_BUFSIZE];
    char transpath[CF_BUFSIZE];

/*
 * /var/cfengine -> $workdir translation.
 */
    TranslatePath(translated_req_path, req_path);

    if (ResolveFilename(translated_req_path, transrequest))
    {
        Log(LOG_LEVEL_VERBOSE, "Filename %s is resolved to %s", translated_req_path, transrequest);
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Couldn't resolve (realpath: %s) filename: %s",
            GetErrorStr(), translated_req_path);
        return false;                /* can't continue without transrequest */
    }

    if (lstat(transrequest, &statbuf) == -1)
    {
        Log(LOG_LEVEL_INFO, "Couldn't stat (lstat: %s) filename: %s",
            GetErrorStr(), transrequest);
        return false;
    }

    Log(LOG_LEVEL_DEBUG, "AccessControl, match (%s,%s) encrypt request = %d", transrequest, conn->hostname, encrypt);

    if (SV.admit == NULL)
    {
        Log(LOG_LEVEL_INFO, "cf-serverd access list is empty, no files are visible");
        return false;
    }

    conn->maproot = false;

    for (Auth *ap = SV.admit; ap != NULL; ap = ap->next)
    {
        int res = false;

        Log(LOG_LEVEL_DEBUG, "Examining rule in access list (%s,%s)", transrequest, ap->path);

        /* TODO MapName when constructing this list. */
        strncpy(transpath, ap->path, CF_BUFSIZE - 1);
        MapName(transpath);

        /* If everything is allowed */
        if ((strcmp(transpath, FILE_SEPARATOR_STR) == 0)
            ||
            /* or if transpath is a parent directory of transrequest */
            (strlen(transrequest) > strlen(transpath)
            && strncmp(transpath, transrequest, strlen(transpath)) == 0
            && transrequest[strlen(transpath)] == FILE_SEPARATOR)
            ||
            /* or if it's an exact match */
            (strcmp(transpath, transrequest) == 0))
        {
            res = true;
        }

        /* Exact match means single file to admit */
        if (strcmp(transpath, transrequest) == 0)
        {
            res = true;
        }

        if (res)
        {
            Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", transrequest, transpath);

            if (stat(transpath, &statbuf) == -1)
            {
                Log(LOG_LEVEL_INFO,
                      "Warning cannot stat file object %s in admit/grant, or access list refers to dangling link",
                      transpath);
                continue;
            }

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

                if ((IsMatchItemIn(ap->maproot, MapAddress(conn->ipaddr))) ||
                    (IsRegexItemIn(ctx, ap->maproot, conn->hostname)))
                {
                    conn->maproot = true;
                    Log(LOG_LEVEL_VERBOSE, "Mapping root privileges to access non-root files");
                }

                if ((IsMatchItemIn(ap->accesslist, MapAddress(conn->ipaddr)))
                    || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)))
                {
                    access = true;
                    Log(LOG_LEVEL_DEBUG, "Access granted to host: %s", conn->ipaddr);
                }
            }
            break;
        }
    }

    for (Auth *dp = SV.deny; dp != NULL; dp = dp->next)
    {
        strncpy(transpath, dp->path, CF_BUFSIZE - 1);
        MapName(transpath);

        /* If everything is denied */
        if ((strcmp(transpath, FILE_SEPARATOR_STR) == 0)
            ||
            /* or if transpath is a parent directory of transrequest */
            (strlen(transrequest) > strlen(transpath) &&
             strncmp(transpath, transrequest, strlen(transpath)) == 0 &&
             transrequest[strlen(transpath)] == FILE_SEPARATOR)
            ||
            /* or if it's an exact match */
            (strcmp(transpath, transrequest) == 0))
        {
            if ((IsMatchItemIn(dp->accesslist, MapAddress(conn->ipaddr))) ||
                (IsRegexItemIn(ctx, dp->accesslist, conn->hostname)))
            {
                access = false;
                Log(LOG_LEVEL_INFO, "Host '%s' in deny list, explicitly denying access to '%s'",
                    conn->ipaddr, transrequest);
                break;
            }
        }
    }

    if (access)
    {
        Log(LOG_LEVEL_VERBOSE, "Host %s granted access to %s", conn->hostname, req_path);

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

    return access;
}
Esempio n. 10
0
static int AuthorizeRoles(EvalContext *ctx, ServerConnectionState *conn, char *args)
{
    char *sp;
    Auth *ap;
    char userid1[CF_MAXVARSIZE], userid2[CF_MAXVARSIZE];
    Rlist *rp, *defines = NULL;
    int permitted = false;

    snprintf(userid1, CF_MAXVARSIZE, "%s@%s", conn->username, conn->hostname);
    snprintf(userid2, CF_MAXVARSIZE, "%s@%s", conn->username, conn->ipaddr);

    Log(LOG_LEVEL_VERBOSE, "Checking authorized roles in %s", args);

    if (strncmp(args, "--define", strlen("--define")) == 0)
    {
        sp = args + strlen("--define");
    }
    else
    {
        sp = args + strlen("-D");
    }

    while (*sp == ' ')
    {
        sp++;
    }

    defines = RlistFromSplitRegex(ctx, sp, "[,:;]", 99, false);

/* For each user-defined class attempt, check RBAC */

    for (rp = defines; rp != NULL; rp = rp->next)
    {
        Log(LOG_LEVEL_VERBOSE, "Verifying %s", RlistScalarValue(rp));

        for (ap = SV.roles; ap != NULL; ap = ap->next)
        {
            if (FullTextMatch(ctx, ap->path, RlistScalarValue(rp)))
            {
                /* We have a pattern covering this class - so are we allowed to activate it? */
                if ((IsMatchItemIn(ctx, ap->accesslist, MapAddress(conn->ipaddr))) ||
                    (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, userid1)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, userid2)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, conn->username)))
                {
                    Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is permitted", RlistScalarValue(rp));
                    permitted = true;
                }
                else
                {
                    Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is denied", RlistScalarValue(rp));
                    RlistDestroy(defines);
                    return false;
                }
            }
        }

    }

    if (permitted)
    {
        Log(LOG_LEVEL_VERBOSE, "Role activation allowed");
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE, "Role activation disallowed - abort execution");
    }

    RlistDestroy(defines);
    return permitted;
}
Esempio n. 11
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;
}
Esempio n. 12
0
int AccessControl(EvalContext *ctx, const char *req_path, ServerConnectionState *conn, int encrypt)
{
    Auth *ap;
    int access = false;
    char transrequest[CF_BUFSIZE];
    struct stat statbuf;
    char translated_req_path[CF_BUFSIZE];
    char transpath[CF_BUFSIZE];

/*
 * /var/cfengine -> $workdir translation.
 */
    TranslatePath(translated_req_path, req_path);

    if (ResolveFilename(translated_req_path, transrequest))
    {
        Log(LOG_LEVEL_VERBOSE, "Filename %s is resolved to %s", translated_req_path, transrequest);
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Couldn't resolve (realpath: %s) filename: %s",
            GetErrorStr(), translated_req_path);
    }

    if (lstat(transrequest, &statbuf) == -1)
    {
        Log(LOG_LEVEL_INFO, "Couldn't stat (lstat: %s) filename: %s",
            GetErrorStr(), transrequest);
        return false;
    }

    Log(LOG_LEVEL_DEBUG, "AccessControl, match (%s,%s) encrypt request = %d", transrequest, conn->hostname, encrypt);

    if (SV.admit == NULL)
    {
        Log(LOG_LEVEL_INFO, "cf-serverd access list is empty, no files are visible");
        return false;
    }

    conn->maproot = false;

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

        Log(LOG_LEVEL_DEBUG, "Examining rule in access list (%s,%s)", transrequest, ap->path);

        strncpy(transpath, ap->path, CF_BUFSIZE - 1);
        MapName(transpath);

        if ((strlen(transrequest) > strlen(transpath)) && (strncmp(transpath, transrequest, strlen(transpath)) == 0)
            && (transrequest[strlen(transpath)] == FILE_SEPARATOR))
        {
            res = true;         /* Substring means must be a / to link, else just a substring og filename */
        }

        /* Exact match means single file to admit */

        if (strcmp(transpath, transrequest) == 0)
        {
            res = true;
        }

        if (strcmp(transpath, "/") == 0)
        {
            res = true;
        }

        if (res)
        {
            Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", transrequest, transpath);

            if (stat(transpath, &statbuf) == -1)
            {
                Log(LOG_LEVEL_INFO,
                      "Warning cannot stat file object %s in admit/grant, or access list refers to dangling link\n",
                      transpath);
                continue;
            }

            if ((!encrypt) && (ap->encrypt == true))
            {
                Log(LOG_LEVEL_ERR, "File %s requires encrypt connection...will not serve", transpath);
                access = false;
            }
            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 to access non-root files");
                }

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

    if (strncmp(transpath, transrequest, strlen(transpath)) == 0)
    {
        for (ap = SV.deny; ap != NULL; ap = ap->next)
        {
            if (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))
            {
                access = false;
                Log(LOG_LEVEL_INFO, "Host %s explicitly denied access to %s", conn->hostname, transrequest);
                break;
            }
        }
    }

    if (access)
    {
        Log(LOG_LEVEL_VERBOSE, "Host %s granted access to %s", conn->hostname, req_path);

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

    if (!conn->rsa_auth)
    {
        Log(LOG_LEVEL_INFO, "Cannot map root access without RSA authentication");
        conn->maproot = false;  /* only public files accessible */
    }

    return access;
}