/* * Sets string property in current pg */ int smb_smf_set_string_property(smb_scfhandle_t *handle, char *propname, char *valstr) { int ret = SMBC_SMF_OK; scf_value_t *value = NULL; scf_transaction_entry_t *entry = NULL; if (handle == NULL) { return (SMBC_SMF_SYSTEM_ERR); } /* * properties must be set in transactions and don't take * effect until the transaction has been ended/committed. */ value = scf_value_create(handle->scf_handle); entry = scf_entry_create(handle->scf_handle); if (value != NULL && entry != NULL) { if (scf_transaction_property_change(handle->scf_trans, entry, propname, SCF_TYPE_ASTRING) == 0 || scf_transaction_property_new(handle->scf_trans, entry, propname, SCF_TYPE_ASTRING) == 0) { if (scf_value_set_astring(value, valstr) == 0) { if (scf_entry_add_value(entry, value) != 0) { ret = SMBC_SMF_SYSTEM_ERR; scf_value_destroy(value); } /* the value is in the transaction */ value = NULL; } else { /* value couldn't be constructed */ ret = SMBC_SMF_SYSTEM_ERR; } /* the entry is in the transaction */ entry = NULL; } else { ret = SMBC_SMF_SYSTEM_ERR; } } else { ret = SMBC_SMF_SYSTEM_ERR; } if (ret == SMBC_SMF_SYSTEM_ERR) { switch (scf_error()) { case SCF_ERROR_PERMISSION_DENIED: ret = SMBC_SMF_NO_PERMISSION; break; } } /* * cleanup if there were any errors that didn't leave these * values where they would be cleaned up later. */ if (value != NULL) scf_value_destroy(value); if (entry != NULL) scf_entry_destroy(entry); return (ret); }
static void new_property(targ_scf_t *h, tgt_node_t *n) { scf_transaction_entry_t *e = NULL; scf_value_t *v = NULL; scf_type_t type; assert(n != NULL); e = scf_entry_create(h->t_handle); v = scf_value_create(h->t_handle); if (strcmp(n->x_value, "true") == 0 || strcmp(n->x_value, "false") == 0) { type = SCF_TYPE_BOOLEAN; } else if (strcmp(n->x_name, "main") == 0 || strcmp(n->x_name, "radius") == 0) { type = SCF_TYPE_ASTRING; } else if (strncmp(n->x_name, "I_", 2) == 0) { type = SCF_TYPE_ASTRING; } else if (strcmp(n->x_name, XML_ELEMENT_VERS) == 0) { type = SCF_TYPE_ASTRING; } else if (isnumber(n->x_value)) { type = SCF_TYPE_COUNT; } else { type = SCF_TYPE_ASTRING; } scf_transaction_property_new(h->t_trans, e, n->x_name, type); scf_value_set_from_string(v, type, n->x_value); scf_entry_add_value(e, v); }
static void delete_prop(const scf_instance_t *inst, const char *pg, const char *prop) { scf_transaction_t *tx; scf_transaction_entry_t *ent; scf_propertygroup_t *gpg; scf_property_t *eprop; int ret; if ((gpg = scf_pg_create(h)) == NULL || (eprop = scf_property_create(h)) == NULL || (tx = scf_transaction_create(h)) == NULL || (ent = scf_entry_create(h)) == NULL) scfdie(); if (scf_instance_get_pg(inst, pg, gpg) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); uu_die(gettext("Error: \"%s\" property group missing.\n"), pg); } do { if (scf_transaction_start(tx, gpg) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } if (scf_transaction_property_delete(tx, ent, prop) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); uu_die( gettext("Error: \"%s\" property does not exist.\n"), prop); } ret = scf_transaction_commit(tx); if (ret < 0) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } if (ret == 0) { scf_transaction_reset(tx); if (scf_pg_update(gpg) == -1) scfdie(); } } while (ret == 0); (void) scf_entry_destroy(ent); scf_transaction_destroy(tx); scf_property_destroy(eprop); scf_pg_destroy(gpg); }
static int add_new_property(scf_handle_t *handle, const char *prop_name, scf_type_t type, const char *val, scf_transaction_t *tx) { scf_value_t *value = NULL; scf_transaction_entry_t *entry = NULL; int status = FAILURE; entry = scf_entry_create(handle); if (entry == NULL) { KSSL_DEBUG("scf_entry_create failed: %s\n", scf_strerror(scf_error())); goto out; } KSSL_DEBUG("scf_entry_create succeeded\n"); value = scf_value_create(handle); if (value == NULL) { goto out; } KSSL_DEBUG("scf_value_create succeeded\n"); if (scf_transaction_property_new(tx, entry, prop_name, type) != 0) { goto out; } KSSL_DEBUG("scf_transaction_property_new succeeded\n"); if (scf_value_set_from_string(value, type, val) != 0) { goto out; } KSSL_DEBUG("scf_value_set_from_string \'%s\' succeeded\n", val); if (scf_entry_add_value(entry, value) != 0) { KSSL_DEBUG( "scf_entry_add_value failed: %s\n", scf_strerror(scf_error())); goto out; } KSSL_DEBUG("scf_entry_add_value succeeded\n"); status = SUCCESS; out: if (status != SUCCESS) (void) fprintf(stderr, gettext( "Unexpected fatal libscf error: %s. Exiting.\n"), scf_strerror(scf_error())); return (status); }
/* * Delete a property (for properties obsoleted during an upgrade). */ int smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) { scf_transaction_entry_t *entry; int ret = SMBD_SMF_OK; if (handle == NULL) return (SMBD_SMF_SYSTEM_ERR); if (handle->scf_trans == NULL) return (SMBD_SMF_SYSTEM_ERR); /* * properties must be set in transactions and don't take * effect until the transaction has been ended/committed. */ entry = scf_entry_create(handle->scf_handle); if (entry == NULL) { ret = SMBD_SMF_SYSTEM_ERR; goto out; } if (scf_transaction_property_delete(handle->scf_trans, entry, propname) == 0) { /* the entry is in the transaction */ entry = NULL; } else { switch (scf_error()) { case SCF_ERROR_NOT_FOUND: /* Did not exist. We're done. */ ret = SMBD_SMF_OK; goto out; case SCF_ERROR_PERMISSION_DENIED: ret = SMBD_SMF_NO_PERMISSION; goto out; default: ret = SMBD_SMF_SYSTEM_ERR; goto out; } } out: scf_entry_destroy(entry); return (ret); }
static void new_value_list(targ_scf_t *h, tgt_node_t *p) { scf_transaction_entry_t *e = NULL; scf_value_t *v = NULL; tgt_node_t *c; char *name; assert(p != NULL); name = p->x_name; e = scf_entry_create(h->t_handle); scf_transaction_property_new(h->t_trans, e, name, SCF_TYPE_ASTRING); for (c = p->x_child; c; c = c->x_sibling) { v = scf_value_create(h->t_handle); scf_value_set_astring(v, c->x_value); scf_entry_add_value(e, v); } }
/* * Deletes property in current pg */ int smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) { int ret = SMBC_SMF_OK; scf_transaction_entry_t *entry = NULL; if (handle == NULL) { return (SMBC_SMF_SYSTEM_ERR); } /* * properties must be set in transactions and don't take * effect until the transaction has been ended/committed. */ entry = scf_entry_create(handle->scf_handle); if (entry != NULL) { if (scf_transaction_property_delete(handle->scf_trans, entry, propname) != 0) { ret = SMBC_SMF_SYSTEM_ERR; } } else { ret = SMBC_SMF_SYSTEM_ERR; } if (ret == SMBC_SMF_SYSTEM_ERR) { switch (scf_error()) { case SCF_ERROR_PERMISSION_DENIED: ret = SMBC_SMF_NO_PERMISSION; break; } } /* * cleanup if there were any errors that didn't leave these * values where they would be cleaned up later. */ if ((ret != SMBC_SMF_OK) && (entry != NULL)) { scf_entry_destroy(entry); } return (ret); }
/* * store_inetd_hash stores the string hash in inetd's configuration file hash * in the repository. On success, SCF_ERROR_NONE is returned. Otherwise, the * scf_error value is returned. */ scf_error_t store_inetd_hash(const char *hash) { int ret; scf_error_t rval = SCF_ERROR_NONE; scf_handle_t *h; scf_propertygroup_t *pg = NULL; scf_instance_t *inst = NULL; scf_transaction_t *tx = NULL; scf_transaction_entry_t *txent = NULL; scf_property_t *prop = NULL; scf_value_t *val = NULL; if ((h = scf_handle_create(SCF_VERSION)) == NULL || scf_handle_bind(h) == -1) goto error; if ((pg = scf_pg_create(h)) == NULL || (inst = scf_instance_create(h)) == NULL || scf_handle_decode_fmri(h, INETD_INSTANCE_FMRI, NULL, NULL, inst, NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1) goto error; if (scf_instance_get_pg(inst, HASH_PG, pg) == -1) { if (scf_error() != SCF_ERROR_NOT_FOUND || scf_instance_add_pg(inst, HASH_PG, SCF_GROUP_APPLICATION, 0, pg) == -1) goto error; } if ((tx = scf_transaction_create(h)) == NULL || (txent = scf_entry_create(h)) == NULL || (prop = scf_property_create(h)) == NULL || (val = scf_value_create(h)) == NULL) goto error; do { if (scf_transaction_start(tx, pg) == -1) goto error; if (scf_transaction_property_new(tx, txent, HASH_PROP, SCF_TYPE_ASTRING) == -1 && scf_transaction_property_change_type(tx, txent, HASH_PROP, SCF_TYPE_ASTRING) == -1) goto error; if (scf_value_set_astring(val, hash) == -1 || scf_entry_add_value(txent, val) == -1) goto error; if ((ret = scf_transaction_commit(tx)) == -1) goto error; if (ret == 0) { scf_transaction_reset(tx); if (scf_pg_update(pg) == -1) goto error; } } while (ret == 0); goto success; error: rval = scf_error(); success: scf_value_destroy(val); scf_property_destroy(prop); scf_entry_destroy(txent); scf_transaction_destroy(tx); scf_instance_destroy(inst); scf_pg_destroy(pg); scf_handle_destroy(h); return (rval); }
/* * check_auth_modify() checks if a given cred has * the authorization to add/change/remove configuration values. * cred is from the door call. */ Boolean_t check_auth_modify(ucred_t *cred) { targ_scf_t *h = NULL; Boolean_t ret = False; int exit_code = -1; uid_t uid; gid_t gid; pid_t pid; tgt_node_t *n = NULL; scf_transaction_entry_t *ent = NULL; const priv_set_t *eset; pid = fork(); switch (pid) { case 0: /* Child process to check authorization */ uid = ucred_geteuid(cred); if (seteuid(uid) != 0) { syslog(LOG_ERR, "not priviliged\n"); exit(-1); } gid = ucred_getegid(cred); if (setegid(gid) != 0) { syslog(LOG_ERR, "not priviliged\n"); exit(-1); } eset = ucred_getprivset(cred, PRIV_EFFECTIVE); setppriv(PRIV_ON, PRIV_EFFECTIVE, eset); h = mgmt_handle_init(); if (h == NULL) { exit(-1); } if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) { n = tgt_node_alloc("dummy", String, "dummy"); new_property(h, n); tgt_node_free(n); if (mgmt_transaction_end(h) == True) { exit_code = 0; } else { exit_code = -1; } } else { exit_code = -1; } if (exit_code != 0) { mgmt_handle_fini(h); exit(exit_code); } if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) { ent = scf_entry_create(h->t_handle); if (ent) { scf_transaction_property_delete(h->t_trans, ent, "dummy"); } } mgmt_transaction_end(h); mgmt_handle_fini(h); exit(exit_code); break; case -1: /* Fail to fork */ exit(SMF_EXIT_ERR_CONFIG); default: wait(&exit_code); exit_code = exit_code >> 8; if (exit_code == 0) ret = True; else ret = False; break; } return (ret); }
int fs_smf_set_prop(smf_fstype_t fstype, char *prop_name, char *valbuf, char *instance, scf_type_t sctype, char *fmri) { fs_smfhandle_t *phandle = NULL; scf_handle_t *handle; scf_propertygroup_t *pg; scf_property_t *prop; scf_transaction_t *tran = NULL; scf_transaction_entry_t *entry = NULL; scf_instance_t *inst; scf_value_t *val; int valint; int index = 0; int ret = 0; char *p = NULL; char *svcname, srv[MAXPATHLEN]; const char *pgname; /* * 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; prop = phandle->fs_property; inst = phandle->fs_instance; val = phandle->fs_value; tran = scf_transaction_create(handle); entry = scf_entry_create(handle); if (handle == NULL || pg == NULL || prop == NULL || val == NULL|| tran == NULL || entry == NULL || inst == NULL) { ret = SMF_SYSTEM_ERR; goto out; } 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) { uint8_t vint; if (scf_transaction_start(tran, pg) == -1) { ret = scf_error(); goto out; } switch (sctype) { case SCF_TYPE_INTEGER: errno = 0; valint = strtoul(valbuf, NULL, 0); if (errno != 0) { ret = SMF_SYSTEM_ERR; goto out; } if (scf_transaction_property_change(tran, entry, prop_name, SCF_TYPE_INTEGER) == 0) { scf_value_set_integer(val, valint); if (scf_entry_add_value(entry, val) < 0) { ret = scf_error(); goto out; } } break; case SCF_TYPE_ASTRING: if (scf_transaction_property_change(tran, entry, prop_name, SCF_TYPE_ASTRING) == 0) { if (scf_value_set_astring(val, valbuf) == 0) { if (scf_entry_add_value(entry, val) != 0) { ret = scf_error(); goto out; } } else ret = SMF_SYSTEM_ERR; } else ret = SMF_SYSTEM_ERR; break; case SCF_TYPE_BOOLEAN: if (strcmp(valbuf, "1") == 0) { vint = 1; } else if (strcmp(valbuf, "0") == 0) { vint = 0; } else { ret = SMF_SYSTEM_ERR; break; } if (scf_transaction_property_change(tran, entry, prop_name, SCF_TYPE_BOOLEAN) == 0) { scf_value_set_boolean(val, (uint8_t)vint); if (scf_entry_add_value(entry, val) != 0) { ret = scf_error(); goto out; } } else { ret = SMF_SYSTEM_ERR; } break; } if (ret != SMF_SYSTEM_ERR) scf_transaction_commit(tran); } out: if (tran != NULL) scf_transaction_destroy(tran); if (entry != NULL) scf_entry_destroy(entry); fs_smf_fini(phandle); return (ret); }
conerr_t smfu_set_property(char *fmri, char *pgname, char *propname, char *value) { conerr_t err = ce_ok; scf_handle_t *scfhandle = handle_create(); scf_service_t *service = scf_service_create(scfhandle); scf_instance_t *instance = scf_instance_create(scfhandle); scf_propertygroup_t *pg = scf_pg_create(scfhandle); scf_property_t *prop = scf_property_create(scfhandle); scf_value_t *val = scf_value_create(scfhandle); scf_transaction_t *tx = scf_transaction_create(scfhandle); scf_transaction_entry_t *ent = scf_entry_create(scfhandle); scf_type_t type; if (scfhandle == NULL || service == NULL || instance == NULL || pg == NULL || prop == NULL || tx == NULL || ent == NULL || val == NULL) { err = ce_nomem; goto out; } if (scf_handle_decode_fmri(scfhandle, fmri, NULL, service, instance, NULL, NULL, 0) != SCF_SUCCESS) { rad_log(RL_ERROR, "couldn't decode '%s': %s\n", fmri, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } if (scf_instance_get_pg(instance, pgname, pg) != 0 || scf_pg_get_property(pg, propname, prop) != 0 || scf_property_type(prop, &type) != 0) { rad_log(RL_ERROR, "couldn't get property: '%s/%s/%s': %s\n", fmri, pgname, propname, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } top: if (scf_transaction_start(tx, pg) == -1 || scf_transaction_property_change(tx, ent, propname, type) != 0 || scf_value_set_from_string(val, type, value) != 0 || scf_entry_add_value(ent, val) != 0) { rad_log(RL_ERROR, "couldn't set property: '%s/%s/%s': %s\n", fmri, pgname, propname, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } switch (scf_transaction_commit(tx)) { /* success */ case 1: if (smf_refresh_instance(fmri) != 0) { err = maperr(scf_error()); goto out; } break; /* retry */ case 0: if (scf_pg_update(pg) != 0) { err = maperr(scf_error()); goto out; } scf_transaction_reset(tx); goto top; default: err = maperr(scf_error()); goto out; } out: scf_entry_destroy(ent); scf_transaction_destroy(tx); scf_value_destroy(val); scf_property_destroy(prop); scf_pg_destroy(pg); scf_instance_destroy(instance); scf_service_destroy(service); scf_handle_destroy(scfhandle); return (err); }
static void modify_prop(const scf_instance_t *inst, const char *pg, const char *prop, scf_type_t type, void *value) { scf_transaction_t *tx; scf_transaction_entry_t *ent; scf_propertygroup_t *gpg; scf_property_t *eprop; scf_value_t *v; int ret, create = 0; char *fmri; ssize_t max_fmri_len; if ((gpg = scf_pg_create(h)) == NULL || (eprop = scf_property_create(h)) == NULL || (v = scf_value_create(h)) == NULL) scfdie(); /* Get the property group or create it if it is missing. */ if (scf_instance_get_pg(inst, pg, gpg) == -1) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); if ((fmri = malloc(max_fmri_len + 1)) == NULL) uu_die(gettext("Error: Out of memory.\n")); if (scf_instance_to_fmri(inst, fmri, max_fmri_len + 1) < 0) scfdie(); syslog(LOG_NOTICE, "inetadm: Property group \"%s\" missing " "from \"%s\", attempting to add it.\n", pg, fmri); free(fmri); if (scf_instance_add_pg(inst, pg, SCF_GROUP_FRAMEWORK, 0, gpg) == -1) { switch (scf_error()) { case SCF_ERROR_EXISTS: break; case SCF_ERROR_PERMISSION_DENIED: uu_die(gettext("Error: Permission denied.\n")); default: scfdie(); } } } if (scf_pg_get_property(gpg, prop, eprop) == -1) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); create = 1; } if ((tx = scf_transaction_create(h)) == NULL || (ent = scf_entry_create(h)) == NULL) scfdie(); do { uu_list_t *sv_list; if (scf_transaction_start(tx, gpg) == -1) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } /* Modify the property or create it if it is missing */ if (create) ret = scf_transaction_property_new(tx, ent, prop, type); else ret = scf_transaction_property_change_type(tx, ent, prop, type); if (ret == -1) scfdie(); switch (type) { case SCF_TYPE_BOOLEAN: scf_value_set_boolean(v, *(uint8_t *)value); break; case SCF_TYPE_INTEGER: scf_value_set_integer(v, *(int64_t *)value); break; case SCF_TYPE_ASTRING: if (strcmp(prop, PR_PROTO_NAME) == 0) { add_proto_list(ent, h, (char **)value, &sv_list); } else if (scf_value_set_astring(v, value) == -1) { scfdie(); } break; default: uu_die(gettext("Error: Internal inetadm error")); } if ((strcmp(prop, PR_PROTO_NAME) != 0) && (scf_entry_add_value(ent, v) == -1)) scfdie(); ret = scf_transaction_commit(tx); if (ret == -1) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } scf_transaction_reset(tx); if (ret == 0) { if (scf_pg_update(gpg) == -1) scfdie(); } if (strcmp(prop, PR_PROTO_NAME) == 0) remove_proto_list(ent, sv_list); } while (ret == 0); scf_value_destroy(v); scf_entry_destroy(ent); scf_transaction_destroy(tx); scf_property_destroy(eprop); scf_pg_destroy(gpg); }