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