Example #1
0
/*
 * Gets string property value.upto sz size.
 * Caller is responsible to have enough memory allocated.
 */
int
smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
    char *valstr, size_t sz)
{
	int ret = SMBD_SMF_OK;
	scf_value_t *value;
	scf_property_t *prop;

	if (handle == NULL)
		return (SMBD_SMF_SYSTEM_ERR);

	value = scf_value_create(handle->scf_handle);
	prop = scf_property_create(handle->scf_handle);
	if (value && prop &&
	    (scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
		if (scf_property_get_value(prop, value) == 0) {
			if (scf_value_get_astring(value, valstr, sz) < 0) {
				ret = SMBD_SMF_SYSTEM_ERR;
			}
		} else {
			ret = SMBD_SMF_SYSTEM_ERR;
		}
	} else {
		ret = SMBD_SMF_SYSTEM_ERR;
	}
	if (value != NULL)
		scf_value_destroy(value);
	if (prop != NULL)
		scf_property_destroy(prop);
	return (ret);
}
Example #2
0
/*
  In Solaris 11 the audit daemon has been moved to SMF. In the process
  they simply dropped getacna() from the API, since it read from a now
  non-existent config file. This function re-implements getacna() to
  read from the SMF repository instead.
 */
int
getacna(char *auditstring, int len)
{
	scf_handle_t *handle = NULL;
	scf_property_t *property = NULL;
	scf_value_t *value = NULL;
	int ret = 0;

	handle = scf_handle_create(SCF_VERSION);
	if (handle == NULL) 
	        return -2; /* The man page for getacna on Solaris 10 states
			      we should return -2 in case of error and set
			      errno to indicate the error. We don't bother
			      with errno here, though, since the only use
			      of this function below doesn't check for errors
			      anyway. 
			   */

	ret = scf_handle_bind(handle);
	if (ret == -1) 
	        return -2;

	property = scf_property_create(handle);
	if (property == NULL) 
	        return -2;

	ret = scf_handle_decode_fmri(handle, 
	     "svc:/system/auditd:default/:properties/preselection/naflags",
				     NULL, NULL, NULL, NULL, property, 0);
	if (ret == -1) 
	        return -2;

	value = scf_value_create(handle);
	if (value == NULL) 
	        return -2;

	ret = scf_property_get_value(property, value);
	if (ret == -1) 
	        return -2;

	ret = scf_value_get_astring(value, auditstring, len);
	if (ret == -1) 
	        return -2;

	scf_value_destroy(value);
	scf_property_destroy(property);
	scf_handle_destroy(handle);

	return 0;
}
Example #3
0
static void
kbd_defaults(int kbd)
{
    scf_handle_t *h = NULL;
    scf_snapshot_t *snap = NULL;
    scf_instance_t *inst = NULL;
    scf_propertygroup_t *pg = NULL;
    scf_property_t *prop = NULL;
    scf_value_t *val = NULL;

    int layout_num;
    char *val_layout = NULL, *val_abort = NULL;
    uint8_t val_click;
    int64_t val_delay, val_rate;
    int64_t val_kbd_beeper, val_console_beeper;

    if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
            scf_handle_bind(h) != 0 ||
            (inst = scf_instance_create(h)) == NULL ||
            (snap = scf_snapshot_create(h)) == NULL ||
            (pg = scf_pg_create(h)) == NULL ||
            (prop = scf_property_create(h)) == NULL ||
            (val = scf_value_create(h)) == NULL) {
        goto out;
    }

    if (scf_handle_decode_fmri(h, KBD_FMRI, NULL, NULL, inst,
                               NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
        goto out;
    }

    if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
        scf_snapshot_destroy(snap);
        snap = NULL;
    }

    if (scf_instance_get_pg_composed(inst, snap, KBD_PG, pg) != 0) {
        goto out;
    }

    if ((val_abort = malloc(KBD_MAX_NAME_LEN)) == NULL) {
        (void) fprintf(stderr,
                       "Can not alloc memory for keyboard properties\n");
        goto out;
    }

    if ((val_layout = malloc(KBD_MAX_NAME_LEN)) == NULL) {
        (void) fprintf(stderr,
                       "Can not alloc memory for keyboard properties\n");
        goto out;
    }

    if (scf_pg_get_property(pg, KBD_PROP_KEYCLICK, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_boolean(val, &val_click) == -1) {
        (void) fprintf(stderr, "Can not get KEYCLICK\n");
    }

    if (val_click == 1)
        (void) click("on", kbd);
    else if (val_click == 0)
        (void) click("off", kbd);
    else
        (void) fprintf(stderr,
                       BAD_DEFAULT_INT, KBD_PROP_KEYCLICK, val_click);

    if (scf_pg_get_property(pg, KBD_PROP_KEYBOARD_ABORT, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_astring(val, val_abort, KBD_MAX_NAME_LEN) == -1) {
        (void) fprintf(stderr, "Can not get KEYBOARD_ABORT\n");
    }

    if (*val_abort != '\0') {
        /*
         * ABORT must equal "enable", "disable" or "alternate"
         */
        if ((strcmp(val_abort, "enable") == 0) ||
                (strcmp(val_abort, "alternate") == 0) ||
                (strcmp(val_abort, "disable") == 0))
            (void) abort_enable(val_abort, kbd);
        else
            (void) fprintf(stderr, BAD_DEFAULT_STR,
                           KBD_PROP_KEYBOARD_ABORT, val_abort);
    }

    if (scf_pg_get_property(pg, KBD_PROP_RPTDELAY, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_integer(val, &val_delay) == -1) {
        (void) fprintf(stderr, "Can not get RPTDELAY\n");
    }

    if (val_delay > 0)
        (void) set_rptdelay(val_delay, kbd);
    else
        (void) fprintf(stderr,
                       BAD_DEFAULT_LLINT, KBD_PROP_RPTDELAY, val_delay);

    if (scf_pg_get_property(pg, KBD_PROP_RPTRATE, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_integer(val, &val_rate) == -1) {
        (void) fprintf(stderr, "Can not get RPTRATE\n");
    }

    if (val_rate > 0)
        (void) set_rptrate(val_rate, kbd);
    else
        (void) fprintf(stderr,
                       BAD_DEFAULT_LLINT, KBD_PROP_RPTRATE, val_rate);

    if (scf_pg_get_property(pg, KBD_PROP_LAYOUT, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_astring(val, val_layout, KBD_MAX_NAME_LEN) == -1) {
        (void) fprintf(stderr, "Can not get LAYOUT\n");
    }

    if (*val_layout != '\0') {
        /*
         * LAYOUT must be one of the layouts supported in kbd_layouts
         */
        if (get_layouts() != 0)
            goto out;

        if ((layout_num = get_layout_number(val_layout)) == -1) {
            (void) fprintf(stderr,
                           BAD_DEFAULT_STR, KBD_PROP_LAYOUT, val_layout);
            goto out;
        }

        (void) set_layout(kbd, layout_num);
    }

    if (scf_pg_get_property(pg, KBD_PROP_FREQ, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_integer(val, &val_kbd_beeper) == -1) {
        (void) fprintf(stderr, "Can not get FREQ\n");
    }

    if (val_kbd_beeper >= 0 && val_kbd_beeper <= INT16_MAX)
        (void) set_beep_freq(kbd, "keyboard", val_kbd_beeper);
    else
        (void) fprintf(stderr,
                       BAD_DEFAULT_LLINT, KBD_PROP_FREQ, val_kbd_beeper);

    if (scf_pg_get_property(pg, KBD_PROP_CONSFREQ, prop) != 0 ||
            scf_property_get_value(prop, val) != 0 ||
            scf_value_get_integer(val, &val_console_beeper) == -1) {
        (void) fprintf(stderr, "Can not get CONSFREQ\n");
    }

    if (val_console_beeper >= 0 && val_console_beeper <= INT16_MAX)
        (void) set_beep_freq(kbd, "console", val_console_beeper);
    else
        (void) fprintf(stderr,
                       BAD_DEFAULT_LLINT, KBD_PROP_CONSFREQ, val_console_beeper);

out:
    if (val_layout != NULL)
        free(val_layout);
    if (val_abort != NULL)
        free(val_abort);
    if (snap != NULL)
        scf_snapshot_destroy(snap);
    scf_value_destroy(val);
    scf_property_destroy(prop);
    scf_pg_destroy(pg);
    scf_instance_destroy(inst);
    scf_handle_destroy(h);
}
Example #4
0
/*
 * Returns a zone ID of Solaris when the TZ value is "localtime".
 * First, it tries scf. If scf fails, it looks for the same file as
 * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
 */
static char *
getSolarisDefaultZoneID() {
    char *tz = NULL;
    struct stat statbuf;
    size_t size;
    char *buf;
    int fd;
    /* scf specific variables */
    scf_handle_t *h = NULL;
    scf_snapshot_t *snap = NULL;
    scf_instance_t *inst = NULL;
    scf_propertygroup_t *pg = NULL;
    scf_property_t *prop = NULL;
    scf_value_t *val = NULL;

    if ((h = scf_handle_create(SCF_VERSION)) != NULL
        && scf_handle_bind(h) == 0
        && (inst = scf_instance_create(h)) != NULL
        && (snap = scf_snapshot_create(h)) != NULL
        && (pg = scf_pg_create(h)) != NULL
        && (prop = scf_property_create(h)) != NULL
        && (val = scf_value_create(h)) != NULL
        && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
                                  NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
        && scf_instance_get_snapshot(inst, "running", snap) == 0
        && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
        && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
        && scf_property_get_value(prop, val) == 0) {
        ssize_t len;

        /* Gets the length of the zone ID string */
        len = scf_value_get_astring(val, NULL, 0);
        if (len != -1) {
            tz = malloc(++len); /* +1 for a null byte */
            if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
                cleanupScf(h, snap, inst, pg, prop, val, NULL);
                return tz;
            }
        }
    }
    cleanupScf(h, snap, inst, pg, prop, val, tz);

    if (stat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
        return NULL;
    }
    size = (size_t) statbuf.st_size;
    buf = malloc(size);
    if (buf == NULL) {
        return NULL;
    }
    if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
        free((void *) buf);
        return NULL;
    }

    if (read(fd, buf, size) != (ssize_t) size) {
        (void) close(fd);
        free((void *) buf);
        return NULL;
    }
    (void) close(fd);
    tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
    free((void *) buf);
    return tz;
}
Example #5
0
int
fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf,
    char *instance, scf_type_t sctype, char *fmri, int *bufsz)
{
	fs_smfhandle_t *phandle = NULL;
	scf_handle_t *handle;
	scf_propertygroup_t *pg;
	scf_property_t *prop;
	scf_value_t *val;
	scf_instance_t *inst;
	int ret = 0, len = 0, length;
	int64_t valint = 0;
	char srv[MAXPATHLEN], *p, *svcname;
	const char *pgname;
	uint8_t bval;

	/*
	 * The SVC names we are using currently are already
	 * appended by default. Fix this for instances project.
	 */
	snprintf(srv, MAXPATHLEN, "%s", fmri);
	p = strstr(fmri, ":default");
	if (p == NULL) {
		strcat(srv, ":");
		if (instance == NULL)
			instance = "default";
		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
			goto out;
		strncat(srv, instance, strlen(instance));
	}
	svcname = srv;
	phandle = fs_smf_init(fmri, instance);
	if (phandle == NULL)
		return (SMF_SYSTEM_ERR);
	handle = phandle->fs_handle;
	pg = phandle->fs_pg;
	inst = phandle->fs_instance;
	prop = phandle->fs_property;
	val = phandle->fs_value;

	if (handle == NULL || pg == NULL || prop == NULL || val == NULL ||
	    inst == NULL)  {
		return (SMF_SYSTEM_ERR);
	}


	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
		ret = scf_error();
		goto out;
	}

	if (fstype == AUTOFS_SMF)
		pgname = AUTOFS_PROPS_PGNAME;
	else
		pgname = NFS_PROPS_PGNAME;

	if (scf_instance_get_pg(inst, pgname, pg) != -1) {
		if (scf_pg_get_property(pg, prop_name,
		    prop) != SCF_SUCCESS) {
			ret = scf_error();
			goto out;
		}
		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
			ret = scf_error();
			goto out;
		}
		switch (sctype) {
		case SCF_TYPE_ASTRING:
			len = scf_value_get_astring(val, cbuf, *bufsz);
			if (len < 0 || len > *bufsz) {
				ret = scf_error();
				goto out;
			}
			ret = 0;
			*bufsz = len;
		break;
		case SCF_TYPE_INTEGER:
			if (scf_value_get_integer(val, &valint) != 0) {
				ret = scf_error();
				goto out;
			}
			length =  snprintf(cbuf, *bufsz, "%lld", valint);
			if (length < 0 || length > *bufsz) {
				ret = SA_BAD_VALUE;
				goto out;
			}
			ret = 0;
		break;
		case SCF_TYPE_BOOLEAN:
			if (scf_value_get_boolean(val, &bval) != 0) {
				ret = scf_error();
				goto out;
			}
			if (bval == 1) {
				length = snprintf(cbuf, *bufsz, "%s", "true");
			} else {
				length = snprintf(cbuf, *bufsz, "%s", "false");
			}
			if (length < 0 || length > *bufsz) {
				ret = SA_BAD_VALUE;
				goto out;
			}
		break;
		}
	} else {
		ret = scf_error();
	}
	if ((ret != 0) && scf_error() != SCF_ERROR_NONE) {
		/*
		 * This is a workaround for the NFS service manifests not
		 * containing the proper properties in local zones.
		 *
		 * When in a local zone and the property doesn't exist on an NFS
		 * service (most likely nfs/server or nfs/client), don't print
		 * the error.  The caller will still see the correct error code,
		 * but a user creating a delegated dataset or mounting an NFS
		 * share won't see this spurious error.
		 */
		if (getzoneid() == GLOBAL_ZONEID ||
		    scf_error() != SCF_ERROR_NOT_FOUND) {
			fprintf(stdout, gettext("%s\n"), scf_strerror(ret));
		}
	}

out:
	fs_smf_fini(phandle);
	return (ret);
}
Example #6
0
int
fs_smf_get_prop(smf_fstype_t fstype, char *prop_name, char *cbuf,
    char *instance, scf_type_t sctype, char *fmri, int *bufsz)
{
	fs_smfhandle_t *phandle = NULL;
	scf_handle_t *handle;
	scf_propertygroup_t *pg;
	scf_property_t *prop;
	scf_value_t *val;
	scf_instance_t *inst;
	int ret = 0, len = 0, length;
	int64_t valint = 0;
	char srv[MAXPATHLEN], *p, *svcname;
	const char *pgname;
	uint8_t bval;

	/*
	 * The SVC names we are using currently are already
	 * appended by default. Fix this for instances project.
	 */
	snprintf(srv, MAXPATHLEN, "%s", fmri);
	p = strstr(fmri, ":default");
	if (p == NULL) {
		strcat(srv, ":");
		if (instance == NULL)
			instance = "default";
		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
			goto out;
		strncat(srv, instance, strlen(instance));
	}
	svcname = srv;
	phandle = fs_smf_init(fmri, instance);
	if (phandle == NULL)
		return (SMF_SYSTEM_ERR);
	handle = phandle->fs_handle;
	pg = phandle->fs_pg;
	inst = phandle->fs_instance;
	prop = phandle->fs_property;
	val = phandle->fs_value;

	if (handle == NULL || pg == NULL || prop == NULL || val == NULL ||
	    inst == NULL)  {
		return (SMF_SYSTEM_ERR);
	}


	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
		ret = scf_error();
		goto out;
	}

	if (fstype == AUTOFS_SMF)
		pgname = AUTOFS_PROPS_PGNAME;
	else
		pgname = NFS_PROPS_PGNAME;

	if (scf_instance_get_pg(inst, pgname, pg) != -1) {
		if (scf_pg_get_property(pg, prop_name,
		    prop) != SCF_SUCCESS) {
			ret = scf_error();
			goto out;
		}
		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
			ret = scf_error();
			goto out;
		}
		switch (sctype) {
		case SCF_TYPE_ASTRING:
			len = scf_value_get_astring(val, cbuf, *bufsz);
			if (len < 0 || len > *bufsz) {
				ret = scf_error();
				goto out;
			}
			ret = 0;
			*bufsz = len;
		break;
		case SCF_TYPE_INTEGER:
			if (scf_value_get_integer(val, &valint) != 0) {
				ret = scf_error();
				goto out;
			}
			length =  snprintf(cbuf, *bufsz, "%lld", valint);
			if (length < 0 || length > *bufsz) {
				ret = SA_BAD_VALUE;
				goto out;
			}
			ret = 0;
		break;
		case SCF_TYPE_BOOLEAN:
			if (scf_value_get_boolean(val, &bval) != 0) {
				ret = scf_error();
				goto out;
			}
			if (bval == 1) {
				length = snprintf(cbuf, *bufsz, "%s", "true");
			} else {
				length = snprintf(cbuf, *bufsz, "%s", "false");
			}
			if (length < 0 || length > *bufsz) {
				ret = SA_BAD_VALUE;
				goto out;
			}
		break;
		}
	} else {
		ret = scf_error();
	}
	if ((ret != 0) && scf_error() != SCF_ERROR_NONE)
		fprintf(stdout, gettext("%s\n"), scf_strerror(ret));
out:
	fs_smf_fini(phandle);
	return (ret);
}
Example #7
0
void
read_scf_proto_cfg(const char *proto, scf_cfg_t *cfg)
{
	scf_handle_t *handle = NULL;
	scf_scope_t *sc = NULL;
	scf_service_t *svc = NULL;
	scf_propertygroup_t *pg = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *value = NULL;
	scf_iter_t *value_iter = NULL;
	uint64_t val;
	char *str;
	size_t slen;
	int i;

	handle = scf_handle_create(SCF_VERSION);
	sc = scf_scope_create(handle);
	svc = scf_service_create(handle);
	pg = scf_pg_create(handle);
	prop = scf_property_create(handle);
	value = scf_value_create(handle);
	value_iter = scf_iter_create(handle);

	if (handle == NULL || sc == NULL || svc == NULL || pg == NULL ||
	    prop == NULL || value == NULL || value_iter == NULL) {
		DMSG(D_OP, "%s: unable to create smf(5) handles.", proto);
		goto done;
	}

	if (scf_handle_bind(handle) != 0) {
		DMSG(D_OP, "%s: unable to bind smf(5) handle: %s", proto,
		    scf_strerror(scf_error()));
		goto done;
	}

	if (scf_handle_decode_fmri(handle, fmri, sc, svc, NULL, NULL, NULL,
	    0) != 0) {
		DMSG(D_OP, "%s: unable to decode fmri '%s': %s", fmri,
		    scf_strerror(scf_error()));
		goto done;
	}

	if (scf_service_get_pg(svc, proto, pg) != 0 &&
	    scf_error() != SCF_ERROR_NOT_FOUND) {
		DMSG(D_OP, "%s: unable to read '%s' property group: %s",
		    proto, proto, scf_strerror(scf_error()));
		goto done;
	}

	for (i = 0; cfg[i].name != NULL; i++) {
		scf_cfg_t *c = &cfg[i];

		if (scf_pg_get_property(pg, c->name, prop) != 0) {
			if (scf_error() != SCF_ERROR_NOT_FOUND)
				DMSG(D_OP, "%s: unable to read %s/%s from "
				    "smf: %s", proto, proto, c->name,
				    scf_strerror(scf_error()));

			continue;
		}

		if (scf_property_is_type(prop, c->type) != 0) {
			scf_type_t type;

			if (scf_error() != SCF_ERROR_TYPE_MISMATCH) {
				DMSG(D_OP, "%s: unable to validate "
				    "type of '%s/%s' smf property: %s",
				    proto, proto, c->name,
				    scf_strerror(scf_error()));
				continue;
			}

			if (scf_property_type(prop, &type) != 0) {
				DMSG(D_OP, "%s: unable to obtain "
				    "type of '%s/%s' smf property: %s",
				    proto, proto, c->name,
				    scf_strerror(scf_error()));
				continue;
			}

			DMSG(D_OP, "%s: property '%s/%s' has an unexpected "
			    "type:\n"
			    "   expected type: %s\n"
			    "     actual type: %s\n",
			    proto, proto, c->name,
			    scf_type_to_string(c->type),
			    scf_type_to_string(type));
			continue;
		}

		if (scf_property_get_value(prop, value) != 0) {
			if (scf_error() != SCF_ERROR_NOT_SET)
				DMSG(D_OP, "%s: unable to get value of "
				    "'%s/%s' smf property: %s", proto,
				    proto, c->name, scf_strerror(scf_error()));

			continue;
		}

		switch (c->type) {
		case SCF_TYPE_COUNT:
			if (scf_value_get_count(value, &val) != 0) {
				DMSG(D_OP, "%s: unable to read value of "
				    "'%s/%s' smf property: %s", proto, proto,
				    c->name, scf_strerror(scf_error()));
				continue;
			}

			if (val > c->max) {
				DMSG(D_OP, "%s: value of '%s/%s' smf property "
				    "(%'llu) is out of range (0 - %'zu).",
				    proto, proto, c->name, val, c->max);
				continue;
			}
			*((uint32_t *)c->val) = (uint32_t)val;
			break;
		case SCF_TYPE_ASTRING:
		{
			char **valp = (char **)c->val;
			ssize_t len;

			slen = c->max + 1;
			if ((str = malloc(slen)) == NULL) {
				/* XXX message */
				continue;
			}
			if ((len = scf_value_get_astring(value, str,
			    slen)) >= slen)
				DMSG(D_OP, "%s: length of '%s/%s' "
				    "(%'zd bytes) exceeds maximum "
				    "allowable length (%zu bytes).  The string"
				    " will be truncated.", proto, proto,
				    c->name, len, c->max);

			free(*valp);
			*valp = str;
			break;
		}
		default:
			VERIFY(0);
		}
	}

done:
	scf_iter_destroy(value_iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	scf_pg_destroy(pg);
	scf_service_destroy(svc);
	scf_scope_destroy(sc);
	scf_handle_destroy(handle);
}