idmap_config.c revision c8e261054d98729a8718903716b9b8a512d8b693
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Config routines common to idmap(1M) and idmapd(1M)
*/
#include <stdlib.h>
#include <strings.h>
#include <libintl.h>
#include <ctype.h>
#include <errno.h>
#include "idmapd.h"
#include <stdio.h>
#include <stdarg.h>
#include <pthread.h>
#include <port.h>
#include "addisc.h"
#define CONFIG_PG "config"
#define GENERAL_PG "general"
/* initial length of the array for policy options/attributes: */
#define DEF_ARRAY_LENGTH 16
/*LINTLIBRARY*/
static const char *me = "idmapd";
static pthread_t update_thread_handle = 0;
int hup_ev_port = -1;
extern int hupped;
static int
generate_machine_sid(char **machine_sid) {
char *p;
/*
* Generate and split 128-bit UUID into four 32-bit RIDs
* The machine_sid will be of the form S-1-5-N1-N2-N3-N4
* We depart from Windows here, which instead of 128
* bits worth of random numbers uses 96 bits.
*/
if (*machine_sid == NULL) {
return (-1);
}
uuid_clear(uu);
for (i = 0; i < UUID_LEN/4; i++) {
j = i * 4;
p += rlen;
}
return (0);
}
/* Check if in the case of failure the original value of *val is preserved */
static int
{
int rc = 0;
/* this is OK: the property is just undefined */
goto destruction;
/* It is still OK when a property doesn't have any value */
goto destruction;
switch (type) {
case SCF_TYPE_BOOLEAN:
break;
case SCF_TYPE_COUNT:
break;
case SCF_TYPE_INTEGER:
break;
default:
rc = -1;
break;
}
return (rc);
}
static char *
int rc = -1;
char buf_size = 127;
int length;
for (;;) {
if (length < 0) {
rc = -1;
goto destruction;
}
buf_size *= 2;
if (!buf) {
rc = -1;
goto destruction;
}
} else {
rc = 0;
break;
}
}
if (rc < 0) {
if (buf)
}
return (buf);
}
static int
ad_disc_ds_t **val)
{
int len;
int count = 0;
int rc = 0;
/* this is OK: the property is just undefined */
goto destruction;
"%s: scf_iter_property_values(%s) failed: %s",
rc = -1;
goto destruction;
}
/* Workaround scf bugs -- can't reset an iteration */
if (count == 0) {
count++;
if (count == 0)
/* no values */
goto destruction;
goto restart;
}
goto destruction;
}
count = 0;
rc = -1;
goto destruction;
}
*portstr++ = '\0';
(char **)NULL, 10);
}
/* Ignore this server if the hostname is too long */
count++;
}
if (rc < 0) {
if (servers)
}
return (rc);
}
static int
{
int rc = 0;
/* this is OK: the property is just undefined */
goto destruction;
"%s: scf_property_get_value(%s) failed: %s",
rc = -1;
goto destruction;
}
rc = -1;
if (rc < 0) {
if (*val)
}
return (rc);
}
static int
{
int rc = 0, i;
rc = -1;
goto destruction;
}
"%s: scf_transaction_start(%s) failed: %s",
rc = -1;
goto destruction;
}
if (rc == -1) {
"%s: scf_transaction_property_new() failed: %s",
goto destruction;
}
"%s: scf_value_set_astring() failed: %s",
rc = -1;
goto destruction;
}
"%s: scf_entry_add_value() failed: %s",
rc = -1;
goto destruction;
}
/*
* Property group set in scf_transaction_start()
* is not the most recent. Update pg, reset tx and
* retry tx.
*/
"%s: scf_transaction_commit(%s) failed - Retry: %s",
"%s: scf_pg_update() failed: %s",
rc = -1;
goto destruction;
}
}
}
/* Log failure message if all retries failed */
if (rc == 0) {
"%s: scf_transaction_commit(%s) failed: %s",
rc = -1;
}
return (rc);
}
static int
{
return (FALSE);
return (FALSE);
}
return (TRUE);
}
static int
{
int i;
return (FALSE);
return (FALSE);
}
if (*value)
return (TRUE);
}
/*
* Returns 1 if SIGHUP has been received (see hup_handler elsewhere), 0
* otherwise. Uses an event port and a user-defined event.
*
* Note that port_get() does not update its timeout argument when EINTR,
* unlike nanosleep(). We probably don't care very much here because
* the only signals we expect are ones that will lead to idmapd dying or
* SIGHUP, and we intend for the latter to cause this function to
* return. But if we did care then we could always use a timer event
* (see timer_create(3RT)) and associate it with the same event port,
* then we could get accurate waiting regardless of EINTRs.
*/
static
int
{
int retries = 1;
/*
* If event port creation failed earlier and fails now then we
* simply don't learn about SIGHUPs in a timely fashion. No big
* deal
*/
return (0);
}
switch (errno) {
case EBADF:
case EBADFD:
hup_ev_port = -1;
break;
case EINVAL:
/*
* Shouldn't happen, except, perhaps, near the
* end of time
*/
if (retries-- > 0)
goto retry;
/* NOTREACHED */
break;
case EINTR:
if (!hupped)
goto retry;
break;
case ETIME:
/* Timeout */
break;
default:
/* EFAULT */
break;
}
}
/*
* We only have one event that we care about, a user event, so
* there's nothing to check or clean up about pe.
*
* If we get here it's either because we had a SIGHUP and a user
* event was sent to our port, or because the port_get() timed
* out (or even both!).
*/
if (hupped) {
hupped = 0;
/* Got SIGHUP, re-read SMF config */
(void) idmapdlog(LOG_NOTICE,
"idmapd: Failed to reload config");
return (1);
}
return (0);
}
void *
idmap_cfg_update_thread(void *arg)
{
int ttl;
int changed;
for (;;) {
if (ttl > MAX_CHECK_TIME)
if (ttl == -1) {
} else if (ttl > SUBNET_CHECK_TIME) {
/*
* We really ought to just monitor
* network interfaces with a PF_ROUTE
* socket... This crude method of
* discovering subnet changes will do
* for now. Though might even not want
* to bother: subnet changes leading to
* sitename changes ought never happen,
* and requiring a refresh when they do
* to be able to refresh us).
*/
if (wait_for_ttl(&delay)) {
/* Got SIGHUP, re-discover */
ttl = 0;
break;
}
ttl -= SUBNET_CHECK_TIME;
if (ad_disc_SubnetChanged(ad_ctx))
break;
} else {
if (wait_for_ttl(&delay))
ttl = 0;
}
}
/*
* Load configuration data into a private copy.
*
* The fixed values (i.e., from SMF) have already been
* set in AD auto discovery, so if all values have been
* set in SMF and they haven't been changed or the
* service been refreshed then the rest of this loop's
* body is one big no-op.
*/
"%s: unable to discover Default Domain", me);
}
"%s: unable to discover Domain Name", me);
}
"%s: unable to discover Domain Controller", me);
}
"%s: unable to discover Forest Name", me);
}
"%s: unable to discover Site Name", me);
}
"%s: unable to discover Global Catalog", me);
}
"domain and forest names nor domain controllers "
"and global catalog servers", me);
continue;
}
/*
* Update the live configuration
*/
}
/*
* If default_domain came from SMF then we must not
* auto-discover it.
*/
/*
* either the default domain or the global
* catalog server list changed.
*/
if (changed) {
(void) reload_ad();
}
}
/*NOTREACHED*/
return (NULL);
}
int
{
/* Don't check for failure -- see wait_for_ttl() */
hup_ev_port = port_create();
if (errno == 0)
return (0);
else
return (-1);
}
int
{
int rc = 0;
pgcfg->list_size_limit = 0;
rc = -1;
goto exit;
}
rc = -1;
goto exit;
}
if (rc != 0) {
rc = -1;
goto exit;
}
&pgcfg->domain_name);
if (rc != 0) {
rc = -1;
goto exit;
}
&pgcfg->default_domain);
if (rc != 0) {
rc = -1;
goto exit;
}
if (rc != 0) {
rc = -1;
goto exit;
}
/*
* We treat default_domain as having been specified in SMF IFF
* either (the config/default_domain property was set) or (the
* old, obsolete, never documented config/mapping_domain
* property was set and the new config/domain_name property was
* not set).
*/
"%s: Ignoring obsolete, undocumented "
"config/mapping_domain property", me);
}
"%s: The config/mapping_domain property is "
"obsolete; support for it will be removed, "
"please use config/default_domain instead",
me);
}
}
if (rc != 0) {
rc = -1;
goto exit;
}
/* If machine_sid not configured, generate one */
rc = -1;
goto exit;
}
pgcfg->machine_sid);
if (rc < 0) {
rc = -1;
goto exit;
}
}
if (rc != 0) {
rc = -1;
goto exit;
}
if (rc != 0) {
rc = -1;
goto exit;
}
if (rc != 0) {
rc = -1;
goto exit;
}
&pgcfg->global_catalog);
if (rc != 0) {
rc = -1;
goto exit;
}
/*
* Auto Discover the rest
*/
"%s: unable to discover Default Domain", me);
}
}
"%s: unable to discover Domain Name", me);
}
}
"%s: unable to discover Domain Controller", me);
}
}
"%s: unable to discover Forest Name", me);
}
}
"%s: unable to discover Site Name", me);
}
}
"%s: unable to discover Global Catalog", me);
}
}
exit:
return (rc);
}
/*
* Initialize 'cfg'.
*/
idmap_cfg_init() {
/* First the smf repository handles: */
if (!cfg) {
return (NULL);
}
goto error;
}
goto error;
}
goto error;
}
NULL, /* scope */
NULL, /* prop */
SCF_DECODE_FMRI_EXACT) < 0) {
goto error;
}
goto error;
}
/* Initialize AD Auto Discovery context */
goto error;
return (cfg);
(void) idmap_cfg_fini(cfg);
return (NULL);
}
void
if (pgcfg->default_domain) {
}
if (pgcfg->domain_name) {
}
if (pgcfg->machine_sid) {
}
if (pgcfg->domain_controller) {
}
if (pgcfg->forest_name) {
}
}
if (pgcfg->global_catalog) {
}
}
int
{
return (0);
}