This patch implements the smf probe on solaris, which gathers service_name,
service_state, exec_as_user from the smf repository for the fmri that is
provided.
This patch has not been contributed upstream, but is planned to be done by
2015-Mar-01.
--- openscap-1.2.0/src/OVAL/probes/unix/solaris/smf.c.~1~ 2013-03-21 08:27:20.051583517 -0700
+++ openscap-1.2.0/src/OVAL/probes/unix/solaris/smf.c 2015-02-18 10:06:03.709601923 -0800
@@ -33,9 +33,240 @@
#endif
#include "probe-api.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(__SVR4) && defined(__sun)
+/*
+ * smf probe:
+ *
+ * fmri
+ * service_name
+ * service_state
+ * protocol
+ * server_executable
+ * server_arguements
+ * exec_as_user
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>
+#include <libscf.h>
+#include <libscf_priv.h>
+#include "seap.h"
+#include "probe/entcmp.h"
+#include "alloc.h"
+#include "common/debug_priv.h"
+
+#ifndef SCF_PG_START
+#define SCF_PG_START "start"
+#endif
+
+/* Convenience structure for the results being reported */
+struct result_info {
+ const char *fmri;
+ char *service_name;
+ char *service_state;
+ char *protocol;
+ char *server_executable;
+ char *server_arguments;
+ char *exec_as_user;
+};
+
+
+static void
+toUpperCase(char *str)
+{
+ int i = 0;
+
+ if (str != NULL) {
+ while (str[i] != '\0') {
+ str[i] = toupper(str[i]);
+ i++;
+ }
+ }
+}
+
+static char *
+strdup_check(char *p)
+{
+ char *ret;
+
+ if ((ret = strdup(p)) == NULL) {
+ oscap_dlprintf(DBG_E, "Error: Out of Memory error.\n");
+ exit(PROBE_ENOMEM);
+ }
+ return (ret);
+}
+
+static void
+get_smf_prop_val(scf_handle_t *h, const char *fmri,
+ const char *prop_grp_name, const char *prop_name, char **val)
+{
+ scf_simple_prop_t *prop;
+ char *prop_val;
+ *val = NULL;
+
+ if ((prop = scf_simple_prop_get(h, fmri, prop_grp_name,
+ prop_name)) == NULL) {
+ if (scf_error() == SCF_ERROR_NOT_FOUND) {
+ oscap_dlprintf(DBG_E, "Error: Specified service "
+ " %s has no %s/%s property.\n",
+ fmri, prop_grp_name, prop_name);
+ } else if (scf_error() == SCF_ERROR_INVALID_ARGUMENT) {
+ oscap_dlprintf(DBG_E, "Error: Invalid service "
+ " %s does not exist.\n",
+ fmri);
+ }
+ } else {
+ if ((prop_val =
+ scf_simple_prop_next_astring(prop)) == NULL) {
+ oscap_dlprintf(DBG_E,
+ "Error: Could not read "
+ " %s/%s property of %s.\n",
+ prop_grp_name,
+ prop_name,
+ fmri);
+ } else if (prop_val[0] != '\0') {
+ *val = strdup_check(prop_val);
+ }
+ scf_simple_prop_free(prop);
+ }
+}
+
+
+static void
+report_finding(struct result_info *res, probe_ctx *ctx)
+{
+ SEXP_t *item;
+
+ oscap_dlprintf(DBG_I, "In report_finding.\n");
+ item = probe_item_create(OVAL_SOLARIS_SMF, NULL,
+ "fmri", OVAL_DATATYPE_STRING, res->fmri,
+ "service_name", OVAL_DATATYPE_STRING, res->service_name,
+ "service_state", OVAL_DATATYPE_STRING, res->service_state,
+ "protocol", OVAL_DATATYPE_STRING, res->protocol,
+ "server_executable", OVAL_DATATYPE_STRING,
+ res->server_executable,
+ "server_arguments", OVAL_DATATYPE_STRING,
+ res->server_arguments,
+ "exec_as_user", OVAL_DATATYPE_STRING, res->exec_as_user,
+ NULL);
+ probe_item_collect(ctx, item);
+}
+
+static int
+collect_smf_info(char *fmri, probe_ctx *ctx)
+{
+ struct result_info r;
+ int rc = 0;
+ char *tmp;
+ scf_handle_t *scf_hdl = NULL;
+ scf_instance_t *inst = NULL;
+ scf_service_t *svc = NULL;
+
+
+ oscap_dlprintf(DBG_I, "In collect_smf_info.\n");
+ memset(&r, 0, sizeof (r));
+ r.fmri = fmri;
+ if ((scf_hdl = scf_handle_create(SCF_VERSION)) == NULL ||
+ scf_handle_bind(scf_hdl) != 0 ||
+ (svc = scf_service_create(scf_hdl)) == NULL ||
+ (inst = scf_instance_create(scf_hdl)) == NULL) {
+ rc = PROBE_EFATAL;
+ goto cleanup;
+ }
+ /* To check if service exists */
+ get_smf_prop_val(scf_hdl, r.fmri, SCF_PG_RESTARTER,
+ SCF_PROPERTY_STATE, &(r.service_state));
+ if (scf_error() == SCF_ERROR_NOT_FOUND) {
+ if (scf_handle_decode_fmri(scf_hdl, fmri, NULL, svc,
+ inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0 ||
+ scf_error() == SCF_ERROR_NOT_FOUND) {
+ oscap_dlprintf(DBG_I,"decode_fmri failed.\n");
+ goto cleanup;
+ }
+ }
+ if (r.service_state != NULL &&
+ r.service_state[0] != '\0')
+ toUpperCase(r.service_state);
+ get_smf_prop_val(scf_hdl, r.fmri, SCF_PG_START,
+ SCF_PROPERTY_EXEC, &(r.server_executable));
+ get_smf_prop_val(scf_hdl, r.fmri, SCF_PG_START,
+ SCF_PROPERTY_USER, &(r.exec_as_user));
+ /*
+ * At this point the fmri we have is valid because
+ * we were able to locate it and get info on the
+ * above listed properties. Now trying to parse
+ * the fmri to only get the service:instance name.
+ * So skipping the scope and service prefix. If we
+ * did not find the scope and service prefix, we
+ * return the full fmri that was passed in.
+ */
+ if ((tmp = strstr(fmri, SCF_FMRI_SCOPE_PREFIX)) != NULL)
+ tmp += sizeof(SCF_FMRI_SCOPE_PREFIX) - 1;
+ else
+ tmp = fmri;
+ if ((tmp = strstr(tmp, SCF_FMRI_SERVICE_PREFIX)) != NULL)
+ tmp += sizeof(SCF_FMRI_SERVICE_PREFIX) - 1;
+ else
+ tmp = fmri;
+ asprintf(&r.service_name, "%s", tmp);
+ report_finding(&r, ctx);
+ free(r.protocol);
+ free(r.service_state);
+ free(r.server_executable);
+ free(r.server_arguments);
+ free(r.exec_as_user);
+cleanup:
+ free(r.service_name);
+ scf_service_destroy(svc);
+ scf_instance_destroy(inst);
+ if (scf_hdl != NULL)
+ scf_handle_unbind(scf_hdl);
+ scf_handle_destroy(scf_hdl);
+ return (rc);
+}
+
+int
+probe_main(probe_ctx *ctx, void *arg)
+{
+ SEXP_t *fmri, *fmri_val, *probe_in;
+ char *fmri_str;
+ int rc;
+
+ probe_in = probe_ctx_getobject(ctx);
+ if (probe_in == NULL) {
+ oscap_dlprintf(DBG_E, "No object in context.\n");
+ return (PROBE_ENOVAL);
+ }
+ fmri = probe_obj_getent(probe_in, "fmri", 1);
+ if (fmri == NULL) {
+ oscap_dlprintf(DBG_E, "No fmri in context.\n");
+ return (PROBE_ENOVAL);
+ }
+ fmri_val = probe_ent_getval(fmri);
+ fmri_str = SEXP_string_cstr(fmri_val);
+ oscap_dlprintf(DBG_I, "fmri in context: %s.\n", fmri_str);
+ rc = collect_smf_info(fmri_str, ctx);
+ free(fmri_str);
+ SEXP_free(fmri_val);
+ SEXP_free(fmri);
+ return (rc);
+}
+#else
int probe_main(probe_ctx *ctx, void *probe_arg)
{
return(PROBE_EOPNOTSUPP);
}
+#endif