/** * The "roles" access promise is for remote class activation by means of * cf-runagent -D: * * pp->promiser is a regex to match classes. * pp->conlist is an slist of usernames. */ static void KeepServerRolePromise(EvalContext *ctx, const Promise *pp) { size_t pos = acl_SortedInsert(&roles_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } size_t i = SeqLength(pp->conlist); while (i > 0) { i--; Constraint *cp = SeqAt(pp->conlist, i); char const * const authorizer = CF_REMROLE_BODIES[REMOTE_ROLE_AUTHORIZE].lval; if (strcmp(cp->lval, authorizer) == 0) { if (cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "Right-hand side of authorize promise for '%s' should be a list", pp->promiser); } else if (IsDefinedClass(ctx, cp->classes)) { for (const Rlist *rp = cp->rval.item; rp != NULL; rp = rp->next) { /* The "roles" access promise currently only supports * listing usernames to admit access to, nothing more. */ struct resource_acl *racl = &roles_acl->acls[pos]; size_t zret = StrList_Append(&racl->admit.usernames, RlistScalarValue(rp)); if (zret == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "StrList_Append: %s", GetErrorStr()); exit(255); } } } } else if (strcmp(cp->lval, "comment") != 0 && strcmp(cp->lval, "handle") != 0 && /* Are there other known list constraints ? if not, skip this: */ cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_WARNING, "Unrecognised promise '%s' for %s", cp->lval, pp->promiser); } } }
static void KeepBundlesAccessPromise(EvalContext *ctx, const Promise *pp) { size_t pos = acl_SortedInsert(&bundles_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } /* Last params are NULL because we don't have * old-school Auth type ACLs here. */ AccessPromise_AddAccessConstraints(ctx, pp, &bundles_acl->acls[pos], NULL, NULL); }
static void KeepQueryAccessPromise(EvalContext *ctx, const Promise *pp) { Auth *dp = GetOrCreateAuth(pp->promiser, &SV.vardeny, &SV.vardenytail), *ap = GetOrCreateAuth(pp->promiser, &SV.varadmit, &SV.varadmittail); RegisterLiteralServerData(ctx, pp->promiser, pp); ap->literal = true; size_t pos = acl_SortedInsert(&query_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &query_acl->acls[pos], ap, dp); }
void KeepLiteralAccessPromise(EvalContext *ctx, const Promise *pp, const char *type) { Auth *ap, *dp; const char *handle = PromiseGetHandle(pp); if (handle == NULL && strcmp(type, "literal") == 0) { Log(LOG_LEVEL_ERR, "Access to literal server data requires you to define a promise handle for reference"); return; } if (strcmp(type, "literal") == 0) { Log(LOG_LEVEL_VERBOSE,"Looking at literal access promise '%s', type '%s'", pp->promiser, type); ap = GetOrCreateAuth(handle, &SV.varadmit, &SV.varadmittail); dp = GetOrCreateAuth(handle, &SV.vardeny, &SV.vardenytail); RegisterLiteralServerData(ctx, handle, pp); ap->literal = true; size_t pos = acl_SortedInsert(&literals_acl, handle); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &literals_acl->acls[pos], ap, dp); } else { Log(LOG_LEVEL_VERBOSE,"Looking at context/var access promise '%s', type '%s'", pp->promiser, type); ap = GetOrCreateAuth(pp->promiser, &SV.varadmit, &SV.varadmittail); dp = GetOrCreateAuth(pp->promiser, &SV.vardeny, &SV.vardenytail); if (strcmp(type, "context") == 0) { ap->classpattern = true; size_t pos = acl_SortedInsert(&classes_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &classes_acl->acls[pos], ap, dp); } else if (strcmp(type, "variable") == 0) { ap->variable = true; size_t pos = acl_SortedInsert(&vars_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &vars_acl->acls[pos], ap, dp); } } }
static void KeepFileAccessPromise(const EvalContext *ctx, const Promise *pp) { char path[PATH_MAX]; size_t path_len = strlen(pp->promiser); if (path_len > sizeof(path) - 1) { goto err_too_long; } memcpy(path, pp->promiser, path_len + 1); /* Resolve symlinks and canonicalise access_rules path. */ size_t ret2 = PreprocessRequestPath(path, sizeof(path)); if (ret2 == (size_t) -1) { if (errno != ENOENT) /* something went wrong */ { Log(LOG_LEVEL_ERR, "Failed to canonicalize path '%s' in access_rules, ignoring!", pp->promiser); return; } else /* file does not exist, it doesn't matter */ { Log(LOG_LEVEL_INFO, "Path does not exist, it's added as-is in access rules: %s", path); Log(LOG_LEVEL_INFO, "WARNING: this means that (not) having a trailing slash defines if it's (not) a directory!"); /* Legacy: convert trailing "/." to "/" */ if (path_len >= 2 && path[path_len - 1] == '.' && path[path_len - 2] == '/') { path[path_len - 1] = '\0'; path_len--; } } } else /* file exists, path canonicalised */ { /* If it's a directory append trailing '/' */ path_len = ret2; int is_dir = IsDirReal(path); if (is_dir == 1 && path[path_len - 1] != FILE_SEPARATOR) { if (path_len + 2 > sizeof(path)) { goto err_too_long; } PathAppendTrailingSlash(path, path_len); path_len++; } } size_t pos = acl_SortedInsert(&paths_acl, path); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } /* Legacy code */ if (path_len != 1) { DeleteSlash(path); } Auth *ap = GetOrCreateAuth(path, &SV.admit, &SV.admittail); Auth *dp = GetOrCreateAuth(path, &SV.deny, &SV.denytail); AccessPromise_AddAccessConstraints(ctx, pp, &paths_acl->acls[pos], ap, dp); return; err_too_long: Log(LOG_LEVEL_ERR, "Path '%s' in access_rules is too long (%zu > %d), ignoring!", pp->promiser, strlen(pp->promiser), PATH_MAX); return; }