2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <strings.h>
2N/A#include <libscf.h>
2N/A#include <syslog.h>
2N/A#include <nfs/fedfs.h>
2N/A#include <libintl.h>
2N/A#include "fedfs_impl.h"
2N/A
2N/A/*
2N/A * fedfs_smf_get_pg() - create a property group name based on host/port.
2N/A *
2N/A * On success, returns an allocated string with the name, which the
2N/A * caller must free. On failure, returns NULL.
2N/A */
2N/Astatic char *
2N/Afedfs_smf_get_pg(char *host, int port)
2N/A{
2N/A int sz;
2N/A char *s, *buf;
2N/A char sport[10];
2N/A
2N/A (void) snprintf(sport, sizeof (sport), "%d", port);
2N/A sz = strlen(host) + 1 + strlen(sport) + 1 + 5;
2N/A buf = calloc(sz, 1);
2N/A if (buf == NULL)
2N/A return (NULL);
2N/A (void) snprintf(buf, sz, "cred_%s_%s", host, sport);
2N/A for (s = buf; s < buf + sz; s++)
2N/A if (*s == '.' || *s == ',' || *s == '=')
2N/A *s = '_';
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_get_pg: built %s\n", buf);
2N/A#endif
2N/A return (buf);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_smf_lookup() - look up the distinguished name (user),
2N/A * password, NCE and security details for a particular host/port.
2N/A *
2N/A * On success, returns a pointer to an allocated nsdb_info_t structure
2N/A * which must be freed by the caller. On failure, returns NULL.
2N/A */
2N/Ansdb_info_t *
2N/Afedfs_smf_lookup(char *host, int port, int prompt_pw)
2N/A{
2N/A char *p, *pgname;
2N/A scf_simple_prop_t *prop;
2N/A nsdb_info_t *info;
2N/A
2N/A pgname = fedfs_smf_get_pg(host, port);
2N/A if (pgname == NULL)
2N/A return (NULL);
2N/A info = calloc(sizeof (nsdb_info_t), 1);
2N/A if (info == NULL) {
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, pgname, "binddn");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find binddn property in pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A free(info);
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A p = scf_simple_prop_next_astring(prop);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: binddn %s\n", p);
2N/A#endif
2N/A info->binddn = strdup(p);
2N/A scf_simple_prop_free(prop);
2N/A
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, pgname, "bindpw");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find bindpw property in pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A fedfs_smf_lookup_free(info);
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A p = scf_simple_prop_next_astring(prop);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: bindpw %s\n", p);
2N/A#endif
2N/A if (strlen(p) != 0 && strcmp(p, "\"\"") != 0)
2N/A info->bindpw = strdup(p);
2N/A else if (prompt_pw) {
2N/A int len;
2N/A char *buf, *pw;
2N/A char *pstring = dgettext(TEXT_DOMAIN, "Enter password for %s:");
2N/A
2N/A len = strlen(pstring) + strlen(info->binddn) + 1;
2N/A buf = malloc(len);
2N/A /* LINTED */
2N/A (void) snprintf(buf, len, pstring, info->binddn);
2N/A pw = getpassphrase(buf);
2N/A if (pw != NULL)
2N/A info->bindpw = strdup(pw);
2N/A else
2N/A info->bindpw = NULL;
2N/A free(buf);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: prompted pw %s\n",
2N/A info->bindpw);
2N/A#endif
2N/A } else
2N/A info->bindpw = NULL;
2N/A scf_simple_prop_free(prop);
2N/A
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, pgname, "sectype");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find sectype property in pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A fedfs_smf_lookup_free(info);
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A p = scf_simple_prop_next_astring(prop);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: sectype %s\n", p);
2N/A#endif
2N/A if (strlen(p) != 0 && strcmp(p, "\"\"") != 0)
2N/A info->sectype = strdup(p);
2N/A else
2N/A info->sectype = NULL;
2N/A scf_simple_prop_free(prop);
2N/A
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, pgname, "certpath");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find certpath property in pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A fedfs_smf_lookup_free(info);
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A p = scf_simple_prop_next_astring(prop);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: certpath %s\n", p);
2N/A#endif
2N/A if (strlen(p) != 0 && strcmp(p, "\"\"") != 0)
2N/A info->certpath = strdup(p);
2N/A else
2N/A info->certpath = NULL;
2N/A scf_simple_prop_free(prop);
2N/A
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, pgname, "nce");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find nce property in pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A fedfs_smf_lookup_free(info);
2N/A free(pgname);
2N/A return (NULL);
2N/A }
2N/A p = scf_simple_prop_next_astring(prop);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_lookup: nce %s\n", p);
2N/A#endif
2N/A info->nce = strdup(p);
2N/A scf_simple_prop_free(prop);
2N/A
2N/A free(pgname);
2N/A return (info);
2N/A}
2N/A
2N/Avoid
2N/Afedfs_smf_lookup_free(nsdb_info_t *info)
2N/A{
2N/A if (info == NULL)
2N/A return;
2N/A free(info->binddn);
2N/A free(info->bindpw);
2N/A free(info->sectype);
2N/A free(info->certpath);
2N/A free(info->nce);
2N/A free(info);
2N/A}
2N/A
2N/A/*
2N/A * get_pg_value() - from property group, get a named astring value.
2N/A */
2N/Astatic char *
2N/Aget_pg_value(scf_handle_t *h, scf_propertygroup_t *pg,
2N/A scf_property_t *prop, char *name)
2N/A{
2N/A size_t valsz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
2N/A char *valbuf;
2N/A scf_value_t *value = NULL;
2N/A
2N/A if ((value = scf_value_create(h)) == NULL)
2N/A return (NULL);
2N/A if (scf_pg_get_property(pg, name, prop) == -1)
2N/A return (NULL);
2N/A if (scf_property_get_value(prop, value) == -1)
2N/A return (NULL);
2N/A valbuf = calloc(valsz, 1);
2N/A if (scf_value_get_astring(value, valbuf, valsz) == -1) {
2N/A free(valbuf);
2N/A return (NULL);
2N/A }
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "get_pg_value: %s=%s\n", name, valbuf);
2N/A#endif
2N/A return (strdup(valbuf));
2N/A}
2N/A
2N/A/*
2N/A * fedfs_smf_list() - enumerate all nsdbparams entried
2N/A *
2N/A * Returns the number of entries in the allocated array of nsdb_list_t
2N/A * entries to which the passed argument points on success. The array
2N/A * must be freed by the caller. On failure, the return is zero.
2N/A */
2N/Aint
2N/Afedfs_smf_list(nsdb_list_t **listp)
2N/A{
2N/A int num = 0;
2N/A scf_handle_t *h = NULL;
2N/A scf_service_t *svc = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A scf_property_t *prop = NULL;
2N/A scf_iter_t *iter = NULL;
2N/A nsdb_list_t *list = NULL, *nlist;
2N/A size_t namesz = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) + 1;
2N/A char *namebuf;
2N/A size_t valsz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH) + 1;
2N/A char *valbuf;
2N/A
2N/A if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
2N/A scf_handle_bind(h) != 0 ||
2N/A (svc = scf_service_create(h)) == NULL ||
2N/A (pg = scf_pg_create(h)) == NULL ||
2N/A (prop = scf_property_create(h)) == NULL ||
2N/A (iter = scf_iter_create(h)) == NULL ||
2N/A scf_handle_decode_fmri(h, FEDFS_CLIENT, NULL, svc,
2N/A NULL, NULL, NULL, 0) != 0) {
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (scf_iter_service_pgs_typed(iter, svc, SCF_GROUP_APPLICATION) != 0)
2N/A goto cleanup;
2N/A
2N/A namebuf = calloc(namesz, 1);
2N/A if (namebuf == NULL)
2N/A goto cleanup;
2N/A valbuf = calloc(valsz, 1);
2N/A if (valbuf == NULL)
2N/A goto cleanup;
2N/A list = calloc(sizeof (nsdb_list_t), 1);
2N/A if (list == NULL)
2N/A goto cleanup;
2N/A for (;;) {
2N/A if (scf_iter_next_pg(iter, pg) != 1)
2N/A break;
2N/A
2N/A if (scf_pg_get_name(pg, namebuf, namesz) == -1)
2N/A break;
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_list: found pg=%s\n", namebuf);
2N/A#endif
2N/A if (strncmp("cred_", namebuf, 5) != 0)
2N/A continue;
2N/A
2N/A nlist = realloc(list, sizeof (nsdb_list_t) * ++num);
2N/A if (nlist == NULL) {
2N/A free(list);
2N/A list = NULL;
2N/A num = 0;
2N/A break;
2N/A }
2N/A list = nlist;
2N/A
2N/A list[num - 1].hostname = get_pg_value(h, pg, prop, "hostname");
2N/A list[num - 1].portnum = get_pg_value(h, pg, prop, "port");
2N/A }
2N/A if (num > 0)
2N/A *listp = list;
2N/A else
2N/A free(list);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_list: found %d entries\n", num);
2N/A#endif
2N/A
2N/Acleanup:
2N/A free(valbuf);
2N/A free(namebuf);
2N/A scf_iter_destroy(iter);
2N/A scf_pg_destroy(pg);
2N/A scf_service_destroy(svc);
2N/A if (h) {
2N/A (void) scf_handle_unbind(h);
2N/A scf_handle_destroy(h);
2N/A }
2N/A return (num);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_smf_delete() - delete the SMF property group entry for host/port.
2N/A *
2N/A * Returns 0 on success and -1 on failure, usually setting scf_error.
2N/A * A caller may print error diagnosis with scf_strerror().
2N/A */
2N/Aint
2N/Afedfs_smf_delete(char *host, int port)
2N/A{
2N/A char *pgname;
2N/A int err = -1;
2N/A scf_handle_t *h = NULL;
2N/A scf_service_t *svc = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A
2N/A pgname = fedfs_smf_get_pg(host, port);
2N/A if (pgname == NULL)
2N/A return (-1);
2N/A
2N/A if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
2N/A scf_handle_bind(h) != 0 ||
2N/A (svc = scf_service_create(h)) == NULL ||
2N/A (pg = scf_pg_create(h)) == NULL ||
2N/A scf_handle_decode_fmri(h, FEDFS_CLIENT, NULL, svc,
2N/A NULL, NULL, NULL, 0) != 0 ||
2N/A scf_service_get_pg(svc, pgname, pg) != 0)
2N/A goto cleanup;
2N/A
2N/A err = scf_pg_delete(pg);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_delete: delete %s\n",
2N/A err == 0 ? "worked" : "failed");
2N/A#endif
2N/A
2N/Acleanup:
2N/A if (err != 0)
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to delete pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A scf_pg_destroy(pg);
2N/A scf_service_destroy(svc);
2N/A if (h) {
2N/A (void) scf_handle_unbind(h);
2N/A scf_handle_destroy(h);
2N/A }
2N/A free(pgname);
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * set_pg_value() - write a value out to SMF
2N/A *
2N/A * Returns 0 on success and -1 on failure, usually setting scf_error.
2N/A * A caller may print error diagnosis with scf_strerror().
2N/A */
2N/Astatic int
2N/Aset_pg_value(scf_handle_t *h, scf_propertygroup_t *pg,
2N/A char *propname, char *propvalue)
2N/A{
2N/A scf_transaction_t *tran = NULL;
2N/A scf_transaction_entry_t *entry = NULL;
2N/A scf_property_t *prop = NULL;
2N/A scf_value_t *value = NULL;
2N/A boolean_t new;
2N/A int ret = -1;
2N/A
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "set_pg_value: setting %s=%s\n", propname, propvalue);
2N/A#endif
2N/A do {
2N/A if ((tran = scf_transaction_create(h)) == NULL ||
2N/A (entry = scf_entry_create(h)) == NULL ||
2N/A (prop = scf_property_create(h)) == NULL ||
2N/A (value = scf_value_create(h)) == NULL)
2N/A return (-1);
2N/A
2N/A new = (scf_pg_get_property(pg, propname, prop) != 0);
2N/A scf_property_destroy(prop);
2N/A
2N/A if (scf_transaction_start(tran, pg) == -1)
2N/A goto cleanup;
2N/A
2N/A if (new) {
2N/A if (scf_transaction_property_new(tran, entry,
2N/A propname, SCF_TYPE_ASTRING) == -1)
2N/A goto cleanup;
2N/A } else {
2N/A if (scf_transaction_property_change(tran, entry,
2N/A propname, SCF_TYPE_ASTRING) == -1)
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (scf_value_set_astring(value, propvalue) == -1 ||
2N/A scf_entry_add_value(entry, value) == -1)
2N/A goto cleanup;
2N/A
2N/A ret = scf_transaction_commit(tran);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "set_pg_value: commit returned %d\n", ret);
2N/A#endif
2N/A if (ret == -1)
2N/A goto cleanup;
2N/A
2N/A if (ret == 0) {
2N/A scf_transaction_reset(tran);
2N/A scf_entry_reset(entry);
2N/A if (scf_pg_update(pg) == -1)
2N/A goto cleanup;
2N/A }
2N/A } while (ret == 0);
2N/A
2N/A if (ret == 1)
2N/A ret = 0;
2N/Acleanup:
2N/A scf_value_destroy(value);
2N/A scf_entry_destroy(entry);
2N/A scf_transaction_destroy(tran);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_smf_update() - update or create the SMF property group entry for
2N/A * host/port.
2N/A *
2N/A * Returns 0 on success and -1 on failure, while also setting scf_error.
2N/A * A caller may print error diagnosis with scf_strerror().
2N/A */
2N/Aint
2N/Afedfs_smf_update(char *host, int port, nsdb_info_t *info)
2N/A{
2N/A char *pgname, sport[10];
2N/A int err = -1;
2N/A scf_handle_t *h = NULL;
2N/A scf_service_t *svc = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A scf_iter_t *iter = NULL;
2N/A
2N/A pgname = fedfs_smf_get_pg(host, port);
2N/A if (pgname == NULL)
2N/A return (-1);
2N/A (void) snprintf(sport, sizeof (sport), "%d", port);
2N/A
2N/A if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
2N/A scf_handle_bind(h) != 0 ||
2N/A (svc = scf_service_create(h)) == NULL ||
2N/A (pg = scf_pg_create(h)) == NULL ||
2N/A (iter = scf_iter_create(h)) == NULL ||
2N/A scf_handle_decode_fmri(h, FEDFS_CLIENT, NULL, svc,
2N/A NULL, NULL, NULL, 0) != 0)
2N/A goto cleanup;
2N/A
2N/A if (scf_service_get_pg(svc, pgname, pg) != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_update: pg not found\n");
2N/A#endif
2N/A if (scf_error() != SCF_ERROR_NOT_FOUND) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_update: for a bad reason\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A if (scf_service_add_pg(svc, pgname, SCF_GROUP_APPLICATION,
2N/A 0, pg) != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_update: can't be created\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A }
2N/A
2N/A if (info->bindpw == NULL)
2N/A info->bindpw = "";
2N/A if (info->sectype == NULL)
2N/A info->sectype = "";
2N/A if (info->certpath == NULL)
2N/A info->certpath = "";
2N/A
2N/A if (set_pg_value(h, pg, "hostname", host) != 0 ||
2N/A set_pg_value(h, pg, "port", sport) != 0 ||
2N/A set_pg_value(h, pg, "nce", info->nce) != 0 ||
2N/A set_pg_value(h, pg, "binddn", info->binddn) != 0 ||
2N/A set_pg_value(h, pg, "bindpw", info->bindpw) != 0 ||
2N/A set_pg_value(h, pg, "sectype", info->sectype) != 0 ||
2N/A set_pg_value(h, pg, "certpath", info->certpath) != 0 ||
2N/A set_pg_value(h, pg, "read_authorization",
2N/A "solaris.smf.read.fedfs") != 0 ||
2N/A set_pg_value(h, pg, "value_authorization",
2N/A "solaris.smf.value.fedfs") != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_smf_update: can't be saved\n");
2N/A#endif
2N/A err = 1;
2N/A } else
2N/A err = 0;
2N/A (void) smf_refresh_instance(FEDFS_CLIENT);
2N/A
2N/Acleanup:
2N/A if (err != 0)
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to add property to pg %s:%s\n",
2N/A pgname, scf_strerror(scf_error()));
2N/A scf_iter_destroy(iter);
2N/A scf_pg_destroy(pg);
2N/A scf_service_destroy(svc);
2N/A if (h) {
2N/A (void) scf_handle_unbind(h);
2N/A scf_handle_destroy(h);
2N/A }
2N/A free(pgname);
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_get_default_host() - get a default host value from env or SMF.
2N/A *
2N/A * On success, returns an allocated string with the name, which the
2N/A * caller must free. On failure, returns NULL.
2N/A */
2N/Achar *
2N/Afedfs_get_default_host()
2N/A{
2N/A char *v = NULL;
2N/A scf_simple_prop_t *prop = NULL;
2N/A
2N/A v = getenv("FEDFS_NSDB_HOST");
2N/A if (v != NULL) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_host: host %s (env)\n", v);
2N/A#endif
2N/A v = strdup(v);
2N/A goto out;
2N/A }
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, "default", "hostname");
2N/A if (!prop)
2N/A goto out;
2N/A v = scf_simple_prop_next_astring(prop);
2N/A if (v != NULL) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_host: host %s (SMF)\n", v);
2N/A#endif
2N/A v = strdup(v);
2N/A }
2N/Aout:
2N/A if (v == NULL || strlen(v) == 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_host: host %s (def)\n", v);
2N/A#endif
2N/A free(v);
2N/A v = strdup("localhost");
2N/A }
2N/A scf_simple_prop_free(prop);
2N/A return (v);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_get_default_port() - get a default port value from env or SMF.
2N/A *
2N/A * On success, returns an allocated string with the name, which the
2N/A * caller must free. On failure, returns NULL.
2N/A */
2N/Achar *
2N/Afedfs_get_default_port()
2N/A{
2N/A char *v = NULL;
2N/A scf_simple_prop_t *prop = NULL;
2N/A
2N/A v = getenv("FEDFS_NSDB_PORT");
2N/A if (v != NULL) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_port: port %s (env)\n", v);
2N/A#endif
2N/A v = strdup(v);
2N/A goto out;
2N/A }
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, "default", "port");
2N/A if (!prop)
2N/A goto out;
2N/A v = scf_simple_prop_next_astring(prop);
2N/A if (v != NULL && strcmp(v, "\"\"") != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_port: port %s (SMF)\n", v);
2N/A#endif
2N/A v = strdup(v);
2N/A }
2N/Aout:
2N/A if (v == NULL || strlen(v) == 0 || strcmp(v, "\"\"") == 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_get_default_port: port %s (def)\n", v);
2N/A#endif
2N/A free(v);
2N/A v = strdup("389");
2N/A }
2N/A scf_simple_prop_free(prop);
2N/A return (v);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_use_loopback() - query SMF "force_loopback" property
2N/A *
2N/A * Returns:
2N/A * -1: inconclusive (likely no such property or FMRI)
2N/A * 0: force_loopback is false
2N/A * 1: force_loopback is true
2N/A */
2N/Aint
2N/Afedfs_use_loopback()
2N/A{
2N/A scf_simple_prop_t *prop = NULL;
2N/A int retval = -1;
2N/A uint8_t *ret;
2N/A
2N/A prop = scf_simple_prop_get(NULL, FEDFS_CLIENT, "default",
2N/A "force_loopback");
2N/A if (!prop) {
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to find force_loopback property:%s\n",
2N/A scf_strerror(scf_error()));
2N/A return (retval);
2N/A }
2N/A ret = scf_simple_prop_next_boolean(prop);
2N/A retval = (*ret != 0);
2N/A scf_simple_prop_free(prop);
2N/A return (retval);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_set_default() - update the SMF default property; properties
2N/A * are hostname and port.
2N/A *
2N/A * Returns 0 on success and -1 on failure, while also setting scf_error.
2N/A * A caller may print error diagnosis with scf_strerror().
2N/A */
2N/Aint
2N/Afedfs_set_default(char *prop, char *value)
2N/A{
2N/A int err = -1;
2N/A scf_handle_t *h = NULL;
2N/A scf_service_t *svc = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A
2N/A if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
2N/A scf_handle_bind(h) != 0 ||
2N/A (svc = scf_service_create(h)) == NULL ||
2N/A (pg = scf_pg_create(h)) == NULL ||
2N/A scf_handle_decode_fmri(h, FEDFS_CLIENT, NULL, svc,
2N/A NULL, NULL, NULL, 0) != 0)
2N/A goto cleanup;
2N/A
2N/A if (scf_service_get_pg(svc, "default", pg) != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_default: pg not found\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_default: setting %s=%s\n", prop, value);
2N/A#endif
2N/A err = 0;
2N/A if (strncmp(prop, "hostname", 8) == 0)
2N/A err = set_pg_value(h, pg, "hostname", value);
2N/A if (strncmp(prop, "port", 4) == 0)
2N/A err = set_pg_value(h, pg, "port", value);
2N/A#ifdef DEBUG
2N/A if (err < 0)
2N/A fprintf(stderr, "fedfs_set_default: can't be saved\n");
2N/A#endif
2N/A (void) smf_refresh_instance(FEDFS_CLIENT);
2N/A
2N/Acleanup:
2N/A scf_pg_destroy(pg);
2N/A scf_service_destroy(svc);
2N/A if (h) {
2N/A (void) scf_handle_unbind(h);
2N/A scf_handle_destroy(h);
2N/A }
2N/A if (err != 0)
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to update default pg: %s\n",
2N/A scf_strerror(scf_error()));
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * fedfs_set_loopback() - update the SMF default/force_loopback property
2N/A *
2N/A * Returns 0 on success and -1 on failure, while also setting scf_error.
2N/A * A caller may print error diagnosis with scf_strerror().
2N/A */
2N/Aint
2N/Afedfs_set_loopback(boolean_t setting)
2N/A{
2N/A int ret = -1;
2N/A scf_handle_t *h = NULL;
2N/A scf_service_t *svc = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A scf_transaction_t *tran = NULL;
2N/A scf_transaction_entry_t *entry = NULL;
2N/A scf_value_t *value = NULL;
2N/A
2N/A if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
2N/A scf_handle_bind(h) != 0 ||
2N/A (svc = scf_service_create(h)) == NULL ||
2N/A (pg = scf_pg_create(h)) == NULL ||
2N/A scf_handle_decode_fmri(h, FEDFS_CLIENT, NULL, svc,
2N/A NULL, NULL, NULL, 0) != 0)
2N/A goto cleanup;
2N/A
2N/A if (scf_service_get_pg(svc, "default", pg) != 0) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: pg not found\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A do {
2N/A if ((tran = scf_transaction_create(h)) == NULL ||
2N/A (entry = scf_entry_create(h)) == NULL ||
2N/A (value = scf_value_create(h)) == NULL) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: no trans\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (scf_transaction_start(tran, pg) == -1) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: no start\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A if (scf_transaction_property_change(tran, entry,
2N/A "force_loopback", SCF_TYPE_BOOLEAN) == -1) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: no change\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A scf_value_set_boolean(value, setting);
2N/A if (scf_entry_add_value(entry, value) == -1) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: no value\n");
2N/A#endif
2N/A goto cleanup;
2N/A }
2N/A
2N/A ret = scf_transaction_commit(tran);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: commit said %d\n", ret);
2N/A#endif
2N/A if (ret == -1)
2N/A goto cleanup;
2N/A
2N/A if (ret == 0) {
2N/A scf_transaction_reset(tran);
2N/A scf_entry_reset(entry);
2N/A if (scf_pg_update(pg) == -1) {
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "fedfs_set_loopback: update\n");
2N/A#endif
2N/A ret = -1;
2N/A goto cleanup;
2N/A }
2N/A }
2N/A } while (ret == 0);
2N/A
2N/A if (ret == 1)
2N/A ret = 0;
2N/A
2N/Acleanup:
2N/A if (ret != 0)
2N/A syslog(LOG_WARNING,
2N/A "FedFS failed to write force_loopback property:%s\n",
2N/A scf_strerror(scf_error()));
2N/A scf_pg_destroy(pg);
2N/A scf_service_destroy(svc);
2N/A if (h) {
2N/A (void) scf_handle_unbind(h);
2N/A scf_handle_destroy(h);
2N/A }
2N/A return (ret);
2N/A}
2N/A
2N/Aint
2N/Asectype_to_int(char *sectype)
2N/A{
2N/A if (strcmp(sectype, "FEDFS_SEC_TLS") == 0)
2N/A return (FEDFS_SEC_TLS);
2N/A else if (strcmp(sectype, "FEDFS_SEC_NONE") == 0)
2N/A return (FEDFS_SEC_NONE);
2N/A else
2N/A return (-1);
2N/A}