1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /* auditd smf(5)/libscf(3LIB) interface - set and display audit parameters */
26 #include <audit_scf.h>
27 #include <audit_policy.h>
28
29 /* propvec array must be NULL terminated */
30 scf_propvec_t prop_vect[MAX_PROPVECS + 1];
31
32 /*
33 * prt_error() - prt_error_va() wrapper; see prt_error_va() for more contextual
34 * information. Note, that the function disregards errno; if you need to print
35 * out strerror()/errno use directly prt_error_va().
36 * Inputs - program error format and message.
37 */
38 /*PRINTFLIKE1*/
39 static void
prt_error(char * fmt,...)40 prt_error(char *fmt, ...)
41 {
42 va_list args;
43
44 errno = 0;
45
46 va_start(args, fmt);
47 prt_error_va(fmt, args);
48 va_end(args);
49 }
50
51 /*
52 * prt_error_va() - prints an error message along with corresponding system
53 * error number. Inputs - program error format and the va_list already prepared
54 * by the preceding functions.
55 *
56 */
57 /*PRINTFLIKE1*/
58 void
prt_error_va(char * fmt,va_list args)59 prt_error_va(char *fmt, va_list args)
60 {
61 (void) vfprintf(stderr, fmt, args);
62 (void) fputc('\n', stderr);
63 if (errno)
64 (void) fprintf(stderr, "error: %s(%d)\n",
65 strerror(errno), errno);
66 (void) fflush(stderr);
67 }
68
69 /*
70 * prt_scf_err() - scf_error()/scf_strerror() wrapper.
71 */
72 static void
prt_scf_err(void)73 prt_scf_err(void)
74 {
75 (void) fprintf(stderr, "error: %s\n", scf_strerror(scf_error()));
76 }
77
78 /*
79 * add_prop_vect_scf() - adds vector to the array of vectors later passed to
80 * get_/set_val_scf(). The first argument (vector) points to particular position
81 * in the vector of properties.
82 */
83 static void
add_prop_vect_scf(scf_propvec_t * vector,const char * prop_str,scf_type_t prop_type,void * prop_val_ptr)84 add_prop_vect_scf(scf_propvec_t *vector, const char *prop_str,
85 scf_type_t prop_type, void *prop_val_ptr)
86 {
87 vector->pv_prop = prop_str;
88 vector->pv_type = prop_type;
89 vector->pv_ptr = prop_val_ptr;
90 }
91
92 /*
93 * get_val_scf() - get a property values from the audit service
94 *
95 * Arguments: vector = pointers to the head end of array of property vectors
96 * pgroup_str = property group of property in AUDITD_FMRI
97 *
98 */
99 static boolean_t
get_val_scf(scf_propvec_t * vector,char * pgroup_str)100 get_val_scf(scf_propvec_t *vector, char *pgroup_str)
101 {
102 scf_propvec_t *bad_prop_vec = NULL;
103
104 /*
105 * Get the property vector from the editing snapshot (B_FALSE).
106 * For documentation on property vectors see <libscf_priv.h>.
107 */
108 if (scf_read_propvec(AUDITD_FMRI, pgroup_str, B_FALSE, vector,
109 &bad_prop_vec) != SCF_SUCCESS) {
110 prt_scf_err();
111 if (bad_prop_vec != NULL) {
112 prt_error(gettext("Reading the %s property in the %s "
113 "property group failed.\n"), bad_prop_vec->pv_prop,
114 pgroup_str);
115 }
116 return (B_FALSE);
117 }
118
119 return (B_TRUE);
120 }
121
122 /*
123 * set_val_scf() - set property values of the audit service.
124 *
125 * arguments: vector = pointers to the head end of array of property vectors
126 * pgroup_str = property group of property in AUDITD_FMRI
127 *
128 */
129 static boolean_t
set_val_scf(scf_propvec_t * vector,char * pgroup_str)130 set_val_scf(scf_propvec_t *vector, char *pgroup_str)
131 {
132 scf_propvec_t *bad_prop_vec = NULL;
133
134 /* for documentation on property vectors see <libscf_priv.h> */
135 if (scf_write_propvec(AUDITD_FMRI, pgroup_str, vector,
136 &bad_prop_vec) != SCF_SUCCESS) {
137 prt_scf_err();
138 if (bad_prop_vec != NULL) {
139 prt_error(gettext("Setting the %s property in the %s "
140 "property group failed.\n"), bad_prop_vec->pv_prop,
141 pgroup_str);
142 }
143 return (B_FALSE);
144 }
145
146 return (B_TRUE);
147 }
148
149 /*
150 * free_prop_vect() - deallocate heap memory used for propvect values.
151 */
152 static void
free_prop_vect(void)153 free_prop_vect(void)
154 {
155 scf_propvec_t *prop_vect_ptr;
156
157 prop_vect_ptr = prop_vect;
158
159 while (prop_vect_ptr->pv_prop != NULL) {
160 if (stack_inbounds(prop_vect_ptr->pv_ptr) == 0) {
161 free(prop_vect_ptr->pv_ptr);
162 }
163 prop_vect_ptr++;
164 }
165 }
166
167 /*
168 * chk_prop_vect() - check for prop_vect boundaries and possibly process
169 * (typically) full prop_vect.
170 */
171 static boolean_t
chk_prop_vect(scf_propvec_t ** prop_vect_ptr,char * pgrp_str)172 chk_prop_vect(scf_propvec_t **prop_vect_ptr, char *pgrp_str)
173 {
174 if (*prop_vect_ptr < prop_vect ||
175 *prop_vect_ptr >= (prop_vect + MAX_PROPVECS)) {
176 DPRINT((dbfp, "prop_vect is full; flushing\n"));
177 if (!set_val_scf(prop_vect, pgrp_str)) {
178 return (B_FALSE);
179 }
180 free_prop_vect();
181 bzero(prop_vect, sizeof (prop_vect));
182 *prop_vect_ptr = prop_vect;
183 }
184 return (B_TRUE);
185 }
186
187 /*
188 * get_props_kva_all() - get all properties and fill in the plugin_kva.
189 */
190 static boolean_t
get_props_kva_all(asi_scfhandle_t * handle,asi_scfhandle_iter_t * handle_iter,kva_t ** plugin_kva)191 get_props_kva_all(asi_scfhandle_t *handle, asi_scfhandle_iter_t *handle_iter,
192 kva_t **plugin_kva)
193 {
194 char key_buf[PLUGIN_MAXKEY];
195 char val_buf[PLUGIN_MAXVAL];
196 char attr_string[PLUGIN_MAXATT];
197 char attr_buf[PLUGIN_MAXATT];
198 int len = 0;
199 scf_type_t prop_type;
200
201 attr_string[0] = 0;
202 attr_buf[0] = 0;
203
204 while (scf_iter_next_property(handle_iter->prop, handle->prop) == 1) {
205 if (scf_property_get_name(handle->prop, key_buf,
206 PLUGIN_MAXKEY) == -1) {
207 prt_scf_err();
208 return (B_FALSE);
209 }
210
211 /*
212 * We do not fully support multi-valued properties.
213 * scf_property_get_value() only supports single-valued
214 * properties. It returns SCF_ERROR_CONSTRAINT_VIOLATED and one
215 * of the property values. The audit service configuration
216 * values are all single-valued properties. The authorizations
217 * to configure and read the audit service properties may be
218 * multi-valued, these may safely be ignored here as not an
219 * error.
220 */
221 if (scf_property_get_value(handle->prop,
222 handle_iter->prop_val) != 0 &&
223 scf_error() != SCF_ERROR_CONSTRAINT_VIOLATED) {
224 prt_scf_err();
225 return (B_FALSE);
226 }
227 if (scf_property_type(handle->prop, &prop_type) == -1) {
228 prt_scf_err();
229 return (B_FALSE);
230 }
231 switch (prop_type) {
232 case SCF_TYPE_BOOLEAN: {
233 uint8_t pval_bool;
234 if (scf_value_get_boolean(handle_iter->prop_val,
235 &pval_bool) == -1) {
236 prt_scf_err();
237 return (B_FALSE);
238 }
239 len = snprintf(attr_buf, PLUGIN_MAXATT, "%s=%d;",
240 key_buf, pval_bool);
241 if (len < 0 || len >= PLUGIN_MAXATT) {
242 prt_error(gettext("Too long attribute: %s\n"),
243 key_buf);
244 return (B_FALSE);
245 }
246 if (strlcat(attr_string, attr_buf, PLUGIN_MAXATT) >=
247 PLUGIN_MAXATT) {
248 prt_error(gettext("Too long attribute string: "
249 "%s\n"), key_buf);
250 return (B_FALSE);
251 }
252 break;
253 }
254 case SCF_TYPE_ASTRING: {
255 if (scf_value_get_as_string(handle_iter->prop_val,
256 val_buf, PLUGIN_MAXATT) == -1) {
257 prt_scf_err();
258 return (B_FALSE);
259 }
260 len = snprintf(attr_buf, PLUGIN_MAXATT, "%s=%s;",
261 key_buf, val_buf);
262 if (len < 0 || len >= PLUGIN_MAXATT) {
263 prt_error(gettext("Too long attribute: %s\n"),
264 key_buf);
265 return (B_FALSE);
266 }
267 if (strlcat(attr_string, attr_buf, PLUGIN_MAXATT) >=
268 PLUGIN_MAXATT) {
269 prt_error(gettext("Too long attribute string: "
270 "%s\n"), key_buf);
271 return (B_FALSE);
272 }
273 break;
274 }
275 case SCF_TYPE_COUNT: {
276 uint64_t pval_count;
277 if (scf_value_get_count(handle_iter->prop_val,
278 &pval_count) == -1) {
279 prt_scf_err();
280 return (B_FALSE);
281 }
282 len = snprintf(attr_buf, PLUGIN_MAXATT, "%s=%llu;",
283 key_buf, pval_count);
284 if (len < 0 || len >= PLUGIN_MAXATT) {
285 prt_error(gettext("Too long attribute: %s\n"),
286 key_buf);
287 return (B_FALSE);
288 }
289 if (strlcat(attr_string, attr_buf, PLUGIN_MAXATT) >=
290 PLUGIN_MAXATT) {
291 prt_error(gettext("Too long attribute string: "
292 "%s\n"), key_buf);
293 return (B_FALSE);
294 }
295 break;
296 }
297 default:
298 (void) printf("Unsupported value type %s [%d]\n",
299 key_buf, prop_type);
300 break;
301 }
302 }
303
304 if (*attr_string == '\0' ||
305 (*plugin_kva = _str2kva(attr_string, "=", ";")) == NULL) {
306 prt_error(gettext("Empty or invalid attribute string."));
307 return (B_FALSE);
308 }
309
310 return (B_TRUE);
311 }
312
313 /*
314 * get_plugin_kva() - get and save config attributes of given plugin plugin_str
315 * (or all plugins in case plugin_str == NULL) into scf_plugin_kva_node_t.
316 */
317 static boolean_t
get_plugin_kva(asi_scfhandle_t * handle,asi_scfhandle_iter_t * handle_iter,scf_plugin_kva_node_t ** plugin_kva_ll,char * plugin_str)318 get_plugin_kva(asi_scfhandle_t *handle, asi_scfhandle_iter_t *handle_iter,
319 scf_plugin_kva_node_t **plugin_kva_ll, char *plugin_str)
320 {
321
322 scf_plugin_kva_node_t *node = NULL;
323 scf_plugin_kva_node_t *node_prev = NULL;
324 scf_plugin_kva_node_t *node_head = NULL;
325 char plugin_str_tmp[PLUGIN_MAXBUF];
326
327 bzero(plugin_str_tmp, PLUGIN_MAXBUF);
328
329 if (scf_iter_instance_pgs_typed(handle_iter->pgrp, handle->inst,
330 (const char *)"plugin") == -1) {
331 prt_scf_err();
332 return (B_FALSE);
333 }
334
335 while (scf_iter_next_pg(handle_iter->pgrp, handle->pgrp) == 1) {
336 if (scf_pg_get_name(handle->pgrp, plugin_str_tmp,
337 PLUGIN_MAXBUF) == -1) {
338 prt_scf_err();
339 plugin_kva_ll_free(node);
340 return (B_FALSE);
341 }
342
343 if (plugin_str != NULL &&
344 strcmp(plugin_str_tmp, plugin_str) != 0) {
345 continue;
346 }
347
348 if ((node =
349 calloc(1, sizeof (scf_plugin_kva_node_t))) == NULL) {
350 prt_error(gettext("No available memory."));
351 plugin_kva_ll_free(node_prev);
352 return (B_FALSE);
353 }
354 if (node_head == NULL) {
355 node_head = node;
356 }
357 if (node_prev != NULL) {
358 node_prev->next = node;
359 node->prev = node_prev;
360 }
361 node_prev = node;
362
363 (void) strlcat((char *)&(node->plugin_name), plugin_str_tmp,
364 PLUGIN_MAXBUF);
365
366 if (scf_iter_pg_properties(handle_iter->prop,
367 handle->pgrp) != 0) {
368 prt_scf_err();
369 plugin_kva_ll_free(node);
370 return (B_FALSE);
371 }
372
373 if (!get_props_kva_all(handle, handle_iter,
374 &(node->plugin_kva))) {
375 plugin_kva_ll_free(node);
376 return (B_FALSE);
377 }
378 }
379
380 #if DEBUG
381 {
382 scf_plugin_kva_node_t *node_debug = node_head;
383 char attr_string[PLUGIN_MAXATT];
384
385 while (node_debug != NULL) {
386 if (_kva2str(node_debug->plugin_kva, attr_string,
387 PLUGIN_MAXATT, "=", ";") == 0) {
388 DPRINT((dbfp, "Found plugin - %s: %s\n",
389 node_debug->plugin_name, attr_string));
390 } else {
391 DPRINT((dbfp, "Could not get attribute string "
392 "for %s\n", node_debug->plugin_name));
393 }
394 node_debug = node_debug->prev;
395 }
396 }
397 #endif
398
399 *plugin_kva_ll = node_head;
400
401 return (B_TRUE);
402 }
403
404 /*
405 * scf_free() - free scf handles
406 */
407 static void
scf_free(asi_scfhandle_t * handle)408 scf_free(asi_scfhandle_t *handle)
409 {
410 if (handle == NULL) {
411 return;
412 }
413
414 if (handle->prop != NULL) {
415 scf_property_destroy(handle->prop);
416 }
417 if (handle->pgrp != NULL) {
418 scf_pg_destroy(handle->pgrp);
419 }
420 if (handle->inst != NULL) {
421 scf_instance_destroy(handle->inst);
422 }
423 if (handle->hndl != NULL) {
424 if (scf_handle_unbind(handle->hndl) == -1) {
425 prt_error(gettext("Internal error."));
426 prt_scf_err();
427 }
428 scf_handle_destroy(handle->hndl);
429 }
430 }
431
432 /*
433 * scf_init() - initiate scf handles
434 */
435 static boolean_t
scf_init(asi_scfhandle_t * handle)436 scf_init(asi_scfhandle_t *handle)
437 {
438 bzero(handle, sizeof (asi_scfhandle_t));
439
440 if ((handle->hndl = scf_handle_create(SCF_VERSION)) == NULL ||
441 scf_handle_bind(handle->hndl) != 0) {
442 goto err_out;
443 }
444 if ((handle->inst = scf_instance_create(handle->hndl)) == NULL) {
445 goto err_out;
446 }
447 if ((handle->pgrp = scf_pg_create(handle->hndl)) == NULL) {
448 goto err_out;
449 }
450 if ((handle->prop = scf_property_create(handle->hndl)) == NULL) {
451 goto err_out;
452 }
453
454 return (B_TRUE);
455
456 err_out:
457 prt_scf_err();
458 scf_free(handle);
459 return (B_FALSE);
460 }
461
462 /*
463 * scf_free_iter() - free scf iter handles
464 */
465 static void
scf_free_iter(asi_scfhandle_iter_t * handle_iter)466 scf_free_iter(asi_scfhandle_iter_t *handle_iter)
467 {
468 if (handle_iter == NULL) {
469 return;
470 }
471
472 if (handle_iter->pgrp != NULL) {
473 scf_iter_destroy(handle_iter->pgrp);
474 }
475 if (handle_iter->prop != NULL) {
476 scf_iter_destroy(handle_iter->prop);
477 }
478 if (handle_iter->prop_val != NULL) {
479 scf_value_destroy(handle_iter->prop_val);
480 }
481 }
482
483 /*
484 * scf_init_iter() - initiate scf iter handles
485 */
486 static boolean_t
scf_init_iter(asi_scfhandle_iter_t * handle_iter,asi_scfhandle_t * handle)487 scf_init_iter(asi_scfhandle_iter_t *handle_iter,
488 asi_scfhandle_t *handle)
489 {
490 bzero(handle_iter, sizeof (asi_scfhandle_iter_t));
491
492 if ((handle_iter->pgrp = scf_iter_create(handle->hndl)) == NULL) {
493 goto err_out;
494 }
495 if ((handle_iter->prop = scf_iter_create(handle->hndl)) == NULL) {
496 goto err_out;
497 }
498 if ((handle_iter->prop_val = scf_value_create(handle->hndl)) == NULL) {
499 goto err_out;
500 }
501
502 return (B_TRUE);
503
504 err_out:
505 prt_scf_err();
506 scf_free_iter(handle_iter);
507 return (B_FALSE);
508 }
509
510 /*
511 * chk_policy_context() - does some policy based checks, checks the context
512 * (zone, smf) in which the policy could make some sense.
513 */
514 static boolean_t
chk_policy_context(char * policy_str)515 chk_policy_context(char *policy_str)
516 {
517
518 /*
519 * "all" and "none" policy flags, since they represent
520 * sub/set of auditing policies, are not stored in the
521 * AUDITD_FMRI service instance configuration.
522 */
523 DPRINT((dbfp, "Walking policy - %s: ", policy_str));
524 if (strcmp("all", policy_str) == 0 ||
525 strcmp("none", policy_str) == 0) {
526 DPRINT((dbfp, "skipped\n"));
527 return (B_FALSE);
528 }
529 /*
530 * In the local zone (!= GLOBAL_ZONEID) we do not touch
531 * "ahlt" and "perzone" policy flags, since these are
532 * relevant only in the global zone.
533 */
534 if ((getzoneid() != GLOBAL_ZONEID) &&
535 (strcmp("ahlt", policy_str) == 0 ||
536 strcmp("perzone", policy_str) == 0)) {
537 DPRINT((dbfp, "skipped\n"));
538 return (B_FALSE);
539 }
540
541 return (B_TRUE);
542 }
543
544 /*
545 * free_static_att_kva() - free hardcoded/static plugin attributes (key/value
546 * pairs) from the kva plugin structure.
547 */
548 void
free_static_att_kva(kva_t * plugin_kva)549 free_static_att_kva(kva_t *plugin_kva)
550 {
551 _kva_free_value(plugin_kva, PLUGIN_ACTIVE);
552 _kva_free_value(plugin_kva, PLUGIN_PATH);
553 _kva_free_value(plugin_kva, PLUGIN_QSIZE);
554 _kva_free_value(plugin_kva, "read_authorization");
555 _kva_free_value(plugin_kva, "value_authorization");
556 }
557
558
559 /*
560 * do_getqctrl_scf() - get the values of qctrl properties of the audit service
561 */
562 boolean_t
do_getqctrl_scf(struct au_qctrl * cval)563 do_getqctrl_scf(struct au_qctrl *cval)
564 {
565 scf_propvec_t *prop_vect_ptr;
566 scf_qctrl_t cval_scf;
567
568 bzero(prop_vect, sizeof (prop_vect));
569
570 prop_vect_ptr = prop_vect;
571 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QHIWATER,
572 SCF_TYPE_COUNT, &cval_scf.scf_qhiwater);
573 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QLOWATER,
574 SCF_TYPE_COUNT, &cval_scf.scf_qlowater);
575 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QBUFSZ,
576 SCF_TYPE_COUNT, &cval_scf.scf_qbufsz);
577 add_prop_vect_scf(prop_vect_ptr, QUEUECTRL_QDELAY,
578 SCF_TYPE_COUNT, &cval_scf.scf_qdelay);
579
580 if (!get_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL)) {
581 return (B_FALSE);
582 }
583
584 cval->aq_hiwater = (size_t)cval_scf.scf_qhiwater;
585 cval->aq_lowater = (size_t)cval_scf.scf_qlowater;
586 cval->aq_bufsz = (size_t)cval_scf.scf_qbufsz;
587 cval->aq_delay = (clock_t)cval_scf.scf_qdelay;
588
589 scf_clean_propvec(prop_vect);
590
591 return (B_TRUE);
592 }
593
594 /*
595 * do_getqbufsz_scf() - get the qbufsz audit service property value
596 */
597 boolean_t
do_getqbufsz_scf(size_t * cval)598 do_getqbufsz_scf(size_t *cval)
599 {
600 uint64_t cval_l;
601
602 bzero(prop_vect, sizeof (prop_vect));
603 add_prop_vect_scf(prop_vect, QUEUECTRL_QBUFSZ, SCF_TYPE_COUNT, &cval_l);
604
605 if (!get_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL)) {
606 return (B_FALSE);
607 }
608
609 *cval = (size_t)cval_l;
610
611 return (B_TRUE);
612 }
613
614 /*
615 * do_getqdelay_scf() - get the qdelay audit service property value
616 */
617 boolean_t
do_getqdelay_scf(clock_t * cval)618 do_getqdelay_scf(clock_t *cval)
619 {
620 uint64_t cval_l;
621
622 bzero(prop_vect, sizeof (prop_vect));
623 add_prop_vect_scf(prop_vect, QUEUECTRL_QDELAY, SCF_TYPE_COUNT, &cval_l);
624
625 if (!get_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL)) {
626 return (B_FALSE);
627 }
628
629 *cval = (clock_t)cval_l;
630
631 return (B_TRUE);
632 }
633
634 /*
635 * do_getqhiwater_scf() - get the qhiwater audit service property value
636 */
637 boolean_t
do_getqhiwater_scf(size_t * cval)638 do_getqhiwater_scf(size_t *cval)
639 {
640 uint64_t cval_l;
641
642 bzero(prop_vect, sizeof (prop_vect));
643 add_prop_vect_scf(prop_vect, QUEUECTRL_QHIWATER, SCF_TYPE_COUNT,
644 &cval_l);
645
646 if (!get_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL)) {
647 return (B_FALSE);
648 }
649
650 *cval = (size_t)cval_l;
651
652 return (B_TRUE);
653 }
654
655 /*
656 * do_getqlowater_scf() - get the qlowater audit service property value
657 */
658 boolean_t
do_getqlowater_scf(size_t * cval)659 do_getqlowater_scf(size_t *cval)
660 {
661 uint64_t cval_l;
662
663 bzero(prop_vect, sizeof (prop_vect));
664 add_prop_vect_scf(prop_vect, QUEUECTRL_QLOWATER, SCF_TYPE_COUNT,
665 &cval_l);
666
667 if (!get_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL)) {
668 return (B_FALSE);
669 }
670
671 *cval = (size_t)cval_l;
672
673 return (B_TRUE);
674 }
675
676 /*
677 * do_getpolicy_scf() - get the audit policy flags from service
678 */
679 boolean_t
do_getpolicy_scf(uint32_t * policy_mask)680 do_getpolicy_scf(uint32_t *policy_mask)
681 {
682 int i;
683 scf_propvec_t *prop_vect_ptr;
684 char *cur_policy_str;
685 policy_sw_t policy_arr[POLICY_TBL_SZ + 1];
686 policy_sw_t *policy_arr_ptr;
687
688 prop_vect_ptr = prop_vect;
689 policy_arr_ptr = policy_arr;
690
691 bzero(prop_vect, sizeof (prop_vect));
692 bzero(policy_arr, sizeof (policy_arr));
693
694 /* prepare the smf(5) query */
695 for (i = 0; i < POLICY_TBL_SZ; i++) {
696
697 cur_policy_str = policy_table[i].policy_str;
698
699 /* Do some basic policy dependent checks */
700 if (!chk_policy_context(cur_policy_str)) {
701 continue;
702 }
703 DPRINT((dbfp, "will be queried\n"));
704
705 add_prop_vect_scf(prop_vect_ptr++, cur_policy_str,
706 SCF_TYPE_BOOLEAN, &policy_arr_ptr->flag);
707
708 policy_arr_ptr->policy = cur_policy_str;
709 policy_arr_ptr++;
710
711 }
712 if (!get_val_scf(prop_vect, ASI_PGROUP_POLICY)) {
713 return (B_FALSE);
714 }
715
716 /* set the policy mask */
717 policy_arr_ptr = policy_arr;
718 *policy_mask = 0;
719 while (policy_arr_ptr->policy != NULL) {
720 if (policy_arr_ptr->flag) {
721 *policy_mask |= get_policy(policy_arr_ptr->policy);
722 }
723 policy_arr_ptr++;
724 }
725
726 return (B_TRUE);
727 }
728
729 /*
730 * do_setpolicy_scf() - sets the policy flags in audit service configuration
731 */
732 boolean_t
do_setpolicy_scf(uint32_t policy)733 do_setpolicy_scf(uint32_t policy)
734 {
735 int i;
736 char *cur_policy_str;
737 scf_propvec_t *prop_vect_ptr;
738 boolean_t bool_arr[POLICY_TBL_SZ];
739 boolean_t *bool_arr_ptr;
740
741 prop_vect_ptr = prop_vect;
742 bool_arr_ptr = bool_arr;
743
744 bzero(prop_vect, sizeof (prop_vect));
745 bzero(bool_arr, sizeof (bool_arr));
746
747 for (i = 0; i < POLICY_TBL_SZ; i++) {
748
749 cur_policy_str = policy_table[i].policy_str;
750
751 /* Do some basic policy dependent checks */
752 if (!chk_policy_context(cur_policy_str)) {
753 continue;
754 }
755
756 if (policy_table[i].policy_mask & policy) {
757 *bool_arr_ptr = B_TRUE;
758 } else {
759 *bool_arr_ptr = B_FALSE;
760 }
761
762 DPRINT((dbfp, "%s%s\n", (*bool_arr_ptr == B_TRUE ? "+" : "-"),
763 cur_policy_str));
764
765 add_prop_vect_scf(prop_vect_ptr++, cur_policy_str,
766 SCF_TYPE_BOOLEAN, bool_arr_ptr++);
767
768 }
769
770 return (set_val_scf(prop_vect, ASI_PGROUP_POLICY));
771 }
772
773 /*
774 * do_setqctrl_scf() - set the values of qctrl properties of the audit service
775 */
776 boolean_t
do_setqctrl_scf(struct au_qctrl * cval)777 do_setqctrl_scf(struct au_qctrl *cval)
778 {
779 scf_propvec_t *prop_vect_ptr;
780 scf_qctrl_t cval_scf;
781
782 if (!CHK_BDRY_QHIWATER(cval->aq_lowater, cval->aq_hiwater) &&
783 cval->aq_hiwater != 0) {
784 (void) printf(gettext("Specified audit queue hiwater mark is "
785 "outside of allowed boundaries.\n"));
786 return (B_FALSE);
787 }
788 if (!CHK_BDRY_QLOWATER(cval->aq_lowater, cval->aq_hiwater) &&
789 cval->aq_lowater != 0) {
790 (void) printf(gettext("Specified audit queue lowater mark is "
791 "outside of allowed boundaries.\n"));
792 return (B_FALSE);
793 }
794 if (!CHK_BDRY_QBUFSZ(cval->aq_bufsz) && cval->aq_bufsz != 0) {
795 (void) printf(gettext("Specified audit queue buffer size is "
796 "outside of allowed boundaries.\n"));
797 return (B_FALSE);
798 }
799 if (!CHK_BDRY_QDELAY(cval->aq_delay) && cval->aq_delay != 0) {
800 (void) printf(gettext("Specified audit queue delay is "
801 "outside of allowed boundaries.\n"));
802 return (B_FALSE);
803 }
804
805 cval_scf.scf_qhiwater = (uint64_t)cval->aq_hiwater;
806 cval_scf.scf_qlowater = (uint64_t)cval->aq_lowater;
807 cval_scf.scf_qbufsz = (uint64_t)cval->aq_bufsz;
808 cval_scf.scf_qdelay = (uint64_t)cval->aq_delay;
809
810 bzero(prop_vect, sizeof (prop_vect));
811
812 prop_vect_ptr = prop_vect;
813 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QHIWATER, SCF_TYPE_COUNT,
814 &cval_scf.scf_qhiwater);
815 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QLOWATER, SCF_TYPE_COUNT,
816 &cval_scf.scf_qlowater);
817 add_prop_vect_scf(prop_vect_ptr++, QUEUECTRL_QBUFSZ, SCF_TYPE_COUNT,
818 &cval_scf.scf_qbufsz);
819 add_prop_vect_scf(prop_vect_ptr, QUEUECTRL_QDELAY, SCF_TYPE_COUNT,
820 &cval_scf.scf_qdelay);
821
822 return (set_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL));
823 }
824
825 /*
826 * do_setqbufsz_scf() - set the qbufsz property value of the audit service
827 */
828 boolean_t
do_setqbufsz_scf(size_t * cval)829 do_setqbufsz_scf(size_t *cval)
830 {
831 uint64_t cval_l;
832
833 if (!CHK_BDRY_QBUFSZ(*cval) && *cval != 0) {
834 (void) printf(gettext("Specified audit queue buffer size is "
835 "outside of allowed boundaries.\n"));
836 return (B_FALSE);
837 }
838
839 cval_l = (uint64_t)*cval;
840
841 bzero(prop_vect, sizeof (prop_vect));
842 add_prop_vect_scf(prop_vect, QUEUECTRL_QBUFSZ, SCF_TYPE_COUNT, &cval_l);
843
844 return (set_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL));
845 }
846
847 /*
848 * do_setqdelay_scf() - set the qdelay property value of the audit service
849 */
850 boolean_t
do_setqdelay_scf(clock_t * cval)851 do_setqdelay_scf(clock_t *cval)
852 {
853 uint64_t cval_l;
854
855 if (!CHK_BDRY_QDELAY(*cval) && *cval != 0) {
856 (void) printf(gettext("Specified audit queue delay is "
857 "outside of allowed boundaries.\n"));
858 return (B_FALSE);
859 }
860
861 cval_l = (uint64_t)*cval;
862
863 bzero(prop_vect, sizeof (prop_vect));
864 add_prop_vect_scf(prop_vect, QUEUECTRL_QDELAY, SCF_TYPE_COUNT, &cval_l);
865
866 return (set_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL));
867 }
868
869 /*
870 * do_setqhiwater_scf() - set the qhiwater property value of the audit service
871 */
872 boolean_t
do_setqhiwater_scf(size_t * cval)873 do_setqhiwater_scf(size_t *cval)
874 {
875 uint64_t cval_l;
876 size_t cval_lowater;
877
878 if (!do_getqlowater_scf(&cval_lowater)) {
879 (void) printf(gettext("Could not get configured value of "
880 "queue lowater mark.\n"));
881 return (B_FALSE);
882 }
883 if (cval_lowater == 0) {
884 cval_lowater = AQ_MINLOW;
885 }
886 if (!CHK_BDRY_QHIWATER(cval_lowater, *cval) && *cval != 0) {
887 (void) printf(gettext("Specified audit queue hiwater mark is "
888 "outside of allowed boundaries.\n"));
889 return (B_FALSE);
890 }
891
892 cval_l = (uint64_t)*cval;
893
894 bzero(prop_vect, sizeof (prop_vect));
895 add_prop_vect_scf(prop_vect, QUEUECTRL_QHIWATER, SCF_TYPE_COUNT,
896 &cval_l);
897
898 return (set_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL));
899 }
900
901 /*
902 * do_setqlowater_scf() - set the qlowater property value of the audit service
903 */
904 boolean_t
do_setqlowater_scf(size_t * cval)905 do_setqlowater_scf(size_t *cval)
906 {
907 uint64_t cval_l;
908 size_t cval_hiwater;
909
910 if (!do_getqhiwater_scf(&cval_hiwater)) {
911 (void) printf(gettext("Could not get configured value of "
912 "queue hiwater mark.\n"));
913 return (B_FALSE);
914 }
915 if (cval_hiwater == 0) {
916 cval_hiwater = AQ_MAXHIGH;
917 }
918 if (!CHK_BDRY_QLOWATER(*cval, cval_hiwater) && *cval != 0) {
919 (void) printf(gettext("Specified audit queue lowater mark is "
920 "outside of allowed boundaries.\n"));
921 return (B_FALSE);
922 }
923
924 cval_l = (uint64_t)*cval;
925
926 bzero(prop_vect, sizeof (prop_vect));
927 add_prop_vect_scf(prop_vect, QUEUECTRL_QLOWATER, SCF_TYPE_COUNT,
928 &cval_l);
929
930 return (set_val_scf(prop_vect, ASI_PGROUP_QUEUECTRL));
931 }
932
933 /*
934 * do_getflags_scf() - get the audit attributable flags from service
935 */
936 boolean_t
do_getflags_scf(char ** flags)937 do_getflags_scf(char **flags)
938 {
939 bzero(prop_vect, sizeof (prop_vect));
940 add_prop_vect_scf(prop_vect, PRESELECTION_FLAGS, SCF_TYPE_ASTRING,
941 flags);
942
943 if (!get_val_scf(prop_vect, ASI_PGROUP_PRESELECTION)) {
944 return (B_FALSE);
945 }
946
947 return (B_TRUE);
948 }
949
950 /*
951 * do_getnaflags_scf() - get the audit non-attributable flags from service
952 */
953 boolean_t
do_getnaflags_scf(char ** naflags)954 do_getnaflags_scf(char **naflags)
955 {
956 bzero(prop_vect, sizeof (prop_vect));
957 add_prop_vect_scf(prop_vect, PRESELECTION_NAFLAGS, SCF_TYPE_ASTRING,
958 naflags);
959
960 if (!get_val_scf(prop_vect, ASI_PGROUP_PRESELECTION)) {
961 return (B_FALSE);
962 }
963
964 return (B_TRUE);
965 }
966
967 /*
968 * do_setflags_scf() - set the attributable mask property value of the audit
969 * service
970 */
971 boolean_t
do_setflags_scf(char * flags)972 do_setflags_scf(char *flags)
973 {
974 bzero(prop_vect, sizeof (prop_vect));
975 add_prop_vect_scf(prop_vect, PRESELECTION_FLAGS, SCF_TYPE_ASTRING,
976 flags);
977
978 return (set_val_scf(prop_vect, ASI_PGROUP_PRESELECTION));
979 }
980
981 /*
982 * do_setnaflags_scf() - set the attributable mask property value of the audit
983 * service
984 */
985 boolean_t
do_setnaflags_scf(char * naflags)986 do_setnaflags_scf(char *naflags)
987 {
988 bzero(prop_vect, sizeof (prop_vect));
989 add_prop_vect_scf(prop_vect, PRESELECTION_NAFLAGS, SCF_TYPE_ASTRING,
990 naflags);
991
992 return (set_val_scf(prop_vect, ASI_PGROUP_PRESELECTION));
993 }
994
995 /*
996 * plugin_avail_scf() - look for the plugin in the audit service configuration
997 */
998 boolean_t
plugin_avail_scf(const char * plugin_str)999 plugin_avail_scf(const char *plugin_str)
1000 {
1001 scf_simple_handle_t *sh;
1002
1003 if (plugin_str == NULL || *plugin_str == '\0') {
1004 return (B_FALSE);
1005 }
1006
1007 if ((sh = scf_general_pg_setup(AUDITD_FMRI, plugin_str)) == NULL) {
1008 DPRINT((dbfp, "No such plugin found: %s (%s)\n", plugin_str,
1009 scf_strerror(scf_error())));
1010 return (B_FALSE);
1011 }
1012
1013 scf_simple_handle_destroy(sh);
1014 return (B_TRUE);
1015 }
1016
1017 /*
1018 * do_getpluginconfig_scf() - get plugin configuration from the audit service
1019 * configuration.
1020 */
1021 boolean_t
do_getpluginconfig_scf(char * plugin_str,scf_plugin_kva_node_t ** plugin_kva_ll)1022 do_getpluginconfig_scf(char *plugin_str, scf_plugin_kva_node_t **plugin_kva_ll)
1023 {
1024
1025 char *asi_fmri;
1026 asi_scfhandle_t handle;
1027 asi_scfhandle_iter_t handle_iter;
1028 boolean_t plugin_all = B_FALSE;
1029 boolean_t rv = B_TRUE;
1030
1031 if (plugin_str == NULL || *plugin_str == '\0') {
1032 if (asprintf(&asi_fmri, "%s", AUDITD_FMRI) == -1) {
1033 prt_error(gettext("Out of memory."));
1034 return (B_FALSE);
1035 }
1036 plugin_all = B_TRUE;
1037 } else {
1038 if (asprintf(&asi_fmri, "%s%s%s", AUDITD_FMRI,
1039 SCF_FMRI_PROPERTYGRP_PREFIX, plugin_str) == -1) {
1040 prt_error(gettext("Out of memory."));
1041 return (B_FALSE);
1042 }
1043 }
1044 DPRINT((dbfp, "%s will be decoded\n", asi_fmri));
1045
1046 if (!scf_init(&handle)) {
1047 prt_error(gettext("Unable to initialize scf handles."));
1048 free(asi_fmri);
1049 return (B_FALSE);
1050 }
1051
1052 if (scf_handle_decode_fmri(handle.hndl, asi_fmri, NULL, NULL,
1053 handle.inst, plugin_all ? NULL : handle.pgrp, NULL,
1054 SCF_DECODE_FMRI_EXACT) == -1) {
1055 prt_scf_err();
1056 scf_free(&handle);
1057 free(asi_fmri);
1058 return (B_FALSE);
1059 }
1060
1061 if (!scf_init_iter(&handle_iter, &handle)) {
1062 prt_error(gettext("Unable to initialize scf iter handles."));
1063 scf_free(&handle);
1064 free(asi_fmri);
1065 return (B_FALSE);
1066 }
1067
1068
1069 if (plugin_all) {
1070 rv = get_plugin_kva(&handle, &handle_iter, plugin_kva_ll, NULL);
1071 } else {
1072 rv = get_plugin_kva(&handle, &handle_iter, plugin_kva_ll,
1073 plugin_str);
1074 }
1075
1076 scf_free(&handle);
1077 scf_free_iter(&handle_iter);
1078 free(asi_fmri);
1079 return (rv);
1080 }
1081
1082 /*
1083 * do_setpluginconfig_scf() - set plugin configuration in the audit service
1084 * configuration.
1085 */
1086 boolean_t
do_setpluginconfig_scf(char * plugin_str,boolean_t plugin_state,char * plugin_att,int plugin_qsize)1087 do_setpluginconfig_scf(char *plugin_str, boolean_t plugin_state,
1088 char *plugin_att, int plugin_qsize)
1089 {
1090 kva_t *plugin_att_kva = NULL;
1091 char *plugin_att_ptr = plugin_att;
1092 char *plugin_att_clr_ptr = plugin_att;
1093 scf_simple_prop_t *plugin_prop;
1094 scf_type_t plugin_prop_type;
1095 scf_propvec_t *prop_vect_ptr;
1096 int cnt = 0;
1097 kv_t *data;
1098 boolean_t rval = B_TRUE;
1099 uint64_t plugin_qsize_l = (uint64_t)plugin_qsize;
1100
1101 DPRINT((dbfp, "Auditd plugin configuration to be set:\n\tplugin=%s\n\t"
1102 "state=%d (%s)\n\tattributes=%s\n\tqsize=%d%s\n", plugin_str,
1103 plugin_state, plugin_state == B_TRUE ? "active" : "inactive",
1104 plugin_att == NULL ? " (unspecified)" : plugin_att,
1105 plugin_qsize, plugin_qsize == -1 ? " (unspecified)" : ""));
1106
1107 bzero(prop_vect, sizeof (prop_vect));
1108 prop_vect_ptr = prop_vect;
1109
1110 if (plugin_att != NULL) {
1111
1112 /* get rid of white-space chars */
1113 if (*plugin_att_ptr != '\0') {
1114 while (*plugin_att_ptr != '\0') {
1115 if (isspace(*plugin_att_ptr) == 0) {
1116 *plugin_att_clr_ptr++ = *plugin_att_ptr;
1117 }
1118 plugin_att_ptr++;
1119 }
1120 *plugin_att_clr_ptr = '\0';
1121 }
1122 DPRINT((dbfp, "attributes (no white-space): %s\n", plugin_att));
1123
1124 /* allow empty plugin_att */
1125 if (*plugin_att == '\0') {
1126 cnt = 0;
1127 data = NULL;
1128 } else {
1129 plugin_att_kva = _str2kva(plugin_att, "=", ";");
1130 if (plugin_att_kva == NULL) {
1131 prt_error(gettext("Could not parse plugin "
1132 "attributes."));
1133 return (B_FALSE);
1134 }
1135
1136 free_static_att_kva(plugin_att_kva);
1137 cnt = plugin_att_kva->length;
1138 data = plugin_att_kva->data;
1139 }
1140 }
1141
1142 /* set state */
1143 add_prop_vect_scf(prop_vect_ptr++, PLUGIN_ACTIVE, SCF_TYPE_BOOLEAN,
1144 &plugin_state);
1145 DPRINT((dbfp, "Prepared active -> %d\n", plugin_state));
1146
1147 /* set attributes */
1148 while (cnt) {
1149 if (data->value == NULL) {
1150 cnt--;
1151 data++;
1152 continue;
1153 }
1154 if (!chk_prop_vect(&prop_vect_ptr, plugin_str)) {
1155 rval = B_FALSE;
1156 goto err_out;
1157 }
1158
1159 if ((plugin_prop = scf_simple_prop_get(NULL,
1160 AUDITD_FMRI, plugin_str, data->key)) == NULL) {
1161 prt_error(gettext("Could not get configuration for "
1162 "attribute: %s"), data->key);
1163 prt_scf_err();
1164 rval = B_FALSE;
1165 goto err_out;
1166 }
1167 if ((plugin_prop_type = scf_simple_prop_type(plugin_prop))
1168 == -1) {
1169 prt_error(gettext("Could not get property type: %s"),
1170 data->key);
1171 prt_scf_err();
1172 rval = B_FALSE;
1173 goto err_out;
1174 }
1175
1176 switch (plugin_prop_type) {
1177 case SCF_TYPE_BOOLEAN: {
1178 uint8_t *pval_bool;
1179 pval_bool = (uint8_t *)malloc(sizeof (uint8_t));
1180 if (pval_bool == NULL) {
1181 prt_error(gettext("No free memory available."));
1182 rval = B_FALSE;
1183 goto err_out;
1184 }
1185 *pval_bool = (uint8_t)atoi(data->value);
1186 add_prop_vect_scf(prop_vect_ptr++, data->key,
1187 SCF_TYPE_BOOLEAN, pval_bool);
1188 break;
1189 }
1190 case SCF_TYPE_ASTRING: {
1191 char *pval_str;
1192 if ((pval_str = strdup(data->value)) == NULL) {
1193 prt_error(gettext("No free memory available."));
1194 rval = B_FALSE;
1195 goto err_out;
1196 }
1197 add_prop_vect_scf(prop_vect_ptr++, data->key,
1198 SCF_TYPE_ASTRING, pval_str);
1199 break;
1200 }
1201 case SCF_TYPE_COUNT: {
1202 uint64_t *pval_count;
1203 pval_count = (uint64_t *)malloc(sizeof (uint64_t));
1204 if (pval_count == NULL) {
1205 prt_error(gettext("No free memory available."));
1206 rval = B_FALSE;
1207 goto err_out;
1208 }
1209 *pval_count = (uint64_t)atoll(data->value);
1210 add_prop_vect_scf(prop_vect_ptr++, data->key,
1211 SCF_TYPE_COUNT, pval_count);
1212 break;
1213 }
1214 default:
1215 prt_error(gettext("Unsupported property type: %s (%d)"),
1216 data->key, plugin_prop_type);
1217 break;
1218 }
1219
1220 DPRINT((dbfp, "Prepared %s -> %s\n", data->key, data->value));
1221 scf_simple_prop_free(plugin_prop);
1222 data++;
1223 cnt--;
1224 }
1225
1226 if (!chk_prop_vect(&prop_vect_ptr, plugin_str)) {
1227 rval = B_FALSE;
1228 goto err_out;
1229 }
1230
1231 /* set qsize */
1232 if (plugin_qsize != -1) {
1233 add_prop_vect_scf(prop_vect_ptr, PLUGIN_QSIZE, SCF_TYPE_COUNT,
1234 &plugin_qsize_l);
1235 DPRINT((dbfp, "Prepared qsize -> %d\n", plugin_qsize));
1236 }
1237
1238 if (!set_val_scf(prop_vect, plugin_str)) {
1239 rval = B_FALSE;
1240 }
1241
1242 err_out:
1243 free_prop_vect();
1244 _kva_free(plugin_att_kva);
1245 return (rval);
1246 }
1247
1248 /*
1249 * plugin_kva_ll_free() - free the memory used by plugin kva linked list.
1250 */
1251 void
plugin_kva_ll_free(scf_plugin_kva_node_t * node)1252 plugin_kva_ll_free(scf_plugin_kva_node_t *node)
1253 {
1254 scf_plugin_kva_node_t *node_next;
1255
1256 if (node == NULL) {
1257 return;
1258 }
1259
1260 while (node->prev != NULL) {
1261 node = node->prev;
1262 }
1263 while (node != NULL) {
1264 _kva_free(node->plugin_kva);
1265 node_next = node->next;
1266 free(node);
1267 node = node_next;
1268 }
1269 }
1270
1271 /*
1272 * get_policy() - get policy mask entry
1273 */
1274 uint32_t
get_policy(char * policy)1275 get_policy(char *policy)
1276 {
1277 int i;
1278
1279 for (i = 0; i < POLICY_TBL_SZ; i++) {
1280 if (strcasecmp(policy, policy_table[i].policy_str) == 0) {
1281 return (policy_table[i].policy_mask);
1282 }
1283 }
1284
1285 return (0);
1286 }
1287