xref: /illumos-gate/usr/src/cmd/idmap/idmapd/idmap_config.c (revision c2aa8c918a0c67f7fd93724a31efac84968fc12c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Config routines common to idmap(1M) and idmapd(1M)
30  */
31 
32 #include <stdlib.h>
33 #include <synch.h>
34 #include <assert.h>
35 #include <sys/varargs.h>
36 #include <sys/systeminfo.h>
37 #include <strings.h>
38 #include <libintl.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include "idmapd.h"
42 #include <stdio.h>
43 #include <stdarg.h>
44 
45 #define	FMRI_BASE "svc:/system/idmap"
46 
47 #define	CONFIG_PG "config"
48 #define	GENERAL_PG "general"
49 
50 /* initial length of the array for policy options/attributes: */
51 #define	DEF_ARRAY_LENGTH 16
52 
53 static const char *me = "idmapd";
54 
55 /* Check if in the case of failure the original value of *val is preserved */
56 static int
57 get_val_int(idmap_cfg_t *cfg, char *name, void *val, scf_type_t type)
58 {
59 	int rc = 0;
60 
61 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
62 	scf_value_t *value = scf_value_create(cfg->handles.main);
63 
64 
65 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
66 	/* this is OK: the property is just undefined */
67 		goto destruction;
68 
69 
70 	if (0 > scf_property_get_value(scf_prop, value))
71 	/* It is still OK when a property doesn't have any value */
72 		goto destruction;
73 
74 	switch (type) {
75 	case SCF_TYPE_BOOLEAN:
76 		rc = scf_value_get_boolean(value, val);
77 		break;
78 	case SCF_TYPE_COUNT:
79 		rc = scf_value_get_count(value, val);
80 		break;
81 	case SCF_TYPE_INTEGER:
82 		rc = scf_value_get_integer(value, val);
83 		break;
84 	default:
85 		idmapdlog(LOG_ERR, "%s: Invalid scf integer type (%d)",
86 		    me, type);
87 		rc = -1;
88 		break;
89 	}
90 
91 
92 destruction:
93 	scf_value_destroy(value);
94 	scf_property_destroy(scf_prop);
95 
96 	return (rc);
97 }
98 
99 static char *
100 scf_value2string(scf_value_t *value) {
101 	int rc = -1;
102 	char buf_size = 127;
103 	int length;
104 	char *buf = NULL;
105 	buf = (char *) malloc(sizeof (char) * buf_size);
106 
107 	for (;;) {
108 		length = scf_value_get_astring(value, buf, buf_size);
109 		if (length < 0) {
110 			rc = -1;
111 			goto destruction;
112 		}
113 
114 		if (length == buf_size - 1) {
115 			buf_size *= 2;
116 			buf = (char *)realloc(buf, buf_size * sizeof (char));
117 			if (!buf) {
118 				idmapdlog(LOG_ERR, "%s: Out of memory", me);
119 				rc = -1;
120 				goto destruction;
121 			}
122 		} else {
123 			rc = 0;
124 			break;
125 		}
126 	}
127 
128 destruction:
129 	if (rc < 0) {
130 		if (buf)
131 			free(buf);
132 		buf = NULL;
133 	}
134 
135 	return (buf);
136 }
137 
138 
139 static int
140 get_val_astring(idmap_cfg_t *cfg, char *name, char **val)
141 {
142 	int rc = 0;
143 
144 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
145 	scf_value_t *value = scf_value_create(cfg->handles.main);
146 
147 
148 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
149 	/* this is OK: the property is just undefined */
150 		goto destruction;
151 
152 	if (0 > scf_property_get_value(scf_prop, value)) {
153 		idmapdlog(LOG_ERR,
154 		    "%s: scf_property_get_value(%s) failed: %s",
155 		    me, name, scf_strerror(scf_error()));
156 		rc = -1;
157 		goto destruction;
158 	}
159 
160 	if (!(*val = scf_value2string(value))) {
161 		rc = -1;
162 		idmapdlog(LOG_ERR,
163 		    "%s: scf_value2string(%s) failed: %s",
164 		    me, name, scf_strerror(scf_error()));
165 	}
166 
167 destruction:
168 	scf_value_destroy(value);
169 	scf_property_destroy(scf_prop);
170 
171 	if (rc < 0) {
172 		if (*val)
173 			free(*val);
174 		*val = NULL;
175 	}
176 
177 	return (rc);
178 }
179 
180 int
181 idmap_cfg_load(idmap_cfg_t *cfg)
182 {
183 	int rc = 0;
184 
185 	cfg->pgcfg.list_size_limit = 0;
186 	cfg->pgcfg.mapping_domain = NULL;
187 	cfg->pgcfg.machine_sid = NULL;
188 	cfg->pgcfg.domain_controller = NULL;
189 	cfg->pgcfg.global_catalog = NULL;
190 
191 	if (0 > scf_pg_update(cfg->handles.config_pg)) {
192 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
193 		    me, scf_strerror(scf_error()));
194 		return (-1);
195 	}
196 
197 	if (0 > scf_pg_update(cfg->handles.general_pg)) {
198 		idmapdlog(LOG_ERR, "%s: scf_pg_update() failed: %s",
199 		    me, scf_strerror(scf_error()));
200 		return (-1);
201 	}
202 
203 	rc = get_val_int(cfg, "list_size_limit",
204 	    &cfg->pgcfg.list_size_limit, SCF_TYPE_COUNT);
205 	if (rc != 0)
206 		return (-1);
207 
208 	rc = get_val_astring(cfg, "mapping_domain",
209 	    &cfg->pgcfg.mapping_domain);
210 	if (rc != 0)
211 		return (-1);
212 
213 	/*
214 	 * If there is no mapping_domain in idmap's smf config then
215 	 * set it to the joined domain.
216 	 * Till domain join is implemented, temporarily set it to
217 	 * the system domain for testing purposes.
218 	 */
219 	if (!cfg->pgcfg.mapping_domain) 	{
220 		char test[1];
221 		long dname_size = sysinfo(SI_SRPC_DOMAIN, test, 1);
222 		if (dname_size > 0) {
223 			cfg->pgcfg.mapping_domain =
224 			    (char *)malloc(dname_size * sizeof (char));
225 			dname_size = sysinfo(SI_SRPC_DOMAIN,
226 			    cfg->pgcfg.mapping_domain, dname_size);
227 		}
228 		if (dname_size <= 0) {
229 			idmapdlog(LOG_ERR,
230 			    "%s: unable to get name service domain", me);
231 			if (cfg->pgcfg.mapping_domain)
232 				free(cfg->pgcfg.mapping_domain);
233 			cfg->pgcfg.mapping_domain = NULL;
234 		}
235 	}
236 
237 	rc = get_val_astring(cfg, "machine_sid", &cfg->pgcfg.machine_sid);
238 	if (rc != 0)
239 		return (-1);
240 
241 	rc = get_val_astring(cfg, "global_catalog", &cfg->pgcfg.global_catalog);
242 	if (rc != 0)
243 		return (-1);
244 
245 	rc = get_val_astring(cfg, "domain_controller",
246 	    &cfg->pgcfg.domain_controller);
247 	if (rc != 0)
248 		return (-1);
249 
250 	return (rc);
251 }
252 
253 /*
254  * Initialize 'cfg'.
255  */
256 idmap_cfg_t *
257 idmap_cfg_init() {
258 
259 	/* First the smf repository handles: */
260 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
261 	if (!cfg) {
262 		idmapdlog(LOG_ERR, "%s: Out of memory", me);
263 		return (NULL);
264 	}
265 
266 	if (!(cfg->handles.main = scf_handle_create(SCF_VERSION))) {
267 		idmapdlog(LOG_ERR, "%s: scf_handle_create() failed: %s",
268 		    me, scf_strerror(scf_error()));
269 		goto error;
270 	}
271 
272 	if (0 > scf_handle_bind(cfg->handles.main)) {
273 		idmapdlog(LOG_ERR, "%s: scf_handle_bind() failed: %s",
274 		    me, scf_strerror(scf_error()));
275 		goto error;
276 	}
277 
278 	if (!(cfg->handles.service = scf_service_create(cfg->handles.main)) ||
279 	    !(cfg->handles.instance = scf_instance_create(cfg->handles.main)) ||
280 	    !(cfg->handles.config_pg = scf_pg_create(cfg->handles.main)) ||
281 	    !(cfg->handles.general_pg = scf_pg_create(cfg->handles.main))) {
282 		idmapdlog(LOG_ERR, "%s: scf handle creation failed: %s",
283 		    me, scf_strerror(scf_error()));
284 		goto error;
285 	}
286 
287 	if (0 > scf_handle_decode_fmri(cfg->handles.main,
288 		FMRI_BASE "/:properties/" CONFIG_PG,
289 		NULL,				/* scope */
290 		cfg->handles.service,		/* service */
291 		cfg->handles.instance,		/* instance */
292 		cfg->handles.config_pg,		/* pg */
293 		NULL,				/* prop */
294 		SCF_DECODE_FMRI_EXACT)) {
295 		idmapdlog(LOG_ERR, "%s: scf_handle_decode_fmri() failed: %s",
296 		    me, scf_strerror(scf_error()));
297 		goto error;
298 
299 	}
300 
301 	if (0 > scf_service_get_pg(cfg->handles.service,
302 		GENERAL_PG, cfg->handles.general_pg)) {
303 		idmapdlog(LOG_ERR, "%s: scf_service_get_pg() failed: %s",
304 		    me, scf_strerror(scf_error()));
305 		goto error;
306 	}
307 
308 	return (cfg);
309 
310 error:
311 	(void) idmap_cfg_fini(cfg);
312 	return (NULL);
313 }
314 
315 /* ARGSUSED */
316 static void
317 idmap_pgcfg_fini(idmap_pg_config_t *pgcfg) {
318 	if (pgcfg->mapping_domain)
319 		free(pgcfg->mapping_domain);
320 	if (pgcfg->machine_sid)
321 		free(pgcfg->mapping_domain);
322 	if (pgcfg->global_catalog)
323 		free(pgcfg->global_catalog);
324 	if (pgcfg->domain_controller)
325 		free(pgcfg->domain_controller);
326 }
327 
328 int
329 idmap_cfg_fini(idmap_cfg_t *cfg)
330 {
331 	idmap_pgcfg_fini(&cfg->pgcfg);
332 
333 	scf_pg_destroy(cfg->handles.config_pg);
334 	scf_pg_destroy(cfg->handles.general_pg);
335 	scf_instance_destroy(cfg->handles.instance);
336 	scf_service_destroy(cfg->handles.service);
337 	scf_handle_destroy(cfg->handles.main);
338 	free(cfg);
339 
340 	return (0);
341 }
342