1 /*
2   Copyright 2021 Northern.tech AS
3 
4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 3.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
18 
19   To the extent this program is licensed as part of the Enterprise
20   versions of CFEngine, the applicable Commercial Open Source License
21   (COSL) may apply to this file if you as a licensee so wish it. See
22   included file COSL.txt.
23 */
24 
25 /*
26   This file can act as a template for adding functionality to cfengine 3.  All
27   functionality can be added by extending the main array
28 
29   CF_MOD_PROMISE_TYPES[CF3_MODULES]
30 
31   and its array dimension, in mod_common, in the manner shown here.
32 */
33 
34 #include <mod_access.h>
35 
36 #include <syntax.h>
37 #include <string_lib.h>
38 #include <policy.h>
39 
40 /*
41   Read this module file backwards, as dependencies have to be defined first -
42   these arrays declare pairs of constraints
43 
44   lval => rval
45 
46   in the form (lval,type,range)
47 
48   If the type is cf_body then the range is a pointer to another array of pairs,
49   like in a body "sub-routine"
50 */
51 
52 static const char *const POLICY_ERROR_WRONG_RESOURCE_FOR_DATA_SELECT =
53     "Constraint report_data_select is allowed only for 'query' resource_type";
54 
55 static bool AccessParseTreeCheck(const Promise *pp, Seq *errors);
56 
57 static const ConstraintSyntax report_data_select_constraints[] =
58 {
59     CONSTRAINT_SYNTAX_GLOBAL,
60     ConstraintSyntaxNewStringList("classes_include", CF_ANYSTRING, "List of regex filters for class names to be included into class report", SYNTAX_STATUS_REMOVED),
61     ConstraintSyntaxNewStringList("classes_exclude", CF_ANYSTRING, "List of regex filters for class names to be excluded from class report", SYNTAX_STATUS_REMOVED),
62     ConstraintSyntaxNewStringList("variables_include", CF_ANYSTRING, "List of regex filters for variable full qualified path to be included into variables report", SYNTAX_STATUS_REMOVED),
63     ConstraintSyntaxNewStringList("variables_exclude", CF_ANYSTRING, "List of regex filters for variable full qualified path to be excluded from variables report", SYNTAX_STATUS_REMOVED),
64     ConstraintSyntaxNewStringList("promise_notkept_log_include", CF_ANYSTRING, "List of regex filters for handle name to be included into promise not kept log report", SYNTAX_STATUS_REMOVED),
65     ConstraintSyntaxNewStringList("promise_notkept_log_exclude", CF_ANYSTRING, "List of regex filters for handle name to be excluded from promise not kept log report", SYNTAX_STATUS_REMOVED),
66     ConstraintSyntaxNewStringList("promise_repaired_log_include", CF_ANYSTRING, "List of regex filters for handle name to be included into promise repaired log report", SYNTAX_STATUS_REMOVED),
67     ConstraintSyntaxNewStringList("promise_repaired_log_exclude", CF_ANYSTRING, "List of regex filters for handle name to be excluded from promise repaired log report", SYNTAX_STATUS_REMOVED),
68     ConstraintSyntaxNewStringList("monitoring_include", CF_ANYSTRING, "List of regex filters for slot name to be included from monitoring report", SYNTAX_STATUS_NORMAL),
69     ConstraintSyntaxNewStringList("monitoring_exclude", CF_ANYSTRING, "List of regex filters for slot name to be excluded from monitoring report", SYNTAX_STATUS_NORMAL),
70     ConstraintSyntaxNewStringList("metatags_include", CF_ANYSTRING, "List of regex filters for metatags to be included into reports", SYNTAX_STATUS_NORMAL),
71     ConstraintSyntaxNewStringList("metatags_exclude", CF_ANYSTRING, "List of regex filters for metatags to be excluded from reports", SYNTAX_STATUS_NORMAL),
72     ConstraintSyntaxNewStringList("promise_handle_include", CF_ANYSTRING, "List of regex filters for promise handle to be included into reports", SYNTAX_STATUS_NORMAL),
73     ConstraintSyntaxNewStringList("promise_handle_exclude", CF_ANYSTRING, "List of regex filters for promise handle to be excluded from reports", SYNTAX_STATUS_NORMAL),
74     ConstraintSyntaxNewNull()
75 };
76 
77 static const BodySyntax report_data_select_body = BodySyntaxNew("report_data_select", report_data_select_constraints, NULL, SYNTAX_STATUS_NORMAL);
78 
79 const ConstraintSyntax CF_REMACCESS_BODIES[REMOTE_ACCESS_NONE + 1] =
80 {
81     ConstraintSyntaxNewStringList("admit", "", "List of host names or IP addresses to grant access to file objects", SYNTAX_STATUS_NORMAL),
82     ConstraintSyntaxNewStringList("deny", "", "List of host names or IP addresses to deny access to file objects", SYNTAX_STATUS_NORMAL),
83     ConstraintSyntaxNewStringList("admit_ips", "", "List of IP addresses or subnet masks to grant access to file objects", SYNTAX_STATUS_NORMAL),
84     ConstraintSyntaxNewStringList("deny_ips", "", "List of IP addresses or subnet masks to deny access to file objects", SYNTAX_STATUS_NORMAL),
85     ConstraintSyntaxNewStringList("admit_hostnames", "", "List of hostnames to grant access to file objects", SYNTAX_STATUS_NORMAL),
86     ConstraintSyntaxNewStringList("deny_hostnames", "", "List of hostnames to deny access to file objects", SYNTAX_STATUS_NORMAL),
87     ConstraintSyntaxNewStringList("admit_keys", "", "List of host keys that will be granted access to file objects", SYNTAX_STATUS_NORMAL),
88     ConstraintSyntaxNewStringList("deny_keys", "", "List of host keys that will be denied access to file objects", SYNTAX_STATUS_NORMAL),
89     ConstraintSyntaxNewStringList("maproot", "", "List of host names or IP addresses to grant full read-privilege on the server", SYNTAX_STATUS_NORMAL),
90     ConstraintSyntaxNewBool("ifencrypted", "true/false whether the current file access promise is conditional on the connection from the client being encrypted. Default value: false", SYNTAX_STATUS_NORMAL),
91     ConstraintSyntaxNewOption("resource_type", "path,literal,context,query,variable,bundle", "The type of object being granted access (the default is path and grants access to files)", SYNTAX_STATUS_NORMAL),
92     ConstraintSyntaxNewBody("report_data_select", &report_data_select_body, "Report content filter", SYNTAX_STATUS_NORMAL),
93     ConstraintSyntaxNewString("shortcut", "", "For path resource_type, the server will expand a relative path beginning with this text", SYNTAX_STATUS_NORMAL),
94     ConstraintSyntaxNewNull()
95 };
96 
97 const ConstraintSyntax CF_REMROLE_BODIES[REMOTE_ROLE_NONE + 1] =
98 {
99     ConstraintSyntaxNewStringList("authorize", "", "List of public-key user names that are allowed to activate the promised class during remote agent activation", SYNTAX_STATUS_NORMAL),
100     ConstraintSyntaxNewNull()
101 };
102 
103 const PromiseTypeSyntax CF_REMACCESS_PROMISE_TYPES[] =
104 {
105     PromiseTypeSyntaxNew("server", "access", CF_REMACCESS_BODIES, &AccessParseTreeCheck, SYNTAX_STATUS_NORMAL),
106     PromiseTypeSyntaxNew("server", "roles", CF_REMROLE_BODIES, NULL, SYNTAX_STATUS_NORMAL),
107     PromiseTypeSyntaxNewNull()
108 };
109 
AccessParseTreeCheck(const Promise * pp,Seq * errors)110 static bool AccessParseTreeCheck(const Promise *pp, Seq *errors)
111 {
112     bool success = true;
113 
114     bool isResourceType = false;
115     bool isReportDataSelect = false;
116     Constraint *data_select_const = NULL;
117 
118     for (size_t i = 0; i <SeqLength(pp->conlist); i++)
119     {
120         Constraint *con = SeqAt(pp->conlist, i);
121 
122         if (StringSafeCompare("resource_type", con->lval) == 0)
123         {
124             if (con->rval.type == RVAL_TYPE_SCALAR)
125             {
126                 if (StringSafeCompare("query", (char*)con->rval.item) == 0)
127                 {
128                     isResourceType = true;
129                 }
130             }
131         }
132         else if (StringSafeCompare("report_data_select", con->lval) == 0)
133         {
134             data_select_const = con;
135             isReportDataSelect = true;
136         }
137 
138     }
139 
140     if (isReportDataSelect && !isResourceType)
141     {
142         SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, data_select_const,
143                                          POLICY_ERROR_WRONG_RESOURCE_FOR_DATA_SELECT));
144         success = false;
145     }
146 
147     return success;
148 }
149 
150