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