1c5c4113dSnw /*
2c5c4113dSnw  * CDDL HEADER START
3c5c4113dSnw  *
4c5c4113dSnw  * The contents of this file are subject to the terms of the
5c5c4113dSnw  * Common Development and Distribution License (the "License").
6c5c4113dSnw  * You may not use this file except in compliance with the License.
7c5c4113dSnw  *
8c5c4113dSnw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw  * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw  * See the License for the specific language governing permissions
11c5c4113dSnw  * and limitations under the License.
12c5c4113dSnw  *
13c5c4113dSnw  * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw  * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw  * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw  * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw  *
19c5c4113dSnw  * CDDL HEADER END
20c5c4113dSnw  */
21c5c4113dSnw /*
22c5c4113dSnw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23c5c4113dSnw  * Use is subject to license terms.
24c5c4113dSnw  */
25c5c4113dSnw 
26c5c4113dSnw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c5c4113dSnw 
28c5c4113dSnw /*
29c5c4113dSnw  * Config routines common to idmap(1M) and idmapd(1M)
30c5c4113dSnw  */
31c5c4113dSnw 
32c5c4113dSnw #include <stdlib.h>
33c5c4113dSnw #include <synch.h>
34c5c4113dSnw #include <assert.h>
35c5c4113dSnw #include <sys/varargs.h>
36c5c4113dSnw #include <sys/systeminfo.h>
37c5c4113dSnw #include <strings.h>
38c5c4113dSnw #include <libintl.h>
39c5c4113dSnw #include <ctype.h>
40c5c4113dSnw #include <errno.h>
41651c0131Sbaban #include "idmapd.h"
42c5c4113dSnw #include <stdio.h>
43c5c4113dSnw #include <stdarg.h>
44*8edda628Sbaban #include <uuid/uuid.h>
45c5c4113dSnw 
46*8edda628Sbaban #define	MACHINE_SID_LEN	(9 + UUID_LEN/4 * 11)
47c5c4113dSnw #define	FMRI_BASE "svc:/system/idmap"
48c5c4113dSnw #define	CONFIG_PG "config"
49c5c4113dSnw #define	GENERAL_PG "general"
50c5c4113dSnw /* initial length of the array for policy options/attributes: */
51c5c4113dSnw #define	DEF_ARRAY_LENGTH 16
52c5c4113dSnw 
53651c0131Sbaban static const char *me = "idmapd";
54c5c4113dSnw 
55*8edda628Sbaban static int
56*8edda628Sbaban generate_machine_sid(char **machine_sid) {
57*8edda628Sbaban 	char *p;
58*8edda628Sbaban 	uuid_t uu;
59*8edda628Sbaban 	int i, j, len, rlen;
60*8edda628Sbaban 	uint32_t rid;
61*8edda628Sbaban 
62*8edda628Sbaban 	/*
63*8edda628Sbaban 	 * Generate and split 128-bit UUID into four 32-bit RIDs
64*8edda628Sbaban 	 * The machine_sid will be of the form S-1-5-N1-N2-N3-N4
65*8edda628Sbaban 	 * We depart from Windows here, which instead of 128
66*8edda628Sbaban 	 * bits worth of random numbers uses 96 bits.
67*8edda628Sbaban 	 */
68*8edda628Sbaban 
69*8edda628Sbaban 	*machine_sid = calloc(1, MACHINE_SID_LEN);
70*8edda628Sbaban 	if (*machine_sid == NULL) {
71*8edda628Sbaban 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
72*8edda628Sbaban 		return (-1);
73*8edda628Sbaban 	}
74*8edda628Sbaban 	(void) strcpy(*machine_sid, "S-1-5-21");
75*8edda628Sbaban 	p = *machine_sid + strlen("S-1-5-21");
76*8edda628Sbaban 	len = MACHINE_SID_LEN - strlen("S-1-5-21");
77*8edda628Sbaban 
78*8edda628Sbaban 	uuid_clear(uu);
79*8edda628Sbaban 	uuid_generate_random(uu);
80*8edda628Sbaban 
81*8edda628Sbaban 	for (i = 0; i < UUID_LEN/4; i++) {
82*8edda628Sbaban 		j = i * 4;
83*8edda628Sbaban 		rid = (uu[j] << 24) | (uu[j + 1] << 16) |
84*8edda628Sbaban 			(uu[j + 2] << 8) | (uu[j + 3]);
85*8edda628Sbaban 		rlen = snprintf(p, len, "-%u", rid);
86*8edda628Sbaban 		p += rlen;
87*8edda628Sbaban 		len -= rlen;
88*8edda628Sbaban 	}
89*8edda628Sbaban 
90*8edda628Sbaban 	return (0);
91*8edda628Sbaban }
92*8edda628Sbaban 
93c5c4113dSnw /* Check if in the case of failure the original value of *val is preserved */
94c5c4113dSnw static int
95c5c4113dSnw get_val_int(idmap_cfg_t *cfg, char *name, void *val, scf_type_t type)
96c5c4113dSnw {
97c5c4113dSnw 	int rc = 0;
98c5c4113dSnw 
99c5c4113dSnw 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
100c5c4113dSnw 	scf_value_t *value = scf_value_create(cfg->handles.main);
101c5c4113dSnw 
102c5c4113dSnw 
103c5c4113dSnw 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
104c5c4113dSnw 	/* this is OK: the property is just undefined */
105c5c4113dSnw 		goto destruction;
106c5c4113dSnw 
107c5c4113dSnw 
108c5c4113dSnw 	if (0 > scf_property_get_value(scf_prop, value))
109c5c4113dSnw 	/* It is still OK when a property doesn't have any value */
110c5c4113dSnw 		goto destruction;
111c5c4113dSnw 
112c5c4113dSnw 	switch (type) {
113c5c4113dSnw 	case SCF_TYPE_BOOLEAN:
114c5c4113dSnw 		rc = scf_value_get_boolean(value, val);
115c5c4113dSnw 		break;
116c5c4113dSnw 	case SCF_TYPE_COUNT:
117c5c4113dSnw 		rc = scf_value_get_count(value, val);
118c5c4113dSnw 		break;
119c5c4113dSnw 	case SCF_TYPE_INTEGER:
120c5c4113dSnw 		rc = scf_value_get_integer(value, val);
121c5c4113dSnw 		break;
122c5c4113dSnw 	default:
123651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: Invalid scf integer type (%d)",
124651c0131Sbaban 		    me, type);
125c5c4113dSnw 		rc = -1;
126c5c4113dSnw 		break;
127c5c4113dSnw 	}
128c5c4113dSnw 
129c5c4113dSnw 
130c5c4113dSnw destruction:
131c5c4113dSnw 	scf_value_destroy(value);
132c5c4113dSnw 	scf_property_destroy(scf_prop);
133c5c4113dSnw 
134c5c4113dSnw 	return (rc);
135c5c4113dSnw }
136c5c4113dSnw 
137c5c4113dSnw static char *
138c5c4113dSnw scf_value2string(scf_value_t *value) {
139c5c4113dSnw 	int rc = -1;
140c5c4113dSnw 	char buf_size = 127;
141c5c4113dSnw 	int length;
142c5c4113dSnw 	char *buf = NULL;
143c5c4113dSnw 	buf = (char *) malloc(sizeof (char) * buf_size);
144c5c4113dSnw 
145c5c4113dSnw 	for (;;) {
146c5c4113dSnw 		length = scf_value_get_astring(value, buf, buf_size);
147c5c4113dSnw 		if (length < 0) {
148c5c4113dSnw 			rc = -1;
149c5c4113dSnw 			goto destruction;
150c5c4113dSnw 		}
151c5c4113dSnw 
152c5c4113dSnw 		if (length == buf_size - 1) {
153c5c4113dSnw 			buf_size *= 2;
154c5c4113dSnw 			buf = (char *)realloc(buf, buf_size * sizeof (char));
155c5c4113dSnw 			if (!buf) {
156651c0131Sbaban 				idmapdlog(LOG_ERR, "%s: Out of memory", me);
157c5c4113dSnw 				rc = -1;
158c5c4113dSnw 				goto destruction;
159c5c4113dSnw 			}
160c5c4113dSnw 		} else {
161c5c4113dSnw 			rc = 0;
162c5c4113dSnw 			break;
163c5c4113dSnw 		}
164c5c4113dSnw 	}
165c5c4113dSnw 
166c5c4113dSnw destruction:
167c5c4113dSnw 	if (rc < 0) {
168c5c4113dSnw 		if (buf)
169c5c4113dSnw 			free(buf);
170c5c4113dSnw 		buf = NULL;
171c5c4113dSnw 	}
172c5c4113dSnw 
173c5c4113dSnw 	return (buf);
174c5c4113dSnw }
175c5c4113dSnw 
176c5c4113dSnw 
177c5c4113dSnw static int
178c5c4113dSnw get_val_astring(idmap_cfg_t *cfg, char *name, char **val)
179c5c4113dSnw {
180c5c4113dSnw 	int rc = 0;
181c5c4113dSnw 
182c5c4113dSnw 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
183c5c4113dSnw 	scf_value_t *value = scf_value_create(cfg->handles.main);
184c5c4113dSnw 
185c5c4113dSnw 
186c5c4113dSnw 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
187c5c4113dSnw 	/* this is OK: the property is just undefined */
188c5c4113dSnw 		goto destruction;
189c5c4113dSnw 
190c5c4113dSnw 	if (0 > scf_property_get_value(scf_prop, value)) {
191651c0131Sbaban 		idmapdlog(LOG_ERR,
192651c0131Sbaban 		    "%s: scf_property_get_value(%s) failed: %s",
193651c0131Sbaban 		    me, name, scf_strerror(scf_error()));
194c5c4113dSnw 		rc = -1;
195c5c4113dSnw 		goto destruction;
196c5c4113dSnw 	}
197c5c4113dSnw 
198c5c4113dSnw 	if (!(*val = scf_value2string(value))) {
199c5c4113dSnw 		rc = -1;
200651c0131Sbaban 		idmapdlog(LOG_ERR,
201651c0131Sbaban 		    "%s: scf_value2string(%s) failed: %s",
202651c0131Sbaban 		    me, name, scf_strerror(scf_error()));
203c5c4113dSnw 	}
204c5c4113dSnw 
205c5c4113dSnw destruction:
206c5c4113dSnw 	scf_value_destroy(value);
207c5c4113dSnw 	scf_property_destroy(scf_prop);
208c5c4113dSnw 
209c5c4113dSnw 	if (rc < 0) {
210c5c4113dSnw 		if (*val)
211c5c4113dSnw 			free(*val);
212c5c4113dSnw 		*val = NULL;
213c5c4113dSnw 	}
214c5c4113dSnw 
215c5c4113dSnw 	return (rc);
216c5c4113dSnw }
217c5c4113dSnw 
218*8edda628Sbaban static int
219*8edda628Sbaban set_val_astring(idmap_cfg_t *cfg, char *name, const char *val)
220*8edda628Sbaban {
221*8edda628Sbaban 	int			rc = 0, i;
222*8edda628Sbaban 	scf_property_t		*scf_prop = NULL;
223*8edda628Sbaban 	scf_value_t		*value = NULL;
224*8edda628Sbaban 	scf_transaction_t	*tx = NULL;
225*8edda628Sbaban 	scf_transaction_entry_t	*ent = NULL;
226*8edda628Sbaban 
227*8edda628Sbaban 	if ((scf_prop = scf_property_create(cfg->handles.main)) == NULL ||
228*8edda628Sbaban 	    (value = scf_value_create(cfg->handles.main)) == NULL ||
229*8edda628Sbaban 	    (tx = scf_transaction_create(cfg->handles.main)) == NULL ||
230*8edda628Sbaban 	    (ent = scf_entry_create(cfg->handles.main)) == NULL) {
231*8edda628Sbaban 		idmapdlog(LOG_ERR, "%s: Unable to set property %s: %s",
232*8edda628Sbaban 		    me, name, scf_strerror(scf_error()));
233*8edda628Sbaban 		rc = -1;
234*8edda628Sbaban 		goto destruction;
235*8edda628Sbaban 	}
236*8edda628Sbaban 
237*8edda628Sbaban 	for (i = 0; i < MAX_TRIES && rc == 0; i++) {
238*8edda628Sbaban 		if (scf_transaction_start(tx, cfg->handles.config_pg) == -1) {
239*8edda628Sbaban 			idmapdlog(LOG_ERR,
240*8edda628Sbaban 			    "%s: scf_transaction_start(%s) failed: %s",
241*8edda628Sbaban 			    me, name, scf_strerror(scf_error()));
242*8edda628Sbaban 			rc = -1;
243*8edda628Sbaban 			goto destruction;
244*8edda628Sbaban 		}
245*8edda628Sbaban 
246*8edda628Sbaban 		rc = scf_transaction_property_new(tx, ent, name,
247*8edda628Sbaban 		    SCF_TYPE_ASTRING);
248*8edda628Sbaban 		if (rc == -1) {
249*8edda628Sbaban 			idmapdlog(LOG_ERR,
250*8edda628Sbaban 			    "%s: scf_transaction_property_new() failed: %s",
251*8edda628Sbaban 			    me, scf_strerror(scf_error()));
252*8edda628Sbaban 			goto destruction;
253*8edda628Sbaban 		}
254*8edda628Sbaban 
255*8edda628Sbaban 		if (scf_value_set_astring(value, val) == -1) {
256*8edda628Sbaban 			idmapdlog(LOG_ERR,
257*8edda628Sbaban 			    "%s: scf_value_set_astring() failed: %s",
258*8edda628Sbaban 			    me, scf_strerror(scf_error()));
259*8edda628Sbaban 			rc = -1;
260*8edda628Sbaban 			goto destruction;
261*8edda628Sbaban 		}
262*8edda628Sbaban 
263*8edda628Sbaban 		if (scf_entry_add_value(ent, value) == -1) {
264*8edda628Sbaban 			idmapdlog(LOG_ERR,
265*8edda628Sbaban 			    "%s: scf_entry_add_value() failed: %s",
266*8edda628Sbaban 			    me, scf_strerror(scf_error()));
267*8edda628Sbaban 			rc = -1;
268*8edda628Sbaban 			goto destruction;
269*8edda628Sbaban 		}
270*8edda628Sbaban 
271*8edda628Sbaban 		rc = scf_transaction_commit(tx);
272*8edda628Sbaban 		if (rc == 0 && i < MAX_TRIES - 1) {
273*8edda628Sbaban 			/*
274*8edda628Sbaban 			 * Property group set in scf_transaction_start()
275*8edda628Sbaban 			 * is not the most recent. Update pg, reset tx and
276*8edda628Sbaban 			 * retry tx.
277*8edda628Sbaban 			 */
278*8edda628Sbaban 			idmapdlog(LOG_WARNING,
279*8edda628Sbaban 			    "%s: scf_transaction_commit(%s) failed - Retry: %s",
280*8edda628Sbaban 			    me, name, scf_strerror(scf_error()));
281*8edda628Sbaban 			if (scf_pg_update(cfg->handles.config_pg) == -1) {
282*8edda628Sbaban 				idmapdlog(LOG_ERR,
283*8edda628Sbaban 				    "%s: scf_pg_update() failed: %s",
284*8edda628Sbaban 				    me, scf_strerror(scf_error()));
285*8edda628Sbaban 				rc = -1;
286*8edda628Sbaban 				goto destruction;
287*8edda628Sbaban 			}
288*8edda628Sbaban 			scf_transaction_reset(tx);
289*8edda628Sbaban 		}
290*8edda628Sbaban 	}
291*8edda628Sbaban 
292*8edda628Sbaban 	/* Log failure message if all retries failed */
293*8edda628Sbaban 	if (rc == 0) {
294*8edda628Sbaban 		idmapdlog(LOG_ERR,
295*8edda628Sbaban 		    "%s: scf_transaction_commit(%s) failed: %s",
296*8edda628Sbaban 		    me, name, scf_strerror(scf_error()));
297*8edda628Sbaban 		rc = -1;
298*8edda628Sbaban 	}
299*8edda628Sbaban 
300*8edda628Sbaban destruction:
301*8edda628Sbaban 	scf_value_destroy(value);
302*8edda628Sbaban 	scf_entry_destroy(ent);
303*8edda628Sbaban 	scf_transaction_destroy(tx);
304*8edda628Sbaban 	scf_property_destroy(scf_prop);
305*8edda628Sbaban 	return (rc);
306*8edda628Sbaban }
307*8edda628Sbaban 
308c5c4113dSnw int
309c5c4113dSnw idmap_cfg_load(idmap_cfg_t *cfg)
310c5c4113dSnw {
311c5c4113dSnw 	int rc = 0;
312c5c4113dSnw 
313c5c4113dSnw 	cfg->pgcfg.list_size_limit = 0;
314c5c4113dSnw 	cfg->pgcfg.mapping_domain = NULL;
315c5c4113dSnw 	cfg->pgcfg.machine_sid = NULL;
316c5c4113dSnw 	cfg->pgcfg.domain_controller = NULL;
317c5c4113dSnw 	cfg->pgcfg.global_catalog = NULL;
318c5c4113dSnw 
319c5c4113dSnw 	if (0 > scf_pg_update(cfg->handles.config_pg)) {
320651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
321651c0131Sbaban 		    me, scf_strerror(scf_error()));
322c5c4113dSnw 		return (-1);
323c5c4113dSnw 	}
324c5c4113dSnw 
325c5c4113dSnw 	if (0 > scf_pg_update(cfg->handles.general_pg)) {
326651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
327651c0131Sbaban 		    me, scf_strerror(scf_error()));
328c5c4113dSnw 		return (-1);
329c5c4113dSnw 	}
330c5c4113dSnw 
331c5c4113dSnw 	rc = get_val_int(cfg, "list_size_limit",
332c5c4113dSnw 	    &cfg->pgcfg.list_size_limit, SCF_TYPE_COUNT);
333c5c4113dSnw 	if (rc != 0)
334c5c4113dSnw 		return (-1);
335c5c4113dSnw 
336c5c4113dSnw 	rc = get_val_astring(cfg, "mapping_domain",
337c5c4113dSnw 	    &cfg->pgcfg.mapping_domain);
338c5c4113dSnw 	if (rc != 0)
339c5c4113dSnw 		return (-1);
340c5c4113dSnw 
341c5c4113dSnw 	/*
342c5c4113dSnw 	 * If there is no mapping_domain in idmap's smf config then
343c5c4113dSnw 	 * set it to the joined domain.
344c5c4113dSnw 	 * Till domain join is implemented, temporarily set it to
345c5c4113dSnw 	 * the system domain for testing purposes.
346c5c4113dSnw 	 */
347c5c4113dSnw 	if (!cfg->pgcfg.mapping_domain) 	{
348c5c4113dSnw 		char test[1];
349c5c4113dSnw 		long dname_size = sysinfo(SI_SRPC_DOMAIN, test, 1);
350c5c4113dSnw 		if (dname_size > 0) {
351c5c4113dSnw 			cfg->pgcfg.mapping_domain =
352c5c4113dSnw 			    (char *)malloc(dname_size * sizeof (char));
353c5c4113dSnw 			dname_size = sysinfo(SI_SRPC_DOMAIN,
354c5c4113dSnw 			    cfg->pgcfg.mapping_domain, dname_size);
355c5c4113dSnw 		}
356c5c4113dSnw 		if (dname_size <= 0) {
357651c0131Sbaban 			idmapdlog(LOG_ERR,
358651c0131Sbaban 			    "%s: unable to get name service domain", me);
359c5c4113dSnw 			if (cfg->pgcfg.mapping_domain)
360c5c4113dSnw 				free(cfg->pgcfg.mapping_domain);
361c5c4113dSnw 			cfg->pgcfg.mapping_domain = NULL;
362c5c4113dSnw 		}
363c5c4113dSnw 	}
364c5c4113dSnw 
365c5c4113dSnw 	rc = get_val_astring(cfg, "machine_sid", &cfg->pgcfg.machine_sid);
366c5c4113dSnw 	if (rc != 0)
367c5c4113dSnw 		return (-1);
368*8edda628Sbaban 	if (cfg->pgcfg.machine_sid == NULL) {
369*8edda628Sbaban 		/* If machine_sid not configured, generate one */
370*8edda628Sbaban 		if (generate_machine_sid(&cfg->pgcfg.machine_sid) < 0)
371*8edda628Sbaban 			return (-1);
372*8edda628Sbaban 		rc = set_val_astring(cfg, "machine_sid",
373*8edda628Sbaban 		    cfg->pgcfg.machine_sid);
374*8edda628Sbaban 		if (rc < 0) {
375*8edda628Sbaban 			free(cfg->pgcfg.machine_sid);
376*8edda628Sbaban 			cfg->pgcfg.machine_sid = NULL;
377*8edda628Sbaban 			return (-1);
378*8edda628Sbaban 		}
379*8edda628Sbaban 	}
380c5c4113dSnw 
381c5c4113dSnw 	rc = get_val_astring(cfg, "global_catalog", &cfg->pgcfg.global_catalog);
382c5c4113dSnw 	if (rc != 0)
383c5c4113dSnw 		return (-1);
384c5c4113dSnw 
385c5c4113dSnw 	rc = get_val_astring(cfg, "domain_controller",
386c5c4113dSnw 	    &cfg->pgcfg.domain_controller);
387c5c4113dSnw 	if (rc != 0)
388c5c4113dSnw 		return (-1);
389c5c4113dSnw 
390c5c4113dSnw 	return (rc);
391c5c4113dSnw }
392c5c4113dSnw 
393651c0131Sbaban /*
394651c0131Sbaban  * Initialize 'cfg'.
395651c0131Sbaban  */
396c5c4113dSnw idmap_cfg_t *
397c5c4113dSnw idmap_cfg_init() {
398c5c4113dSnw 
399c5c4113dSnw 	/* First the smf repository handles: */
400c5c4113dSnw 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
401c5c4113dSnw 	if (!cfg) {
402651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
403c5c4113dSnw 		return (NULL);
404c5c4113dSnw 	}
405c5c4113dSnw 
406c5c4113dSnw 	if (!(cfg->handles.main = scf_handle_create(SCF_VERSION))) {
407651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_create() failed: %s",
408651c0131Sbaban 		    me, scf_strerror(scf_error()));
409c5c4113dSnw 		goto error;
410c5c4113dSnw 	}
411c5c4113dSnw 
412c5c4113dSnw 	if (0 > scf_handle_bind(cfg->handles.main)) {
413651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_bind() failed: %s",
414651c0131Sbaban 		    me, scf_strerror(scf_error()));
415c5c4113dSnw 		goto error;
416c5c4113dSnw 	}
417c5c4113dSnw 
418c5c4113dSnw 	if (!(cfg->handles.service = scf_service_create(cfg->handles.main)) ||
419c5c4113dSnw 	    !(cfg->handles.instance = scf_instance_create(cfg->handles.main)) ||
420c5c4113dSnw 	    !(cfg->handles.config_pg = scf_pg_create(cfg->handles.main)) ||
421c5c4113dSnw 	    !(cfg->handles.general_pg = scf_pg_create(cfg->handles.main))) {
422651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf handle creation failed: %s",
423651c0131Sbaban 		    me, scf_strerror(scf_error()));
424c5c4113dSnw 		goto error;
425c5c4113dSnw 	}
426c5c4113dSnw 
427c5c4113dSnw 	if (0 > scf_handle_decode_fmri(cfg->handles.main,
428c5c4113dSnw 		FMRI_BASE "/:properties/" CONFIG_PG,
429c5c4113dSnw 		NULL,				/* scope */
430c5c4113dSnw 		cfg->handles.service,		/* service */
431c5c4113dSnw 		cfg->handles.instance,		/* instance */
432c5c4113dSnw 		cfg->handles.config_pg,		/* pg */
433c5c4113dSnw 		NULL,				/* prop */
434c5c4113dSnw 		SCF_DECODE_FMRI_EXACT)) {
435651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_handle_decode_fmri() failed: %s",
436651c0131Sbaban 		    me, scf_strerror(scf_error()));
437c5c4113dSnw 		goto error;
438c5c4113dSnw 
439c5c4113dSnw 	}
440c5c4113dSnw 
441c5c4113dSnw 	if (0 > scf_service_get_pg(cfg->handles.service,
442c5c4113dSnw 		GENERAL_PG, cfg->handles.general_pg)) {
443651c0131Sbaban 		idmapdlog(LOG_ERR, "%s: scf_service_get_pg() failed: %s",
444651c0131Sbaban 		    me, scf_strerror(scf_error()));
445c5c4113dSnw 		goto error;
446c5c4113dSnw 	}
447c5c4113dSnw 
448c5c4113dSnw 	return (cfg);
449c5c4113dSnw 
450c5c4113dSnw error:
451c5c4113dSnw 	(void) idmap_cfg_fini(cfg);
452c5c4113dSnw 	return (NULL);
453c5c4113dSnw }
454c5c4113dSnw 
455c5c4113dSnw /* ARGSUSED */
456c5c4113dSnw static void
457c5c4113dSnw idmap_pgcfg_fini(idmap_pg_config_t *pgcfg) {
458c5c4113dSnw 	if (pgcfg->mapping_domain)
459c5c4113dSnw 		free(pgcfg->mapping_domain);
460c5c4113dSnw 	if (pgcfg->machine_sid)
461c5c4113dSnw 		free(pgcfg->mapping_domain);
462c5c4113dSnw 	if (pgcfg->global_catalog)
463c5c4113dSnw 		free(pgcfg->global_catalog);
464c5c4113dSnw 	if (pgcfg->domain_controller)
465c5c4113dSnw 		free(pgcfg->domain_controller);
466c5c4113dSnw }
467c5c4113dSnw 
468c5c4113dSnw int
469c5c4113dSnw idmap_cfg_fini(idmap_cfg_t *cfg)
470c5c4113dSnw {
471c5c4113dSnw 	idmap_pgcfg_fini(&cfg->pgcfg);
472c5c4113dSnw 
473c5c4113dSnw 	scf_pg_destroy(cfg->handles.config_pg);
474c5c4113dSnw 	scf_pg_destroy(cfg->handles.general_pg);
475c5c4113dSnw 	scf_instance_destroy(cfg->handles.instance);
476c5c4113dSnw 	scf_service_destroy(cfg->handles.service);
477c5c4113dSnw 	scf_handle_destroy(cfg->handles.main);
478c5c4113dSnw 	free(cfg);
479c5c4113dSnw 
480c5c4113dSnw 	return (0);
481c5c4113dSnw }
482