1 /*
2 Copyright 2020 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 #include <attributes.h>
26
27 #include <promises.h>
28 #include <policy.h>
29 #include <conversion.h>
30 #include <logging.h>
31 #include <chflags.h>
32 #include <audit.h>
33 #include <protocol.h> // ParseProtocolVersionPolicy()
34
35 #define CF_DEFINECLASSES "classes"
36 #define CF_TRANSACTION "action"
37
38 static FilePerms GetPermissionConstraints(const EvalContext *ctx, const Promise *pp);
39
ClearFilesAttributes(Attributes * whom)40 void ClearFilesAttributes(Attributes *whom)
41 {
42 UidListDestroy(whom->perms.owners);
43 GidListDestroy(whom->perms.groups);
44 }
45
GetFilesAttributes(const EvalContext * ctx,const Promise * pp)46 Attributes GetFilesAttributes(const EvalContext *ctx, const Promise *pp)
47 {
48 Attributes attr = ZeroAttributes;
49
50 // default for file copy
51
52 attr.havedepthsearch = PromiseGetConstraintAsBoolean(ctx, "depth_search", pp);
53 attr.haveselect = PromiseGetConstraintAsBoolean(ctx, "file_select", pp);
54 attr.haverename = PromiseGetConstraintAsBoolean(ctx, "rename", pp);
55 attr.havedelete = PromiseGetConstraintAsBoolean(ctx, "delete", pp);
56 attr.content = PromiseGetConstraintAsRval(pp, "content", RVAL_TYPE_SCALAR);
57 attr.haveperms = PromiseGetConstraintAsBoolean(ctx, "perms", pp);
58 attr.havechange = PromiseGetConstraintAsBoolean(ctx, "changes", pp);
59 attr.havecopy = PromiseGetConstraintAsBoolean(ctx, "copy_from", pp);
60 attr.havelink = PromiseGetConstraintAsBoolean(ctx, "link_from", pp);
61
62 attr.edit_template = PromiseGetConstraintAsRval(pp, "edit_template", RVAL_TYPE_SCALAR);
63 attr.edit_template_string = PromiseGetConstraintAsRval(pp, "edit_template_string", RVAL_TYPE_SCALAR);
64 attr.template_method = PromiseGetConstraintAsRval(pp, "template_method", RVAL_TYPE_SCALAR);
65 attr.template_data = PromiseGetConstraintAsRval(pp, "template_data", RVAL_TYPE_CONTAINER);
66
67 if (!attr.template_method )
68 {
69 attr.template_method = "cfengine";
70 }
71
72 attr.haveeditline = PromiseBundleOrBodyConstraintExists(ctx, "edit_line", pp);
73 attr.haveeditxml = PromiseBundleOrBodyConstraintExists(ctx, "edit_xml", pp);
74 attr.haveedit = (attr.haveeditline) || (attr.haveeditxml) || (attr.edit_template) || (attr.edit_template_string);
75
76 /* Files, specialist */
77
78 attr.repository = PromiseGetConstraintAsRval(pp, "repository", RVAL_TYPE_SCALAR);
79 attr.create = PromiseGetConstraintAsBoolean(ctx, "create", pp);
80 attr.touch = PromiseGetConstraintAsBoolean(ctx, "touch", pp);
81 attr.transformer = PromiseGetConstraintAsRval(pp, "transformer", RVAL_TYPE_SCALAR);
82 attr.move_obstructions = PromiseGetConstraintAsBoolean(ctx, "move_obstructions", pp);
83 attr.pathtype = PromiseGetConstraintAsRval(pp, "pathtype", RVAL_TYPE_SCALAR);
84 attr.file_type = PromiseGetConstraintAsRval(pp, "file_type", RVAL_TYPE_SCALAR);
85
86 attr.acl = GetAclConstraints(ctx, pp);
87 attr.perms = GetPermissionConstraints(ctx, pp);
88 attr.select = GetSelectConstraints(ctx, pp);
89 attr.delete = GetDeleteConstraints(ctx, pp);
90 attr.rename = GetRenameConstraints(ctx, pp);
91 attr.change = GetChangeMgtConstraints(ctx, pp);
92 attr.copy = GetCopyConstraints(ctx, pp);
93 attr.link = GetLinkConstraints(ctx, pp);
94 attr.edits = GetEditDefaults(ctx, pp);
95
96 if (attr.edit_template || attr.edit_template_string)
97 {
98 attr.edits.empty_before_use = true;
99 attr.edits.inherit = true;
100 }
101
102 /* Files, multiple use */
103
104 attr.recursion = GetRecursionConstraints(ctx, pp);
105
106 /* Common ("included") */
107
108 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
109 attr.transaction = GetTransactionConstraints(ctx, pp);
110 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
111 attr.classes = GetClassDefinitionConstraints(ctx, pp);
112
113 return attr;
114 }
115
116 /*******************************************************************/
117
GetReportsAttributes(const EvalContext * ctx,const Promise * pp)118 Attributes GetReportsAttributes(const EvalContext *ctx, const Promise *pp)
119 {
120 Attributes attr = ZeroAttributes;
121
122 attr.transaction = GetTransactionConstraints(ctx, pp);
123 attr.classes = GetClassDefinitionConstraints(ctx, pp);
124
125 attr.report = GetReportConstraints(ctx, pp);
126 return attr;
127 }
128
129 /*******************************************************************/
130
GetEnvironmentsAttributes(const EvalContext * ctx,const Promise * pp)131 Attributes GetEnvironmentsAttributes(const EvalContext *ctx, const Promise *pp)
132 {
133 Attributes attr = ZeroAttributes;
134
135 attr.transaction = GetTransactionConstraints(ctx, pp);
136 attr.classes = GetClassDefinitionConstraints(ctx, pp);
137 attr.env = GetEnvironmentsConstraints(ctx, pp);
138
139 return attr;
140 }
141
142 /*******************************************************************/
143
GetServicesAttributes(const EvalContext * ctx,const Promise * pp)144 Attributes GetServicesAttributes(const EvalContext *ctx, const Promise *pp)
145 {
146 Attributes attr = ZeroAttributes;
147
148 attr.transaction = GetTransactionConstraints(ctx, pp);
149 attr.classes = GetClassDefinitionConstraints(ctx, pp);
150 attr.service = GetServicesConstraints(ctx, pp);
151 attr.havebundle = PromiseBundleOrBodyConstraintExists(ctx, "service_bundle", pp);
152
153 return attr;
154 }
155
156 /*******************************************************************/
157
GetPackageAttributes(const EvalContext * ctx,const Promise * pp)158 Attributes GetPackageAttributes(const EvalContext *ctx, const Promise *pp)
159 {
160 Attributes attr = ZeroAttributes;
161
162 attr.transaction = GetTransactionConstraints(ctx, pp);
163 attr.classes = GetClassDefinitionConstraints(ctx, pp);
164 attr.packages = GetPackageConstraints(ctx, pp);
165 attr.new_packages = GetNewPackageConstraints(ctx, pp);
166 return attr;
167 }
168
169 /*******************************************************************/
170
GetUserConstraints(const EvalContext * ctx,const Promise * pp)171 static User GetUserConstraints(const EvalContext *ctx, const Promise *pp)
172 {
173 User u;
174 char *value;
175
176 value = PromiseGetConstraintAsRval(pp, "policy", RVAL_TYPE_SCALAR);
177 u.policy = UserStateFromString(value);
178
179 u.uid = PromiseGetConstraintAsRval(pp, "uid", RVAL_TYPE_SCALAR);
180
181 value = PromiseGetConstraintAsRval(pp, "format", RVAL_TYPE_SCALAR);
182 u.password_format = PasswordFormatFromString(value);
183 u.password = PromiseGetConstraintAsRval(pp, "data", RVAL_TYPE_SCALAR);
184 u.description = PromiseGetConstraintAsRval(pp, "description", RVAL_TYPE_SCALAR);
185
186 u.group_primary = PromiseGetConstraintAsRval(pp, "group_primary", RVAL_TYPE_SCALAR);
187 u.home_dir = PromiseGetConstraintAsRval(pp, "home_dir", RVAL_TYPE_SCALAR);
188 u.shell = PromiseGetConstraintAsRval(pp, "shell", RVAL_TYPE_SCALAR);
189
190 u.groups_secondary = PromiseGetConstraintAsList(ctx, "groups_secondary", pp);
191
192 const Constraint *cp = PromiseGetImmediateConstraint(pp, "groups_secondary");
193 u.groups_secondary_given = (cp != NULL);
194
195 if (value && ((u.policy) == USER_STATE_NONE))
196 {
197 Log(LOG_LEVEL_ERR, "Unsupported user policy '%s' in users promise", value);
198 PromiseRef(LOG_LEVEL_ERR, pp);
199 }
200
201 return u;
202 }
203
GetUserAttributes(const EvalContext * ctx,const Promise * pp)204 Attributes GetUserAttributes(const EvalContext *ctx, const Promise *pp)
205 {
206 Attributes attr = ZeroAttributes;
207
208 attr.havebundle = PromiseBundleOrBodyConstraintExists(ctx, "home_bundle", pp);
209
210 attr.inherit = PromiseGetConstraintAsBoolean(ctx, "home_bundle_inherit", pp);
211
212 attr.transaction = GetTransactionConstraints(ctx, pp);
213 attr.classes = GetClassDefinitionConstraints(ctx, pp);
214 attr.users = GetUserConstraints(ctx, pp);
215 return attr;
216 }
217
218 /*******************************************************************/
219
GetDatabaseAttributes(const EvalContext * ctx,const Promise * pp)220 Attributes GetDatabaseAttributes(const EvalContext *ctx, const Promise *pp)
221 {
222 Attributes attr = ZeroAttributes;
223
224 attr.transaction = GetTransactionConstraints(ctx, pp);
225 attr.classes = GetClassDefinitionConstraints(ctx, pp);
226 attr.database = GetDatabaseConstraints(ctx, pp);
227 return attr;
228 }
229
230 /*******************************************************************/
231
GetClassContextAttributes(const EvalContext * ctx,const Promise * pp)232 Attributes GetClassContextAttributes(const EvalContext *ctx, const Promise *pp)
233 {
234 Attributes a = ZeroAttributes;
235
236 a.transaction = GetTransactionConstraints(ctx, pp);
237 a.classes = GetClassDefinitionConstraints(ctx, pp);
238 a.context = GetContextConstraints(ctx, pp);
239
240 return a;
241 }
242
243 /*******************************************************************/
244
GetExecAttributes(const EvalContext * ctx,const Promise * pp)245 Attributes GetExecAttributes(const EvalContext *ctx, const Promise *pp)
246 {
247 Attributes attr = ZeroAttributes;
248
249 attr.contain = GetExecContainConstraints(ctx, pp);
250 attr.havecontain = PromiseGetConstraintAsBoolean(ctx, "contain", pp);
251
252 attr.args = PromiseGetConstraintAsRval(pp, "args", RVAL_TYPE_SCALAR);
253 attr.arglist = PromiseGetConstraintAsList(ctx, "arglist", pp);
254 attr.module = PromiseGetConstraintAsBoolean(ctx, "module", pp);
255
256 // Possible to suppress info level messages per commands promise:
257 if (PromiseBundleOrBodyConstraintExists(ctx, "inform", pp))
258 {
259 attr.inform = PromiseGetConstraintAsBoolean(ctx, "inform", pp);
260 }
261 else
262 {
263 attr.inform = true; // Default to printing the inform messages
264 }
265
266 /* Common ("included") */
267
268 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
269 attr.transaction = GetTransactionConstraints(ctx, pp);
270
271 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
272 attr.classes = GetClassDefinitionConstraints(ctx, pp);
273
274 return attr;
275 }
276
277 /*******************************************************************/
278
GetProcessAttributes(const EvalContext * ctx,const Promise * pp)279 Attributes GetProcessAttributes(const EvalContext *ctx, const Promise *pp)
280 {
281 Attributes attr = ZeroAttributes;
282
283 attr.signals = PromiseGetConstraintAsList(ctx, "signals", pp);
284 attr.process_stop = PromiseGetConstraintAsRval(pp, "process_stop", RVAL_TYPE_SCALAR);
285 attr.haveprocess_count = PromiseGetConstraintAsBoolean(ctx, "process_count", pp);
286 attr.haveselect = PromiseGetConstraintAsBoolean(ctx, "process_select", pp);
287 attr.restart_class = PromiseGetConstraintAsRval(pp, "restart_class", RVAL_TYPE_SCALAR);
288
289 attr.process_count = GetMatchesConstraints(ctx, pp);
290 attr.process_select = GetProcessFilterConstraints(ctx, pp);
291
292 /* Common ("included") */
293
294 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
295 attr.transaction = GetTransactionConstraints(ctx, pp);
296
297 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
298 attr.classes = GetClassDefinitionConstraints(ctx, pp);
299
300 return attr;
301 }
302
303 /*******************************************************************/
304
GetStorageAttributes(const EvalContext * ctx,const Promise * pp)305 Attributes GetStorageAttributes(const EvalContext *ctx, const Promise *pp)
306 {
307 Attributes attr = ZeroAttributes;
308
309 attr.mount = GetMountConstraints(ctx, pp);
310 attr.volume = GetVolumeConstraints(ctx, pp);
311 attr.havevolume = PromiseGetConstraintAsBoolean(ctx, "volume", pp);
312 attr.havemount = PromiseGetConstraintAsBoolean(ctx, "mount", pp);
313
314 /* Common ("included") */
315
316 if (attr.edits.maxfilesize <= 0)
317 {
318 attr.edits.maxfilesize = EDITFILESIZE;
319 }
320
321 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
322 attr.transaction = GetTransactionConstraints(ctx, pp);
323
324 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
325 attr.classes = GetClassDefinitionConstraints(ctx, pp);
326
327 return attr;
328 }
329
330 /*******************************************************************/
331
GetMethodAttributes(const EvalContext * ctx,const Promise * pp)332 Attributes GetMethodAttributes(const EvalContext *ctx, const Promise *pp)
333 {
334 Attributes attr = ZeroAttributes;
335
336 attr.havebundle = PromiseBundleOrBodyConstraintExists(ctx, "usebundle", pp);
337
338 attr.inherit = PromiseGetConstraintAsBoolean(ctx, "inherit", pp);
339
340 /* Common ("included") */
341
342 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
343 attr.transaction = GetTransactionConstraints(ctx, pp);
344
345 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
346 attr.classes = GetClassDefinitionConstraints(ctx, pp);
347
348 return attr;
349 }
350
GetMeasurementAttributes(const EvalContext * ctx,const Promise * pp)351 Attributes GetMeasurementAttributes(const EvalContext *ctx, const Promise *pp)
352 {
353 Attributes attr = ZeroAttributes;
354
355 attr.measure = GetMeasurementConstraint(ctx, pp);
356
357 /* Common ("included") */
358
359 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
360 attr.transaction = GetTransactionConstraints(ctx, pp);
361
362 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
363 attr.classes = GetClassDefinitionConstraints(ctx, pp);
364
365 return attr;
366 }
367
368 /*******************************************************************/
369 /* Level */
370 /*******************************************************************/
371
GetServicesConstraints(const EvalContext * ctx,const Promise * pp)372 Services GetServicesConstraints(const EvalContext *ctx, const Promise *pp)
373 {
374 Services s;
375
376 s.service_type = PromiseGetConstraintAsRval(pp, "service_type", RVAL_TYPE_SCALAR);
377 s.service_policy = PromiseGetConstraintAsRval(pp, "service_policy", RVAL_TYPE_SCALAR);
378 s.service_autostart_policy = PromiseGetConstraintAsRval(pp, "service_autostart_policy", RVAL_TYPE_SCALAR);
379 s.service_args = PromiseGetConstraintAsRval(pp, "service_args", RVAL_TYPE_SCALAR);
380 s.service_depend = PromiseGetConstraintAsList(ctx, "service_dependencies", pp);
381 s.service_depend_chain = PromiseGetConstraintAsRval(pp, "service_dependence_chain", RVAL_TYPE_SCALAR);
382
383 return s;
384 }
385
386 /*******************************************************************/
387
GetEnvironmentsConstraints(const EvalContext * ctx,const Promise * pp)388 Environments GetEnvironmentsConstraints(const EvalContext *ctx, const Promise *pp)
389 {
390 Environments e;
391
392 e.cpus = PromiseGetConstraintAsInt(ctx, "env_cpus", pp);
393 e.memory = PromiseGetConstraintAsInt(ctx, "env_memory", pp);
394 e.disk = PromiseGetConstraintAsInt(ctx, "env_disk", pp);
395 e.baseline = PromiseGetConstraintAsRval(pp, "env_baseline", RVAL_TYPE_SCALAR);
396 e.spec = PromiseGetConstraintAsRval(pp, "env_spec", RVAL_TYPE_SCALAR);
397 e.host = PromiseGetConstraintAsRval(pp, "environment_host", RVAL_TYPE_SCALAR);
398
399 e.addresses = PromiseGetConstraintAsList(ctx, "env_addresses", pp);
400 e.name = PromiseGetConstraintAsRval(pp, "env_name", RVAL_TYPE_SCALAR);
401 e.type = PromiseGetConstraintAsRval(pp, "environment_type", RVAL_TYPE_SCALAR);
402 e.state = EnvironmentStateFromString(PromiseGetConstraintAsRval(pp, "environment_state", RVAL_TYPE_SCALAR));
403
404 return e;
405 }
406
407 /*******************************************************************/
408
GetExecContainConstraints(const EvalContext * ctx,const Promise * pp)409 ExecContain GetExecContainConstraints(const EvalContext *ctx, const Promise *pp)
410 {
411 ExecContain e;
412
413 e.shelltype = ShellTypeFromString(PromiseGetConstraintAsRval(pp, "useshell", RVAL_TYPE_SCALAR));
414 e.umask = PromiseGetConstraintAsOctal(ctx, "umask", pp);
415 e.owner = PromiseGetConstraintAsUid(ctx, "exec_owner", pp);
416 e.group = PromiseGetConstraintAsGid(ctx, "exec_group", pp);
417 e.preview = PromiseGetConstraintAsBoolean(ctx, "preview", pp);
418 if (PromiseBundleOrBodyConstraintExists(ctx, "no_output", pp))
419 {
420 e.nooutput = PromiseGetConstraintAsBoolean(ctx, "no_output", pp);
421 }
422 else
423 {
424 e.nooutput = PromiseGetConstraintAsBoolean(ctx, "module", pp);
425 }
426 e.timeout = PromiseGetConstraintAsInt(ctx, "exec_timeout", pp);
427 e.chroot = PromiseGetConstraintAsRval(pp, "chroot", RVAL_TYPE_SCALAR);
428 e.chdir = PromiseGetConstraintAsRval(pp, "chdir", RVAL_TYPE_SCALAR);
429
430 return e;
431 }
432
433 /*******************************************************************/
434
GetRecursionConstraints(const EvalContext * ctx,const Promise * pp)435 DirectoryRecursion GetRecursionConstraints(const EvalContext *ctx, const Promise *pp)
436 {
437 DirectoryRecursion r;
438
439 r.travlinks = PromiseGetConstraintAsBoolean(ctx, "traverse_links", pp);
440 r.rmdeadlinks = PromiseGetConstraintAsBoolean(ctx, "rmdeadlinks", pp);
441 r.depth = PromiseGetConstraintAsInt(ctx, "depth", pp);
442
443 if (r.depth == CF_NOINT)
444 {
445 r.depth = 0;
446 }
447
448 r.xdev = PromiseGetConstraintAsBoolean(ctx, "xdev", pp);
449 r.include_dirs = PromiseGetConstraintAsList(ctx, "include_dirs", pp);
450 r.exclude_dirs = PromiseGetConstraintAsList(ctx, "exclude_dirs", pp);
451 r.include_basedir = PromiseGetConstraintAsBoolean(ctx, "include_basedir", pp);
452 return r;
453 }
454
455 /*******************************************************************/
456
GetAclConstraints(const EvalContext * ctx,const Promise * pp)457 Acl GetAclConstraints(const EvalContext *ctx, const Promise *pp)
458 {
459 Acl ac;
460
461 ac.acl_method = AclMethodFromString(PromiseGetConstraintAsRval(pp, "acl_method", RVAL_TYPE_SCALAR));
462 ac.acl_type = AclTypeFromString(PromiseGetConstraintAsRval(pp, "acl_type", RVAL_TYPE_SCALAR));
463 ac.acl_default = AclDefaultFromString(PromiseGetConstraintAsRval(pp, "acl_default", RVAL_TYPE_SCALAR));
464 if (ac.acl_default == ACL_DEFAULT_NONE)
465 {
466 /* Deprecated attribute. */
467 ac.acl_default = AclDefaultFromString(PromiseGetConstraintAsRval(pp, "acl_directory_inherit", RVAL_TYPE_SCALAR));
468 }
469 ac.acl_entries = PromiseGetConstraintAsList(ctx, "aces", pp);
470 ac.acl_default_entries = PromiseGetConstraintAsList(ctx, "specify_default_aces", pp);
471 if (ac.acl_default_entries == NULL)
472 {
473 /* Deprecated attribute. */
474 ac.acl_default_entries = PromiseGetConstraintAsList(ctx, "specify_inherit_aces", pp);
475 }
476 ac.acl_inherit = AclInheritFromString(PromiseGetConstraintAsRval(pp, "acl_inherit", RVAL_TYPE_SCALAR));
477 return ac;
478 }
479
480 /*******************************************************************/
481
GetPermissionConstraints(const EvalContext * ctx,const Promise * pp)482 static FilePerms GetPermissionConstraints(const EvalContext *ctx, const Promise *pp)
483 {
484 FilePerms p;
485 char *value;
486 Rlist *list;
487
488 value = PromiseGetConstraintAsRval(pp, "mode", RVAL_TYPE_SCALAR);
489
490 p.plus = CF_SAMEMODE;
491 p.minus = CF_SAMEMODE;
492
493 if (!ParseModeString(value, &p.plus, &p.minus))
494 {
495 Log(LOG_LEVEL_ERR, "Problem validating a mode string");
496 PromiseRef(LOG_LEVEL_ERR, pp);
497 }
498
499 list = PromiseGetConstraintAsList(ctx, "bsdflags", pp);
500
501 p.plus_flags = 0;
502 p.minus_flags = 0;
503
504 if (list && (!ParseFlagString(list, &p.plus_flags, &p.minus_flags)))
505 {
506 Log(LOG_LEVEL_ERR, "Problem validating a BSD flag string");
507 PromiseRef(LOG_LEVEL_ERR, pp);
508 }
509
510 p.owners = Rlist2UidList((Rlist *) PromiseGetConstraintAsRval(pp, "owners", RVAL_TYPE_LIST), pp);
511 p.groups = Rlist2GidList((Rlist *) PromiseGetConstraintAsRval(pp, "groups", RVAL_TYPE_LIST), pp);
512
513 p.findertype = PromiseGetConstraintAsRval(pp, "findertype", RVAL_TYPE_SCALAR);
514 p.rxdirs = PromiseGetConstraintAsBoolean(ctx, "rxdirs", pp);
515
516 // The default should be true
517
518 if (!PromiseGetConstraintAsRval(pp, "rxdirs", RVAL_TYPE_SCALAR))
519 {
520 p.rxdirs = true;
521 }
522
523 return p;
524 }
525
526 /*******************************************************************/
527
GetSelectConstraints(const EvalContext * ctx,const Promise * pp)528 FileSelect GetSelectConstraints(const EvalContext *ctx, const Promise *pp)
529 {
530 FileSelect s;
531 char *value;
532 Rlist *rp;
533 mode_t plus, minus;
534 u_long fplus, fminus;
535 int entries = false;
536
537 s.name = (Rlist *) PromiseGetConstraintAsRval(pp, "leaf_name", RVAL_TYPE_LIST);
538 s.path = (Rlist *) PromiseGetConstraintAsRval(pp, "path_name", RVAL_TYPE_LIST);
539 s.filetypes = (Rlist *) PromiseGetConstraintAsRval(pp, "file_types", RVAL_TYPE_LIST);
540 s.issymlinkto = (Rlist *) PromiseGetConstraintAsRval(pp, "issymlinkto", RVAL_TYPE_LIST);
541
542 s.perms = PromiseGetConstraintAsList(ctx, "search_mode", pp);
543
544 for (rp = s.perms; rp != NULL; rp = rp->next)
545 {
546 plus = 0;
547 minus = 0;
548 value = RlistScalarValue(rp);
549
550 if (!ParseModeString(value, &plus, &minus))
551 {
552 Log(LOG_LEVEL_ERR, "Problem validating a mode string");
553 PromiseRef(LOG_LEVEL_ERR, pp);
554 }
555 }
556
557 s.bsdflags = PromiseGetConstraintAsList(ctx, "search_bsdflags", pp);
558
559 fplus = 0;
560 fminus = 0;
561
562 if (!ParseFlagString(s.bsdflags, &fplus, &fminus))
563 {
564 Log(LOG_LEVEL_ERR, "Problem validating a BSD flag string");
565 PromiseRef(LOG_LEVEL_ERR, pp);
566 }
567
568 if ((s.name) || (s.path) || (s.filetypes) || (s.issymlinkto) || (s.perms) || (s.bsdflags))
569 {
570 entries = true;
571 }
572
573 s.owners = (Rlist *) PromiseGetConstraintAsRval(pp, "search_owners", RVAL_TYPE_LIST);
574 s.groups = (Rlist *) PromiseGetConstraintAsRval(pp, "search_groups", RVAL_TYPE_LIST);
575
576 value = PromiseGetConstraintAsRval(pp, "search_size", RVAL_TYPE_SCALAR);
577 if (value)
578 {
579 entries++;
580 }
581
582 if (!IntegerRangeFromString(value, (long *) &s.min_size, (long *) &s.max_size))
583 {
584 PromiseRef(LOG_LEVEL_ERR, pp);
585 FatalError(ctx, "Could not make sense of integer range [%s]", value);
586 }
587
588 value = PromiseGetConstraintAsRval(pp, "ctime", RVAL_TYPE_SCALAR);
589 if (value)
590 {
591 entries++;
592 }
593
594 if (!IntegerRangeFromString(value, (long *) &s.min_ctime, (long *) &s.max_ctime))
595 {
596 PromiseRef(LOG_LEVEL_ERR, pp);
597 FatalError(ctx, "Could not make sense of integer range [%s]", value);
598 }
599
600 value = PromiseGetConstraintAsRval(pp, "atime", RVAL_TYPE_SCALAR);
601 if (value)
602 {
603 entries++;
604 }
605
606 if (!IntegerRangeFromString(value, (long *) &s.min_atime, (long *) &s.max_atime))
607 {
608 PromiseRef(LOG_LEVEL_ERR, pp);
609 FatalError(ctx, "Could not make sense of integer range [%s]", value);
610 }
611 value = PromiseGetConstraintAsRval(pp, "mtime", RVAL_TYPE_SCALAR);
612 if (value)
613 {
614 entries++;
615 }
616
617 if (!IntegerRangeFromString(value, (long *) &s.min_mtime, (long *) &s.max_mtime))
618 {
619 PromiseRef(LOG_LEVEL_ERR, pp);
620 FatalError(ctx, "Could not make sense of integer range [%s]", value);
621 }
622
623 s.exec_regex = PromiseGetConstraintAsRval(pp, "exec_regex", RVAL_TYPE_SCALAR);
624 s.exec_program = PromiseGetConstraintAsRval(pp, "exec_program", RVAL_TYPE_SCALAR);
625
626 if ((s.owners) || (s.min_size) || (s.exec_regex) || (s.exec_program))
627 {
628 entries = true;
629 }
630
631 if ((s.result = PromiseGetConstraintAsRval(pp, "file_result", RVAL_TYPE_SCALAR)) == NULL)
632 {
633 if (!entries)
634 {
635 Log(LOG_LEVEL_ERR, "file_select body missing its a file_result return value");
636 }
637 }
638
639 return s;
640 }
641
642 /*******************************************************************/
643
ActionAttributeLogLevelFromString(const char * log_level)644 LogLevel ActionAttributeLogLevelFromString(const char *log_level)
645 {
646 if (!log_level)
647 {
648 return LOG_LEVEL_ERR;
649 }
650
651 if (strcmp("inform", log_level) == 0)
652 {
653 return LOG_LEVEL_INFO;
654 }
655 else if (strcmp("verbose", log_level) == 0)
656 {
657 return LOG_LEVEL_VERBOSE;
658 }
659 else
660 {
661 return LOG_LEVEL_ERR;
662 }
663 }
664
GetTransactionConstraints(const EvalContext * ctx,const Promise * pp)665 TransactionContext GetTransactionConstraints(const EvalContext *ctx, const Promise *pp)
666 {
667 TransactionContext t;
668 char *value;
669
670 value = PromiseGetConstraintAsRval(pp, "action_policy", RVAL_TYPE_SCALAR);
671
672 if (value && ((strcmp(value, "warn") == 0) || (strcmp(value, "nop") == 0)))
673 {
674 t.action = cfa_warn;
675 }
676 else
677 {
678 t.action = cfa_fix; // default
679 }
680
681 t.background = PromiseGetConstraintAsBoolean(ctx, "background", pp);
682 t.ifelapsed = PromiseGetConstraintAsInt(ctx, "ifelapsed", pp);
683 t.expireafter = PromiseGetConstraintAsInt(ctx, "expireafter", pp);
684
685 /* Warn if promise locking was used with a promise that doesn't support it.
686 * XXX: EvalContextGetPass() takes 'EvalContext *' instead of 'const EvalContext *'*/
687 if ((strcmp("access", pp->parent_section->promise_type) == 0 ||
688 strcmp("classes", pp->parent_section->promise_type) == 0 ||
689 strcmp("defaults", pp->parent_section->promise_type) == 0 ||
690 strcmp("meta", pp->parent_section->promise_type) == 0 ||
691 strcmp("roles", pp->parent_section->promise_type) == 0 ||
692 strcmp("vars", pp->parent_section->promise_type) == 0))
693 {
694 if (t.ifelapsed != CF_NOINT)
695 {
696 Log(LOG_LEVEL_WARNING,
697 "ifelapsed attribute specified in action body for %s promise '%s',"
698 " but %s promises do not support promise locking",
699 pp->parent_section->promise_type, pp->promiser,
700 pp->parent_section->promise_type);
701 }
702 if (t.expireafter != CF_NOINT)
703 {
704 Log(LOG_LEVEL_WARNING,
705 "expireafter attribute specified in action body for %s promise '%s',"
706 " but %s promises do not support promise locking",
707 pp->parent_section->promise_type, pp->promiser,
708 pp->parent_section->promise_type);
709 }
710 }
711
712 if (t.ifelapsed == CF_NOINT)
713 {
714 t.ifelapsed = VIFELAPSED;
715 }
716
717 if (t.expireafter == CF_NOINT)
718 {
719 t.expireafter = VEXPIREAFTER;
720 }
721
722 t.audit = PromiseGetConstraintAsBoolean(ctx, "audit", pp);
723 t.log_string = PromiseGetConstraintAsRval(pp, "log_string", RVAL_TYPE_SCALAR);
724 t.log_priority = SyslogPriorityFromString(PromiseGetConstraintAsRval(pp, "log_priority", RVAL_TYPE_SCALAR));
725
726 t.log_kept = PromiseGetConstraintAsRval(pp, "log_kept", RVAL_TYPE_SCALAR);
727 t.log_repaired = PromiseGetConstraintAsRval(pp, "log_repaired", RVAL_TYPE_SCALAR);
728 t.log_failed = PromiseGetConstraintAsRval(pp, "log_failed", RVAL_TYPE_SCALAR);
729
730 value = PromiseGetConstraintAsRval(pp, "log_level", RVAL_TYPE_SCALAR);
731 t.log_level = ActionAttributeLogLevelFromString(value);
732
733 value = PromiseGetConstraintAsRval(pp, "report_level", RVAL_TYPE_SCALAR);
734 t.report_level = ActionAttributeLogLevelFromString(value);
735
736 t.measure_id = PromiseGetConstraintAsRval(pp, "measurement_class", RVAL_TYPE_SCALAR);
737
738 return t;
739 }
740
741 /*******************************************************************/
742
GetClassDefinitionConstraints(const EvalContext * ctx,const Promise * pp)743 DefineClasses GetClassDefinitionConstraints(const EvalContext *ctx, const Promise *pp)
744 {
745 DefineClasses c;
746 char *pt = NULL;
747
748 {
749 const char *context_scope = PromiseGetConstraintAsRval(pp, "scope", RVAL_TYPE_SCALAR);
750 c.scope = ContextScopeFromString(context_scope);
751 }
752 c.change = (Rlist *) PromiseGetConstraintAsList(ctx, "promise_repaired", pp);
753 c.failure = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_failed", pp);
754 c.denied = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_denied", pp);
755 c.timeout = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_timeout", pp);
756 c.kept = (Rlist *) PromiseGetConstraintAsList(ctx, "promise_kept", pp);
757
758 c.del_change = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_repaired", pp);
759 c.del_kept = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_kept", pp);
760 c.del_notkept = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_notkept", pp);
761
762 c.retcode_kept = (Rlist *) PromiseGetConstraintAsList(ctx, "kept_returncodes", pp);
763 c.retcode_repaired = (Rlist *) PromiseGetConstraintAsList(ctx, "repaired_returncodes", pp);
764 c.retcode_failed = (Rlist *) PromiseGetConstraintAsList(ctx, "failed_returncodes", pp);
765
766 c.persist = PromiseGetConstraintAsInt(ctx, "persist_time", pp);
767
768 if (c.persist == CF_NOINT)
769 {
770 c.persist = 0;
771 }
772
773 pt = PromiseGetConstraintAsRval(pp, "timer_policy", RVAL_TYPE_SCALAR);
774
775 if (pt && (strncmp(pt, "abs", 3) == 0))
776 {
777 c.timer = CONTEXT_STATE_POLICY_PRESERVE;
778 }
779 else
780 {
781 c.timer = CONTEXT_STATE_POLICY_RESET;
782 }
783
784 return c;
785 }
786
787 /*******************************************************************/
788
GetDeleteConstraints(const EvalContext * ctx,const Promise * pp)789 FileDelete GetDeleteConstraints(const EvalContext *ctx, const Promise *pp)
790 {
791 FileDelete f;
792 char *value;
793
794 value = PromiseGetConstraintAsRval(pp, "dirlinks", RVAL_TYPE_SCALAR);
795
796 if (value && (strcmp(value, "keep") == 0))
797 {
798 f.dirlinks = TIDY_LINK_KEEP;
799 }
800 else
801 {
802 f.dirlinks = TIDY_LINK_DELETE;
803 }
804
805 f.rmdirs = PromiseGetConstraintAsBoolean(ctx, "rmdirs", pp);
806 return f;
807 }
808
809 /*******************************************************************/
810
GetRenameConstraints(const EvalContext * ctx,const Promise * pp)811 FileRename GetRenameConstraints(const EvalContext *ctx, const Promise *pp)
812 {
813 FileRename r;
814 char *value;
815
816 value = PromiseGetConstraintAsRval(pp, "disable_mode", RVAL_TYPE_SCALAR);
817
818 if (!ParseModeString(value, &r.plus, &r.minus))
819 {
820 Log(LOG_LEVEL_ERR, "Problem validating a mode string");
821 PromiseRef(LOG_LEVEL_ERR, pp);
822 }
823
824 r.disable = PromiseGetConstraintAsBoolean(ctx, "disable", pp);
825 r.disable_suffix = PromiseGetConstraintAsRval(pp, "disable_suffix", RVAL_TYPE_SCALAR);
826 r.newname = PromiseGetConstraintAsRval(pp, "newname", RVAL_TYPE_SCALAR);
827 r.rotate = PromiseGetConstraintAsInt(ctx, "rotate", pp);
828
829 return r;
830 }
831
832 /*******************************************************************/
833
ENTERPRISE_FUNC_0ARG_DEFINE_STUB(HashMethod,GetBestFileChangeHashMethod)834 ENTERPRISE_FUNC_0ARG_DEFINE_STUB(HashMethod, GetBestFileChangeHashMethod)
835 {
836 return HASH_METHOD_BEST;
837 }
838
GetChangeMgtConstraints(const EvalContext * ctx,const Promise * pp)839 FileChange GetChangeMgtConstraints(const EvalContext *ctx, const Promise *pp)
840 {
841 FileChange c;
842 char *value;
843
844 value = PromiseGetConstraintAsRval(pp, "hash", RVAL_TYPE_SCALAR);
845
846 if (value && (strcmp(value, "best") == 0))
847 {
848 c.hash = GetBestFileChangeHashMethod();
849 }
850 else if (value && (strcmp(value, "md5") == 0))
851 {
852 c.hash = HASH_METHOD_MD5;
853 }
854 else if (value && (strcmp(value, "sha1") == 0))
855 {
856 c.hash = HASH_METHOD_SHA1;
857 }
858 else if (value && (strcmp(value, "sha256") == 0))
859 {
860 c.hash = HASH_METHOD_SHA256;
861 }
862 else if (value && (strcmp(value, "sha384") == 0))
863 {
864 c.hash = HASH_METHOD_SHA384;
865 }
866 else if (value && (strcmp(value, "sha512") == 0))
867 {
868 c.hash = HASH_METHOD_SHA512;
869 }
870 else
871 {
872 c.hash = CF_DEFAULT_DIGEST;
873 }
874
875 if (FIPS_MODE && (c.hash == HASH_METHOD_MD5))
876 {
877 Log(LOG_LEVEL_ERR, "FIPS mode is enabled, and md5 is not an approved algorithm");
878 PromiseRef(LOG_LEVEL_ERR, pp);
879 }
880
881 value = PromiseGetConstraintAsRval(pp, "report_changes", RVAL_TYPE_SCALAR);
882
883 if (value && (strcmp(value, "content") == 0))
884 {
885 c.report_changes = FILE_CHANGE_REPORT_CONTENT_CHANGE;
886 }
887 else if (value && (strcmp(value, "stats") == 0))
888 {
889 c.report_changes = FILE_CHANGE_REPORT_STATS_CHANGE;
890 }
891 else if (value && (strcmp(value, "all") == 0))
892 {
893 c.report_changes = FILE_CHANGE_REPORT_ALL;
894 }
895 else
896 {
897 c.report_changes = FILE_CHANGE_REPORT_NONE;
898 }
899
900 if (PromiseGetConstraintAsRval(pp, "update_hashes", RVAL_TYPE_SCALAR))
901 {
902 c.update = PromiseGetConstraintAsBoolean(ctx, "update_hashes", pp);
903 }
904 else
905 {
906 c.update = GetChecksumUpdatesDefault(ctx);
907 }
908
909 c.report_diffs = PromiseGetConstraintAsBoolean(ctx, "report_diffs", pp);
910 return c;
911 }
912
913 /*******************************************************************/
914
GetCopyConstraints(const EvalContext * ctx,const Promise * pp)915 FileCopy GetCopyConstraints(const EvalContext *ctx, const Promise *pp)
916 {
917 FileCopy f;
918 long min, max;
919 const char *value;
920
921 f.source = PromiseGetConstraintAsRval(pp, "source", RVAL_TYPE_SCALAR);
922 f.servers = PromiseGetConstraintAsList(ctx, "servers", pp);
923
924 value = PromiseGetConstraintAsRval(pp, "compare", RVAL_TYPE_SCALAR);
925 if (value == NULL)
926 {
927 value = DEFAULT_COPYTYPE;
928 }
929 f.compare = FileComparatorFromString(value);
930
931 value = PromiseGetConstraintAsRval(pp, "link_type", RVAL_TYPE_SCALAR);
932 f.link_type = FileLinkTypeFromString(value);
933
934 char *protocol_version = PromiseGetConstraintAsRval(pp, "protocol_version",
935 RVAL_TYPE_SCALAR);
936
937 /* Default is undefined, which leaves the choice to body common. */
938 f.protocol_version = CF_PROTOCOL_UNDEFINED;
939 if (protocol_version != NULL)
940 {
941 ProtocolVersion parsed = ParseProtocolVersionPolicy(protocol_version);
942 if (ProtocolIsKnown(parsed))
943 {
944 f.protocol_version = parsed;
945 }
946 }
947
948 f.port = PromiseGetConstraintAsRval(pp, "portnumber", RVAL_TYPE_SCALAR);
949 f.timeout = (short) PromiseGetConstraintAsInt(ctx, "timeout", pp);
950 f.link_instead = PromiseGetConstraintAsList(ctx, "linkcopy_patterns", pp);
951 f.copy_links = PromiseGetConstraintAsList(ctx, "copylink_patterns", pp);
952
953 value = PromiseGetConstraintAsRval(pp, "copy_backup", RVAL_TYPE_SCALAR);
954
955 if (value && (strcmp(value, "false") == 0))
956 {
957 f.backup = BACKUP_OPTION_NO_BACKUP;
958 }
959 else if (value && (strcmp(value, "timestamp") == 0))
960 {
961 f.backup = BACKUP_OPTION_TIMESTAMP;
962 }
963 else
964 {
965 f.backup = BACKUP_OPTION_BACKUP;
966 }
967
968 f.stealth = PromiseGetConstraintAsBoolean(ctx, "stealth", pp);
969 f.collapse = PromiseGetConstraintAsBoolean(ctx, "collapse_destination_dir", pp);
970 f.preserve = PromiseGetConstraintAsBoolean(ctx, "preserve", pp);
971 f.type_check = PromiseGetConstraintAsBoolean(ctx, "type_check", pp);
972 f.force_update = PromiseGetConstraintAsBoolean(ctx, "force_update", pp);
973 f.force_ipv4 = PromiseGetConstraintAsBoolean(ctx, "force_ipv4", pp);
974 f.check_root = PromiseGetConstraintAsBoolean(ctx, "check_root", pp);
975
976 value = PromiseGetConstraintAsRval(pp, "copy_size", RVAL_TYPE_SCALAR);
977 if (!IntegerRangeFromString(value, &min, &max))
978 {
979 PromiseRef(LOG_LEVEL_ERR, pp);
980 FatalError(ctx, "Could not make sense of integer range [%s]", value);
981 }
982
983 f.min_size = (size_t) min;
984 f.max_size = (size_t) max;
985
986 f.trustkey = PromiseGetConstraintAsBoolean(ctx, "trustkey", pp);
987 f.encrypt = PromiseGetConstraintAsBoolean(ctx, "encrypt", pp);
988 f.verify = PromiseGetConstraintAsBoolean(ctx, "verify", pp);
989 f.purge = PromiseGetConstraintAsBoolean(ctx, "purge", pp);
990 f.missing_ok = PromiseGetConstraintAsBoolean(ctx, "missing_ok", pp);
991 f.destination = NULL;
992
993 return f;
994 }
995
996 /*******************************************************************/
997
GetLinkConstraints(const EvalContext * ctx,const Promise * pp)998 FileLink GetLinkConstraints(const EvalContext *ctx, const Promise *pp)
999 {
1000 FileLink f;
1001 char *value;
1002
1003 f.source = PromiseGetConstraintAsRval(pp, "source", RVAL_TYPE_SCALAR);
1004 value = PromiseGetConstraintAsRval(pp, "link_type", RVAL_TYPE_SCALAR);
1005 f.link_type = FileLinkTypeFromString(value);
1006 f.copy_patterns = PromiseGetConstraintAsList(ctx, "copy_patterns", pp);
1007
1008 value = PromiseGetConstraintAsRval(pp, "when_no_source", RVAL_TYPE_SCALAR);
1009
1010 if (value && (strcmp(value, "force") == 0))
1011 {
1012 f.when_no_file = cfa_force;
1013 }
1014 else if (value && (strcmp(value, "delete") == 0))
1015 {
1016 f.when_no_file = cfa_delete;
1017 }
1018 else
1019 {
1020 f.when_no_file = cfa_skip;
1021 }
1022
1023 value = PromiseGetConstraintAsRval(pp, "when_linking_children", RVAL_TYPE_SCALAR);
1024
1025 if (value && (strcmp(value, "override_file") == 0))
1026 {
1027 f.when_linking_children = cfa_override;
1028 }
1029 else
1030 {
1031 f.when_linking_children = cfa_onlynonexisting;
1032 }
1033
1034 f.link_children = PromiseGetConstraintAsBoolean(ctx, "link_children", pp);
1035
1036 return f;
1037 }
1038
1039 /*******************************************************************/
1040
GetEditDefaults(const EvalContext * ctx,const Promise * pp)1041 EditDefaults GetEditDefaults(const EvalContext *ctx, const Promise *pp)
1042 {
1043 EditDefaults e = { 0 };
1044 char *value;
1045
1046 e.maxfilesize = PromiseGetConstraintAsInt(ctx, "max_file_size", pp);
1047
1048 if (e.maxfilesize == CF_NOINT)
1049 {
1050 e.maxfilesize = EDITFILESIZE;
1051 }
1052
1053 value = PromiseGetConstraintAsRval(pp, "edit_backup", RVAL_TYPE_SCALAR);
1054
1055 if (value && (strcmp(value, "false") == 0))
1056 {
1057 e.backup = BACKUP_OPTION_NO_BACKUP;
1058 }
1059 else if (value && (strcmp(value, "timestamp") == 0))
1060 {
1061 e.backup = BACKUP_OPTION_TIMESTAMP;
1062 }
1063 else if (value && (strcmp(value, "rotate") == 0))
1064 {
1065 e.backup = BACKUP_OPTION_ROTATE;
1066 e.rotate = PromiseGetConstraintAsInt(ctx, "rotate", pp);
1067 }
1068 else
1069 {
1070 e.backup = BACKUP_OPTION_BACKUP;
1071 }
1072
1073 e.empty_before_use = PromiseGetConstraintAsBoolean(ctx, "empty_file_before_editing", pp);
1074
1075 e.joinlines = PromiseGetConstraintAsBoolean(ctx, "recognize_join", pp);
1076
1077 e.inherit = PromiseGetConstraintAsBoolean(ctx, "inherit", pp);
1078
1079 return e;
1080 }
1081
1082 /*******************************************************************/
1083
GetContextConstraints(const EvalContext * ctx,const Promise * pp)1084 ContextConstraint GetContextConstraints(const EvalContext *ctx, const Promise *pp)
1085 {
1086 ContextConstraint a;
1087
1088 a.nconstraints = 0;
1089 a.expression = NULL;
1090 a.persistent = PromiseGetConstraintAsInt(ctx, "persistence", pp);
1091
1092 {
1093 const char *context_scope = PromiseGetConstraintAsRval(pp, "scope", RVAL_TYPE_SCALAR);
1094 a.scope = ContextScopeFromString(context_scope);
1095 }
1096
1097 for (size_t i = 0; i < SeqLength(pp->conlist); i++)
1098 {
1099 Constraint *cp = SeqAt(pp->conlist, i);
1100
1101 for (int k = 0; CF_CLASSBODY[k].lval != NULL; k++)
1102 {
1103 if (strcmp(cp->lval, "persistence") == 0 || strcmp(cp->lval, "scope") == 0)
1104 {
1105 continue;
1106 }
1107
1108 if (strcmp(cp->lval, CF_CLASSBODY[k].lval) == 0)
1109 {
1110 a.expression = cp;
1111 a.nconstraints++;
1112 }
1113 }
1114 }
1115
1116 return a;
1117 }
1118
1119 /*******************************************************************/
1120
GetPackageConstraints(const EvalContext * ctx,const Promise * pp)1121 Packages GetPackageConstraints(const EvalContext *ctx, const Promise *pp)
1122 {
1123 Packages p = {0};
1124
1125 bool has_package_method =
1126 PromiseBundleOrBodyConstraintExists(ctx, "package_method", pp);
1127 bool has_generic_package_method = false;
1128
1129 if (!has_package_method)
1130 {
1131 /* Check if we have generic package_method. */
1132 const Policy *policy = PolicyFromPromise(pp);
1133 Seq *bodies_and_args = EvalContextResolveBodyExpression(ctx, policy, "generic", "package_method");; // at position 0 we'll have the body, then its rval, then the same for each of its inherit_from parents
1134 if (bodies_and_args != NULL &&
1135 SeqLength(bodies_and_args) > 0)
1136 {
1137 const Body *bp = SeqAt(bodies_and_args, 0); // guaranteed to be non-NULL
1138 CopyBodyConstraintsToPromise((EvalContext*)ctx, (Promise*)pp, bp);
1139 has_generic_package_method = true;
1140 }
1141 SeqDestroy(bodies_and_args);
1142 }
1143
1144
1145 p.package_version = PromiseGetConstraintAsRval(pp, "package_version", RVAL_TYPE_SCALAR);
1146 p.package_architectures = PromiseGetConstraintAsList(ctx, "package_architectures", pp);
1147 p.package_select = PackageVersionComparatorFromString(PromiseGetConstraintAsRval(pp, "package_select", RVAL_TYPE_SCALAR));
1148 p.package_policy = PackageActionFromString(PromiseGetConstraintAsRval(pp, "package_policy", RVAL_TYPE_SCALAR));
1149
1150 if (p.package_version == NULL && p.package_architectures == NULL &&
1151 p.package_select == PACKAGE_VERSION_COMPARATOR_NONE &&
1152 p.package_policy == PACKAGE_ACTION_NONE)
1153 {
1154 p.is_empty = true;
1155 }
1156 else
1157 {
1158 p.is_empty = false;
1159 }
1160
1161 if (p.package_policy == PACKAGE_ACTION_NONE) // Default action => package add
1162 {
1163 p.package_policy = PACKAGE_ACTION_ADD;
1164 }
1165
1166 p.has_package_method = has_package_method | has_generic_package_method;
1167
1168 /* body package_method constraints */
1169 p.package_add_command = PromiseGetConstraintAsRval(pp, "package_add_command", RVAL_TYPE_SCALAR);
1170 p.package_arch_regex = PromiseGetConstraintAsRval(pp, "package_arch_regex", RVAL_TYPE_SCALAR);
1171 p.package_changes = PackageActionPolicyFromString(PromiseGetConstraintAsRval(pp, "package_changes", RVAL_TYPE_SCALAR));
1172 p.package_delete_command = PromiseGetConstraintAsRval(pp, "package_delete_command", RVAL_TYPE_SCALAR);
1173 p.package_delete_convention = PromiseGetConstraintAsRval(pp, "package_delete_convention", RVAL_TYPE_SCALAR);
1174 p.package_file_repositories = PromiseGetConstraintAsList(ctx, "package_file_repositories", pp);
1175 p.package_installed_regex = PromiseGetConstraintAsRval(pp, "package_installed_regex", RVAL_TYPE_SCALAR);
1176 p.package_default_arch_command = PromiseGetConstraintAsRval(pp, "package_default_arch_command", RVAL_TYPE_SCALAR);
1177 p.package_list_arch_regex = PromiseGetConstraintAsRval(pp, "package_list_arch_regex", RVAL_TYPE_SCALAR);
1178 p.package_list_command = PromiseGetConstraintAsRval(pp, "package_list_command", RVAL_TYPE_SCALAR);
1179 p.package_name_regex = PromiseGetConstraintAsRval(pp, "package_name_regex", RVAL_TYPE_SCALAR);
1180 p.package_list_update_command = PromiseGetConstraintAsRval(pp, "package_list_update_command", RVAL_TYPE_SCALAR);
1181 p.package_list_update_ifelapsed = PromiseGetConstraintAsInt(ctx, "package_list_update_ifelapsed", pp);
1182 p.package_list_version_regex = PromiseGetConstraintAsRval(pp, "package_list_version_regex", RVAL_TYPE_SCALAR);
1183 p.package_name_convention = PromiseGetConstraintAsRval(pp, "package_name_convention", RVAL_TYPE_SCALAR);
1184 p.package_patch_name_regex = PromiseGetConstraintAsRval(pp, "package_patch_name_regex", RVAL_TYPE_SCALAR);
1185 p.package_noverify_regex = PromiseGetConstraintAsRval(pp, "package_noverify_regex", RVAL_TYPE_SCALAR);
1186 p.package_noverify_returncode = PromiseGetConstraintAsInt(ctx, "package_noverify_returncode", pp);
1187 p.package_patch_arch_regex = PromiseGetConstraintAsRval(pp, "package_patch_arch_regex", RVAL_TYPE_SCALAR);
1188 p.package_patch_command = PromiseGetConstraintAsRval(pp, "package_patch_command", RVAL_TYPE_SCALAR);
1189 p.package_patch_installed_regex = PromiseGetConstraintAsRval(pp, "package_patch_installed_regex", RVAL_TYPE_SCALAR);
1190 p.package_patch_list_command = PromiseGetConstraintAsRval(pp, "package_patch_list_command", RVAL_TYPE_SCALAR);
1191 p.package_list_name_regex = PromiseGetConstraintAsRval(pp, "package_list_name_regex", RVAL_TYPE_SCALAR);
1192 p.package_patch_version_regex = PromiseGetConstraintAsRval(pp, "package_patch_version_regex", RVAL_TYPE_SCALAR);
1193 p.package_update_command = PromiseGetConstraintAsRval(pp, "package_update_command", RVAL_TYPE_SCALAR);
1194 p.package_verify_command = PromiseGetConstraintAsRval(pp, "package_verify_command", RVAL_TYPE_SCALAR);
1195 p.package_version_regex = PromiseGetConstraintAsRval(pp, "package_version_regex", RVAL_TYPE_SCALAR);
1196 p.package_multiline_start = PromiseGetConstraintAsRval(pp, "package_multiline_start", RVAL_TYPE_SCALAR);
1197 if (PromiseGetConstraint(pp, "package_commands_useshell") == NULL)
1198 {
1199 p.package_commands_useshell = true;
1200 }
1201 else
1202 {
1203 p.package_commands_useshell = PromiseGetConstraintAsBoolean(ctx, "package_commands_useshell", pp);
1204 }
1205 p.package_version_less_command = PromiseGetConstraintAsRval(pp, "package_version_less_command", RVAL_TYPE_SCALAR);
1206 p.package_version_equal_command = PromiseGetConstraintAsRval(pp, "package_version_equal_command", RVAL_TYPE_SCALAR);
1207
1208 return p;
1209 }
1210
1211 /*******************************************************************/
1212
1213 static const char *new_packages_actions[] =
1214 {
1215 "absent",
1216 "present",
1217 NULL
1218 };
1219
GetNewPackageConstraints(const EvalContext * ctx,const Promise * pp)1220 NewPackages GetNewPackageConstraints(const EvalContext *ctx, const Promise *pp)
1221 {
1222 NewPackages p = {0};
1223 NewPackages empty = {0};
1224
1225 p.package_version = PromiseGetConstraintAsRval(pp, "version", RVAL_TYPE_SCALAR);
1226 p.package_architecture = PromiseGetConstraintAsRval(pp, "architecture", RVAL_TYPE_SCALAR);
1227 p.package_options = PromiseGetConstraintAsList(ctx, "options", pp);
1228
1229 p.is_empty = (memcmp(&p, &empty, sizeof(NewPackages)) == 0);
1230 p.package_policy = GetNewPackagePolicy(PromiseGetConstraintAsRval(pp, "policy", RVAL_TYPE_SCALAR),
1231 new_packages_actions);
1232
1233 /* We can have only policy specified in new package promise definition. */
1234 if (p.package_policy != NEW_PACKAGE_ACTION_NONE)
1235 {
1236 p.is_empty = false;
1237 }
1238
1239 /* If we have promise package manager specified.
1240 * IMPORTANT: this must be done after is_empty flag is set as we can have
1241 * some default options for new package promise specified and still use
1242 * old promise inside policy. */
1243 char *local_promise_manager =
1244 PromiseGetConstraintAsRval(pp, "package_module_name", RVAL_TYPE_SCALAR);
1245 if (local_promise_manager)
1246 {
1247 p.module_body = GetPackageModuleFromContext(ctx, local_promise_manager);
1248 }
1249 else
1250 {
1251 p.module_body = GetDefaultPackageModuleFromContext(ctx);
1252 }
1253 p.package_inventory = GetDefaultInventoryFromContext(ctx);
1254
1255 /* If global options are not override by promise specific ones. */
1256 if (!p.package_options && p.module_body)
1257 {
1258 p.package_options = p.module_body->options;
1259 }
1260
1261 return p;
1262 }
1263
1264 /*******************************************************************/
1265
GetProcessFilterConstraints(const EvalContext * ctx,const Promise * pp)1266 ProcessSelect GetProcessFilterConstraints(const EvalContext *ctx, const Promise *pp)
1267 {
1268 ProcessSelect p;
1269 char *value;
1270 int entries = 0;
1271
1272 p.owner = PromiseGetConstraintAsList(ctx, "process_owner", pp);
1273
1274 value = PromiseGetConstraintAsRval(pp, "pid", RVAL_TYPE_SCALAR);
1275
1276 if (value)
1277 {
1278 entries++;
1279 }
1280
1281 if (!IntegerRangeFromString(value, &p.min_pid, &p.max_pid))
1282 {
1283 PromiseRef(LOG_LEVEL_ERR, pp);
1284 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1285 }
1286 value = PromiseGetConstraintAsRval(pp, "ppid", RVAL_TYPE_SCALAR);
1287
1288 if (value)
1289 {
1290 entries++;
1291 }
1292
1293 if (!IntegerRangeFromString(value, &p.min_ppid, &p.max_ppid))
1294 {
1295 PromiseRef(LOG_LEVEL_ERR, pp);
1296 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1297 }
1298 value = PromiseGetConstraintAsRval(pp, "pgid", RVAL_TYPE_SCALAR);
1299
1300 if (value)
1301 {
1302 entries++;
1303 }
1304
1305 if (!IntegerRangeFromString(value, &p.min_pgid, &p.max_pgid))
1306 {
1307 PromiseRef(LOG_LEVEL_ERR, pp);
1308 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1309 }
1310 value = PromiseGetConstraintAsRval(pp, "rsize", RVAL_TYPE_SCALAR);
1311
1312 if (value)
1313 {
1314 entries++;
1315 }
1316
1317 if (!IntegerRangeFromString(value, &p.min_rsize, &p.max_rsize))
1318 {
1319 PromiseRef(LOG_LEVEL_ERR, pp);
1320 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1321 }
1322 value = PromiseGetConstraintAsRval(pp, "vsize", RVAL_TYPE_SCALAR);
1323 if (value)
1324 {
1325 entries++;
1326 }
1327
1328 if (!IntegerRangeFromString(value, &p.min_vsize, &p.max_vsize))
1329 {
1330 PromiseRef(LOG_LEVEL_ERR, pp);
1331 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1332 }
1333 value = PromiseGetConstraintAsRval(pp, "ttime_range", RVAL_TYPE_SCALAR);
1334 if (value)
1335 {
1336 entries++;
1337 }
1338
1339 if (!IntegerRangeFromString(value, (long *) &p.min_ttime, (long *) &p.max_ttime))
1340 {
1341 PromiseRef(LOG_LEVEL_ERR, pp);
1342 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1343 }
1344 value = PromiseGetConstraintAsRval(pp, "stime_range", RVAL_TYPE_SCALAR);
1345 if (value)
1346 {
1347 entries++;
1348 }
1349
1350 if (!IntegerRangeFromString(value, (long *) &p.min_stime, (long *) &p.max_stime))
1351 {
1352 PromiseRef(LOG_LEVEL_ERR, pp);
1353 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1354 }
1355
1356 p.status = PromiseGetConstraintAsRval(pp, "status", RVAL_TYPE_SCALAR);
1357 p.command = PromiseGetConstraintAsRval(pp, "command", RVAL_TYPE_SCALAR);
1358 p.tty = PromiseGetConstraintAsRval(pp, "tty", RVAL_TYPE_SCALAR);
1359
1360 value = PromiseGetConstraintAsRval(pp, "priority", RVAL_TYPE_SCALAR);
1361 if (value)
1362 {
1363 entries++;
1364 }
1365
1366 if (!IntegerRangeFromString(value, &p.min_pri, &p.max_pri))
1367 {
1368 PromiseRef(LOG_LEVEL_ERR, pp);
1369 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1370 }
1371 value = PromiseGetConstraintAsRval(pp, "threads", RVAL_TYPE_SCALAR);
1372 if (value)
1373 {
1374 entries++;
1375 }
1376
1377 if (!IntegerRangeFromString(value, &p.min_thread, &p.max_thread))
1378 {
1379 PromiseRef(LOG_LEVEL_ERR, pp);
1380 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1381 }
1382
1383 if ((p.owner) || (p.status) || (p.command) || (p.tty))
1384 {
1385 entries = true;
1386 }
1387
1388 if ((p.process_result = PromiseGetConstraintAsRval(pp, "process_result", RVAL_TYPE_SCALAR)) == NULL)
1389 {
1390 if (entries)
1391 {
1392 Log(LOG_LEVEL_ERR, "process_select body missing its a process_result return value");
1393 }
1394 }
1395
1396 return p;
1397 }
1398
1399 /*******************************************************************/
1400
GetMatchesConstraints(const EvalContext * ctx,const Promise * pp)1401 ProcessCount GetMatchesConstraints(const EvalContext *ctx, const Promise *pp)
1402 {
1403 ProcessCount p;
1404 char *value;
1405
1406 value = PromiseGetConstraintAsRval(pp, "match_range", RVAL_TYPE_SCALAR);
1407 if (!IntegerRangeFromString(value, &p.min_range, &p.max_range))
1408 {
1409 PromiseRef(LOG_LEVEL_ERR, pp);
1410 FatalError(ctx, "Could not make sense of integer range [%s]", value);
1411 }
1412 p.in_range_define = PromiseGetConstraintAsList(ctx, "in_range_define", pp);
1413 p.out_of_range_define = PromiseGetConstraintAsList(ctx, "out_of_range_define", pp);
1414
1415 return p;
1416 }
1417
GetInsertionAttributes(const EvalContext * ctx,const Promise * pp)1418 Attributes GetInsertionAttributes(const EvalContext *ctx, const Promise *pp)
1419 {
1420 Attributes attr = ZeroAttributes;
1421
1422 attr.havelocation = PromiseGetConstraintAsBoolean(ctx, "location", pp);
1423 attr.location = GetLocationAttributes(pp);
1424
1425 attr.sourcetype = PromiseGetConstraintAsRval(pp, "insert_type", RVAL_TYPE_SCALAR);
1426 attr.expandvars = PromiseGetConstraintAsBoolean(ctx, "expand_scalars", pp);
1427
1428 attr.haveinsertselect = PromiseGetConstraintAsBoolean(ctx, "insert_select", pp);
1429 attr.line_select = GetInsertSelectConstraints(ctx, pp);
1430
1431 attr.insert_match = PromiseGetConstraintAsList(ctx, "whitespace_policy", pp);
1432
1433 /* Common ("included") */
1434
1435 attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp);
1436 attr.region = GetRegionConstraints(ctx, pp);
1437
1438 attr.xml = GetXmlConstraints(pp);
1439
1440 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
1441 attr.transaction = GetTransactionConstraints(ctx, pp);
1442
1443 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
1444 attr.classes = GetClassDefinitionConstraints(ctx, pp);
1445
1446 return attr;
1447 }
1448
1449 /*******************************************************************/
1450
GetLocationAttributes(const Promise * pp)1451 EditLocation GetLocationAttributes(const Promise *pp)
1452 {
1453 EditLocation e;
1454 char *value;
1455
1456 e.line_matching = PromiseGetConstraintAsRval(pp, "select_line_matching", RVAL_TYPE_SCALAR);
1457
1458 value = PromiseGetConstraintAsRval(pp, "before_after", RVAL_TYPE_SCALAR);
1459
1460 if (value && (strcmp(value, "before") == 0))
1461 {
1462 e.before_after = EDIT_ORDER_BEFORE;
1463 }
1464 else
1465 {
1466 e.before_after = EDIT_ORDER_AFTER;
1467 }
1468
1469 e.first_last = PromiseGetConstraintAsRval(pp, "first_last", RVAL_TYPE_SCALAR);
1470 return e;
1471 }
1472
1473 /*******************************************************************/
1474
GetDeletionAttributes(const EvalContext * ctx,const Promise * pp)1475 Attributes GetDeletionAttributes(const EvalContext *ctx, const Promise *pp)
1476 {
1477 Attributes attr = ZeroAttributes;
1478
1479 attr.not_matching = PromiseGetConstraintAsBoolean(ctx, "not_matching", pp);
1480
1481 attr.havedeleteselect = PromiseGetConstraintAsBoolean(ctx, "delete_select", pp);
1482 attr.line_select = GetDeleteSelectConstraints(ctx, pp);
1483
1484 /* common */
1485
1486 attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp);
1487 attr.region = GetRegionConstraints(ctx, pp);
1488
1489 attr.xml = GetXmlConstraints(pp);
1490
1491 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
1492 attr.transaction = GetTransactionConstraints(ctx, pp);
1493
1494 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
1495 attr.classes = GetClassDefinitionConstraints(ctx, pp);
1496
1497 return attr;
1498 }
1499
1500 /*******************************************************************/
1501
GetColumnAttributes(const EvalContext * ctx,const Promise * pp)1502 Attributes GetColumnAttributes(const EvalContext *ctx, const Promise *pp)
1503 {
1504 Attributes attr = ZeroAttributes;
1505
1506 attr.havecolumn = PromiseGetConstraintAsBoolean(ctx, "edit_field", pp);
1507 attr.column = GetColumnConstraints(ctx, pp);
1508
1509 /* common */
1510
1511 attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp);
1512 attr.region = GetRegionConstraints(ctx, pp);
1513
1514 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
1515 attr.transaction = GetTransactionConstraints(ctx, pp);
1516
1517 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
1518 attr.classes = GetClassDefinitionConstraints(ctx, pp);
1519
1520 return attr;
1521 }
1522
1523 /*******************************************************************/
1524
GetReplaceAttributes(const EvalContext * ctx,const Promise * pp)1525 Attributes GetReplaceAttributes(const EvalContext *ctx, const Promise *pp)
1526 {
1527 Attributes attr = ZeroAttributes;
1528
1529 attr.havereplace = PromiseGetConstraintAsBoolean(ctx, "replace_patterns", pp);
1530 attr.replace = GetReplaceConstraints(pp);
1531
1532 attr.havecolumn = PromiseGetConstraintAsBoolean(ctx, "replace_with", pp);
1533
1534 /* common */
1535
1536 attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp);
1537 attr.region = GetRegionConstraints(ctx, pp);
1538
1539 attr.xml = GetXmlConstraints(pp);
1540
1541 attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp);
1542 attr.transaction = GetTransactionConstraints(ctx, pp);
1543
1544 attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp);
1545 attr.classes = GetClassDefinitionConstraints(ctx, pp);
1546
1547 return attr;
1548 }
1549
1550 /*******************************************************************/
1551
GetXmlConstraints(const Promise * pp)1552 EditXml GetXmlConstraints(const Promise *pp)
1553 {
1554 EditXml x;
1555
1556 x.havebuildxpath = ((x.build_xpath = PromiseGetConstraintAsRval(pp, "build_xpath", RVAL_TYPE_SCALAR)) != NULL);
1557 x.haveselectxpath = ((x.select_xpath = PromiseGetConstraintAsRval(pp, "select_xpath", RVAL_TYPE_SCALAR)) != NULL);
1558 x.haveattributevalue = ((x.attribute_value = PromiseGetConstraintAsRval(pp, "attribute_value", RVAL_TYPE_SCALAR)) != NULL);
1559
1560 return x;
1561 }
1562
1563 /*******************************************************************/
1564
GetRegionConstraints(const EvalContext * ctx,const Promise * pp)1565 EditRegion GetRegionConstraints(const EvalContext *ctx, const Promise *pp)
1566 {
1567 EditRegion e;
1568
1569 e.select_start = PromiseGetConstraintAsRval(pp, "select_start", RVAL_TYPE_SCALAR);
1570 e.select_end = PromiseGetConstraintAsRval(pp, "select_end", RVAL_TYPE_SCALAR);
1571 e.include_start = PromiseGetConstraintAsBoolean(ctx, "include_start_delimiter", pp);
1572 e.include_end = PromiseGetConstraintAsBoolean(ctx, "include_end_delimiter", pp);
1573
1574 // set the value based on body agent control
1575 char *local_select_end = PromiseGetConstraintAsRval(pp, "select_end_match_eof", RVAL_TYPE_SCALAR);
1576 if (local_select_end != NULL)
1577 {
1578 if (strcmp(local_select_end, "true") == 0)
1579 {
1580 e.select_end_match_eof = true;
1581 }
1582 else
1583 {
1584 e.select_end_match_eof = false;
1585 }
1586 }
1587 else
1588 {
1589 e.select_end_match_eof = EvalContextGetSelectEndMatchEof(ctx);
1590 }
1591 return e;
1592 }
1593
1594 /*******************************************************************/
1595
GetReplaceConstraints(const Promise * pp)1596 EditReplace GetReplaceConstraints(const Promise *pp)
1597 {
1598 EditReplace r;
1599
1600 r.replace_value = PromiseGetConstraintAsRval(pp, "replace_value", RVAL_TYPE_SCALAR);
1601 r.occurrences = PromiseGetConstraintAsRval(pp, "occurrences", RVAL_TYPE_SCALAR);
1602
1603 return r;
1604 }
1605
1606 /*******************************************************************/
1607
GetColumnConstraints(const EvalContext * ctx,const Promise * pp)1608 EditColumn GetColumnConstraints(const EvalContext *ctx, const Promise *pp)
1609 {
1610 EditColumn c;
1611 char *value;
1612
1613 c.column_separator = PromiseGetConstraintAsRval(pp, "field_separator", RVAL_TYPE_SCALAR);
1614 c.select_column = PromiseGetConstraintAsInt(ctx, "select_field", pp);
1615
1616 if (((c.select_column) != CF_NOINT) && (PromiseGetConstraintAsBoolean(ctx, "start_fields_from_zero", pp)))
1617 {
1618 c.select_column++;
1619 }
1620
1621 value = PromiseGetConstraintAsRval(pp, "value_separator", RVAL_TYPE_SCALAR);
1622
1623 if (value)
1624 {
1625 c.value_separator = *value;
1626 }
1627 else
1628 {
1629 c.value_separator = '\0';
1630 }
1631
1632 c.column_value = PromiseGetConstraintAsRval(pp, "field_value", RVAL_TYPE_SCALAR);
1633 c.column_operation = PromiseGetConstraintAsRval(pp, "field_operation", RVAL_TYPE_SCALAR);
1634 c.extend_columns = PromiseGetConstraintAsBoolean(ctx, "extend_fields", pp);
1635 c.blanks_ok = PromiseGetConstraintAsBoolean(ctx, "allow_blank_fields", pp);
1636 return c;
1637 }
1638
1639 /*******************************************************************/
1640 /* Storage */
1641 /*******************************************************************/
1642
GetMountConstraints(const EvalContext * ctx,const Promise * pp)1643 StorageMount GetMountConstraints(const EvalContext *ctx, const Promise *pp)
1644 {
1645 StorageMount m;
1646
1647 m.mount_type = PromiseGetConstraintAsRval(pp, "mount_type", RVAL_TYPE_SCALAR);
1648 m.mount_source = PromiseGetConstraintAsRval(pp, "mount_source", RVAL_TYPE_SCALAR);
1649 m.mount_server = PromiseGetConstraintAsRval(pp, "mount_server", RVAL_TYPE_SCALAR);
1650 m.mount_options = PromiseGetConstraintAsList(ctx, "mount_options", pp);
1651 m.editfstab = PromiseGetConstraintAsBoolean(ctx, "edit_fstab", pp);
1652 m.unmount = PromiseGetConstraintAsBoolean(ctx, "unmount", pp);
1653
1654 return m;
1655 }
1656
1657 /*******************************************************************/
1658
GetVolumeConstraints(const EvalContext * ctx,const Promise * pp)1659 StorageVolume GetVolumeConstraints(const EvalContext *ctx, const Promise *pp)
1660 {
1661 StorageVolume v;
1662 char *value;
1663
1664 v.check_foreign = PromiseGetConstraintAsBoolean(ctx, "check_foreign", pp);
1665 value = PromiseGetConstraintAsRval(pp, "freespace", RVAL_TYPE_SCALAR);
1666
1667 v.freespace = (long) IntFromString(value);
1668 value = PromiseGetConstraintAsRval(pp, "sensible_size", RVAL_TYPE_SCALAR);
1669 v.sensible_size = (int) IntFromString(value);
1670 value = PromiseGetConstraintAsRval(pp, "sensible_count", RVAL_TYPE_SCALAR);
1671 v.sensible_count = (int) IntFromString(value);
1672 v.scan_arrivals = PromiseGetConstraintAsBoolean(ctx, "scan_arrivals", pp);
1673
1674 // defaults
1675 if (v.sensible_size == CF_NOINT)
1676 {
1677 v.sensible_size = 1000;
1678 }
1679
1680 if (v.sensible_count == CF_NOINT)
1681 {
1682 v.sensible_count = 2;
1683 }
1684
1685 return v;
1686 }
1687
GetReportConstraints(const EvalContext * ctx,const Promise * pp)1688 Report GetReportConstraints(const EvalContext *ctx, const Promise *pp)
1689 {
1690 Report r = {0};
1691
1692 r.result = PromiseGetConstraintAsRval(pp, "bundle_return_value_index", RVAL_TYPE_SCALAR);
1693
1694 if (PromiseGetConstraintAsRval(pp, "lastseen", RVAL_TYPE_SCALAR))
1695 {
1696 r.havelastseen = true;
1697 r.lastseen = PromiseGetConstraintAsInt(ctx, "lastseen", pp);
1698
1699 if (r.lastseen == CF_NOINT)
1700 {
1701 r.lastseen = 0;
1702 }
1703 }
1704 else
1705 {
1706 r.havelastseen = false;
1707 r.lastseen = 0;
1708 }
1709
1710 if (!PromiseGetConstraintAsReal(ctx, "intermittency", pp, &r.intermittency))
1711 {
1712 r.intermittency = 0;
1713 }
1714
1715 r.haveprintfile = PromiseGetConstraintAsBoolean(ctx, "printfile", pp);
1716 r.filename = PromiseGetConstraintAsRval(pp, "file_to_print", RVAL_TYPE_SCALAR);
1717 r.numlines = PromiseGetConstraintAsInt(ctx, "number_of_lines", pp);
1718
1719 if (r.numlines == CF_NOINT)
1720 {
1721 r.numlines = 5;
1722 }
1723
1724 r.showstate = PromiseGetConstraintAsList(ctx, "showstate", pp);
1725
1726 r.friend_pattern = PromiseGetConstraintAsRval(pp, "friend_pattern", RVAL_TYPE_SCALAR);
1727
1728 r.to_file = PromiseGetConstraintAsRval(pp, "report_to_file", RVAL_TYPE_SCALAR);
1729
1730 if ((r.result) && ((r.haveprintfile) || (r.filename) || (r.showstate) || (r.to_file) || (r.lastseen)))
1731 {
1732 Log(LOG_LEVEL_ERR, "bundle_return_value promise for '%s' in bundle '%s' with too many constraints (ignored)", pp->promiser, PromiseGetBundle(pp)->name);
1733 }
1734
1735 return r;
1736 }
1737
1738 /*******************************************************************/
1739
GetInsertSelectConstraints(const EvalContext * ctx,const Promise * pp)1740 LineSelect GetInsertSelectConstraints(const EvalContext *ctx, const Promise *pp)
1741 {
1742 LineSelect s;
1743
1744 s.startwith_from_list = PromiseGetConstraintAsList(ctx, "insert_if_startwith_from_list", pp);
1745 s.not_startwith_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_startwith_from_list", pp);
1746 s.match_from_list = PromiseGetConstraintAsList(ctx, "insert_if_match_from_list", pp);
1747 s.not_match_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_match_from_list", pp);
1748 s.contains_from_list = PromiseGetConstraintAsList(ctx, "insert_if_contains_from_list", pp);
1749 s.not_contains_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_contains_from_list", pp);
1750
1751 return s;
1752 }
1753
1754 /*******************************************************************/
1755
GetDeleteSelectConstraints(const EvalContext * ctx,const Promise * pp)1756 LineSelect GetDeleteSelectConstraints(const EvalContext *ctx, const Promise *pp)
1757 {
1758 LineSelect s;
1759
1760 s.startwith_from_list = PromiseGetConstraintAsList(ctx, "delete_if_startwith_from_list", pp);
1761 s.not_startwith_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_startwith_from_list", pp);
1762 s.match_from_list = PromiseGetConstraintAsList(ctx, "delete_if_match_from_list", pp);
1763 s.not_match_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_match_from_list", pp);
1764 s.contains_from_list = PromiseGetConstraintAsList(ctx, "delete_if_contains_from_list", pp);
1765 s.not_contains_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_contains_from_list", pp);
1766
1767 return s;
1768 }
1769
1770 /*******************************************************************/
1771
GetMeasurementConstraint(const EvalContext * ctx,const Promise * pp)1772 Measurement GetMeasurementConstraint(const EvalContext *ctx, const Promise *pp)
1773 {
1774 Measurement m;
1775 char *value;
1776
1777 m.stream_type = PromiseGetConstraintAsRval(pp, "stream_type", RVAL_TYPE_SCALAR);
1778
1779 value = PromiseGetConstraintAsRval(pp, "data_type", RVAL_TYPE_SCALAR);
1780 m.data_type = DataTypeFromString(value);
1781
1782 if (m.data_type == CF_DATA_TYPE_NONE)
1783 {
1784 m.data_type = CF_DATA_TYPE_STRING;
1785 }
1786
1787 m.history_type = PromiseGetConstraintAsRval(pp, "history_type", RVAL_TYPE_SCALAR);
1788 m.select_line_matching = PromiseGetConstraintAsRval(pp, "select_line_matching", RVAL_TYPE_SCALAR);
1789 m.select_line_number = PromiseGetConstraintAsInt(ctx, "select_line_number", pp);
1790 m.policy = MeasurePolicyFromString(PromiseGetConstraintAsRval(pp, "select_multiline_policy", RVAL_TYPE_SCALAR));
1791
1792 m.extraction_regex = PromiseGetConstraintAsRval(pp, "extraction_regex", RVAL_TYPE_SCALAR);
1793 m.units = PromiseGetConstraintAsRval(pp, "units", RVAL_TYPE_SCALAR);
1794 m.growing = PromiseGetConstraintAsBoolean(ctx, "track_growing_file", pp);
1795 return m;
1796 }
1797
1798 /*******************************************************************/
1799
GetDatabaseConstraints(const EvalContext * ctx,const Promise * pp)1800 Database GetDatabaseConstraints(const EvalContext *ctx, const Promise *pp)
1801 {
1802 Database d;
1803 char *value;
1804
1805 d.db_server_owner = PromiseGetConstraintAsRval(pp, "db_server_owner", RVAL_TYPE_SCALAR);
1806 d.db_server_password = PromiseGetConstraintAsRval(pp, "db_server_password", RVAL_TYPE_SCALAR);
1807 d.db_server_host = PromiseGetConstraintAsRval(pp, "db_server_host", RVAL_TYPE_SCALAR);
1808 d.db_connect_db = PromiseGetConstraintAsRval(pp, "db_server_connection_db", RVAL_TYPE_SCALAR);
1809 d.type = PromiseGetConstraintAsRval(pp, "database_type", RVAL_TYPE_SCALAR);
1810 d.server = PromiseGetConstraintAsRval(pp, "database_server", RVAL_TYPE_SCALAR);
1811 d.columns = PromiseGetConstraintAsList(ctx, "database_columns", pp);
1812 d.rows = PromiseGetConstraintAsList(ctx, "database_rows", pp);
1813 d.operation = PromiseGetConstraintAsRval(pp, "database_operation", RVAL_TYPE_SCALAR);
1814 d.exclude = PromiseGetConstraintAsList(ctx, "registry_exclude", pp);
1815
1816 value = PromiseGetConstraintAsRval(pp, "db_server_type", RVAL_TYPE_SCALAR);
1817 d.db_server_type = DatabaseTypeFromString(value);
1818
1819 if (value && ((d.db_server_type) == DATABASE_TYPE_NONE))
1820 {
1821 Log(LOG_LEVEL_ERR, "Unsupported database type '%s' in databases promise", value);
1822 PromiseRef(LOG_LEVEL_ERR, pp);
1823 }
1824
1825 return d;
1826 }
1827