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