xref: /titanic_52/usr/src/cmd/idmap/idmapd/idmap_config.c (revision b48b4ad70157f504f1e9b62203d1cc83a5c03104)
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 "idmap_config.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 #define	IDMAP_CFG_DEBUG 0
51 
52 /* initial length of the array for policy options/attributes: */
53 #define	DEF_ARRAY_LENGTH 16
54 
55 static char errmess_buf [1000] =
56 	"Internal error: idmap configuration has not been initialized";
57 
58 static void
59 errmess(char *format, va_list ap)
60 {
61 /*LINTED: E_SEC_PRINTF_VAR_FMT*/
62 	(void) vsnprintf(errmess_buf, sizeof (errmess_buf), format, ap);
63 	(void) strlcat(errmess_buf, gettext(".\n"), sizeof (errmess_buf));
64 
65 #if IDMAP_CFG_DEBUG
66 	(void) fprintf(stderr, errmess_buf);
67 	fflush(stderr);
68 #endif
69 }
70 
71 
72 static void
73 idmap_error(char *format, ...)
74 {
75 	va_list ap;
76 	va_start(ap, format);
77 	errmess(format, ap);
78 	va_end(ap);
79 }
80 
81 static void
82 idmap_scf_error(char *format, ...)
83 {
84 	const char *scf_message;
85 	char *new_format;
86 	char *sep;
87 	va_list ap;
88 
89 	sep = gettext(": ");
90 	va_start(ap, format);
91 
92 	scf_message = scf_strerror(scf_error());
93 	new_format = (char *) malloc(sizeof (char) *
94 	    (strlen(format) + strlen(scf_message) + strlen(sep) + 1));
95 
96 	(void) strcpy(new_format, format);
97 	(void) strcat(new_format, sep);
98 	(void) strcat(new_format, scf_message);
99 
100 	errmess(new_format, ap);
101 
102 	va_end(ap);
103 	free(new_format);
104 }
105 
106 char *
107 idmap_cfg_error() {
108 	return (errmess_buf);
109 }
110 
111 /* Check if in the case of failure the original value of *val is preserved */
112 static int
113 get_val_int(idmap_cfg_t *cfg, char *name, void *val, scf_type_t type)
114 {
115 	int rc = 0;
116 
117 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
118 	scf_value_t *value = scf_value_create(cfg->handles.main);
119 
120 
121 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
122 	/* this is OK: the property is just undefined */
123 		goto destruction;
124 
125 
126 	if (0 > scf_property_get_value(scf_prop, value))
127 	/* It is still OK when a property doesn't have any value */
128 		goto destruction;
129 
130 	switch (type) {
131 	case SCF_TYPE_BOOLEAN:
132 		rc = scf_value_get_boolean(value, val);
133 		break;
134 	case SCF_TYPE_COUNT:
135 		rc = scf_value_get_count(value, val);
136 		break;
137 	case SCF_TYPE_INTEGER:
138 		rc = scf_value_get_integer(value, val);
139 		break;
140 	default:
141 		idmap_scf_error(gettext("Internal error: invalid int type %d"),
142 		    type);
143 		rc = -1;
144 		break;
145 	}
146 
147 
148 destruction:
149 	scf_value_destroy(value);
150 	scf_property_destroy(scf_prop);
151 
152 	return (rc);
153 }
154 
155 static char *
156 scf_value2string(scf_value_t *value) {
157 	int rc = -1;
158 	char buf_size = 127;
159 	int length;
160 	char *buf = NULL;
161 	buf = (char *) malloc(sizeof (char) * buf_size);
162 
163 	for (;;) {
164 		length = scf_value_get_astring(value, buf, buf_size);
165 		if (length < 0) {
166 			rc = -1;
167 			goto destruction;
168 		}
169 
170 		if (length == buf_size - 1) {
171 			buf_size *= 2;
172 			buf = (char *)realloc(buf, buf_size * sizeof (char));
173 			if (!buf) {
174 				idmap_scf_error(
175 					gettext("Not enough memory"));
176 				rc = -1;
177 				goto destruction;
178 			}
179 		} else {
180 			rc = 0;
181 			break;
182 		}
183 	}
184 
185 destruction:
186 	if (rc < 0) {
187 		if (buf)
188 			free(buf);
189 		buf = NULL;
190 	}
191 
192 	return (buf);
193 }
194 
195 
196 static int
197 get_val_astring(idmap_cfg_t *cfg, char *name, char **val)
198 {
199 	int rc = 0;
200 
201 	scf_property_t *scf_prop = scf_property_create(cfg->handles.main);
202 	scf_value_t *value = scf_value_create(cfg->handles.main);
203 
204 
205 	if (0 > scf_pg_get_property(cfg->handles.config_pg, name, scf_prop))
206 	/* this is OK: the property is just undefined */
207 		goto destruction;
208 
209 	if (0 > scf_property_get_value(scf_prop, value)) {
210 		idmap_scf_error(gettext("Cannot get the astring %s"), name);
211 		rc = -1;
212 		goto destruction;
213 	}
214 
215 	if (!(*val = scf_value2string(value))) {
216 		rc = -1;
217 		idmap_scf_error(gettext("Cannot retrieve the astring %s"),
218 		    name);
219 	}
220 
221 destruction:
222 	scf_value_destroy(value);
223 	scf_property_destroy(scf_prop);
224 
225 	if (rc < 0) {
226 		if (*val)
227 			free(*val);
228 		*val = NULL;
229 	}
230 
231 	return (rc);
232 }
233 
234 int
235 idmap_cfg_load(idmap_cfg_t *cfg)
236 {
237 	int rc = 0;
238 
239 	cfg->pgcfg.list_size_limit = 0;
240 	cfg->pgcfg.mapping_domain = NULL;
241 	cfg->pgcfg.machine_sid = NULL;
242 	cfg->pgcfg.domain_controller = NULL;
243 	cfg->pgcfg.global_catalog = NULL;
244 
245 	if (0 > scf_pg_update(cfg->handles.config_pg)) {
246 		idmap_scf_error(gettext("Error updating config pg"));
247 		return (-1);
248 	}
249 
250 	if (0 > scf_pg_update(cfg->handles.general_pg)) {
251 		idmap_scf_error(gettext("Error updating general pg"));
252 		return (-1);
253 	}
254 
255 	rc = get_val_int(cfg, "list_size_limit",
256 	    &cfg->pgcfg.list_size_limit, SCF_TYPE_COUNT);
257 	if (rc != 0)
258 		return (-1);
259 
260 	rc = get_val_astring(cfg, "mapping_domain",
261 	    &cfg->pgcfg.mapping_domain);
262 	if (rc != 0)
263 		return (-1);
264 
265 	/*
266 	 * TBD:
267 	 * If there is no mapping_domain in idmap's smf config then
268 	 * set it to the joined domain.
269 	 * Till domain join is implemented, temporarily set it to
270 	 * the system domain for testing purposes.
271 	 */
272 	if (!cfg->pgcfg.mapping_domain) 	{
273 		char test[1];
274 		long dname_size = sysinfo(SI_SRPC_DOMAIN, test, 1);
275 		if (dname_size > 0) {
276 			cfg->pgcfg.mapping_domain =
277 			    (char *)malloc(dname_size * sizeof (char));
278 			dname_size = sysinfo(SI_SRPC_DOMAIN,
279 			    cfg->pgcfg.mapping_domain, dname_size);
280 		}
281 		if (dname_size <= 0) {
282 			idmap_scf_error(
283 			    gettext("Error obtaining the default domain"));
284 			if (cfg->pgcfg.mapping_domain)
285 				free(cfg->pgcfg.mapping_domain);
286 			cfg->pgcfg.mapping_domain = NULL;
287 		}
288 	}
289 
290 	rc = get_val_astring(cfg, "machine_sid", &cfg->pgcfg.machine_sid);
291 	if (rc != 0)
292 		return (-1);
293 
294 	rc = get_val_astring(cfg, "global_catalog", &cfg->pgcfg.global_catalog);
295 	if (rc != 0)
296 		return (-1);
297 
298 	rc = get_val_astring(cfg, "domain_controller",
299 	    &cfg->pgcfg.domain_controller);
300 	if (rc != 0)
301 		return (-1);
302 
303 	return (rc);
304 }
305 
306 idmap_cfg_t *
307 idmap_cfg_init() {
308 	/*
309 	 * The following initializes 'cfg'.
310 	 */
311 
312 	/* First the smf repository handles: */
313 	idmap_cfg_t *cfg = calloc(1, sizeof (idmap_cfg_t));
314 	if (!cfg) {
315 		idmap_error(gettext("Not enough memory"));
316 		return (NULL);
317 	}
318 
319 	if (!(cfg->handles.main = scf_handle_create(SCF_VERSION))) {
320 		idmap_scf_error(gettext("SCF handle not created"));
321 		goto error;
322 	}
323 
324 	if (0 > scf_handle_bind(cfg->handles.main)) {
325 		idmap_scf_error(gettext("SCF connection failed"));
326 		goto error;
327 	}
328 
329 	if (!(cfg->handles.service = scf_service_create(cfg->handles.main)) ||
330 	    !(cfg->handles.instance = scf_instance_create(cfg->handles.main)) ||
331 	    !(cfg->handles.config_pg = scf_pg_create(cfg->handles.main)) ||
332 	    !(cfg->handles.general_pg = scf_pg_create(cfg->handles.main))) {
333 		idmap_scf_error(gettext("SCF handle creation failed"));
334 		goto error;
335 	}
336 
337 	if (0 > scf_handle_decode_fmri(cfg->handles.main,
338 		FMRI_BASE "/:properties/" CONFIG_PG,
339 		NULL,				/* scope */
340 		cfg->handles.service,		/* service */
341 		cfg->handles.instance,		/* instance */
342 		cfg->handles.config_pg,		/* pg */
343 		NULL,				/* prop */
344 		SCF_DECODE_FMRI_EXACT)) {
345 		idmap_scf_error(gettext("SCF fmri decoding failed"));
346 		goto error;
347 
348 	}
349 
350 	if (0 > scf_service_get_pg(cfg->handles.service,
351 		GENERAL_PG, cfg->handles.general_pg)) {
352 		idmap_scf_error(gettext("SCF general pg not obtained"));
353 		goto error;
354 	}
355 
356 	return (cfg);
357 
358 error:
359 	(void) idmap_cfg_fini(cfg);
360 	return (NULL);
361 }
362 
363 /* ARGSUSED */
364 static void
365 idmap_pgcfg_fini(idmap_pg_config_t *pgcfg) {
366 	if (pgcfg->mapping_domain)
367 		free(pgcfg->mapping_domain);
368 	if (pgcfg->machine_sid)
369 		free(pgcfg->mapping_domain);
370 	if (pgcfg->global_catalog)
371 		free(pgcfg->global_catalog);
372 	if (pgcfg->domain_controller)
373 		free(pgcfg->domain_controller);
374 }
375 
376 int
377 idmap_cfg_fini(idmap_cfg_t *cfg)
378 {
379 	idmap_pgcfg_fini(&cfg->pgcfg);
380 
381 	scf_pg_destroy(cfg->handles.config_pg);
382 	scf_pg_destroy(cfg->handles.general_pg);
383 	scf_instance_destroy(cfg->handles.instance);
384 	scf_service_destroy(cfg->handles.service);
385 	scf_handle_destroy(cfg->handles.main);
386 	free(cfg);
387 
388 	return (0);
389 }
390