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