idmapd.c revision bcced03bbdd2d55d8573d1da7b39a496f30d68cb
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* main() of idmapd(1M)
*/
#include "idmapd.h"
#include <atomic.h>
#include <signal.h>
#include <string.h> /* strcmp */
#include <unistd.h> /* setsid */
#include <memory.h>
#include <stropts.h>
#include <netconfig.h>
#include <syslog.h>
#include <priv_utils.h> /* privileges */
#include <locale.h>
#include <sys/systeminfo.h>
#include <errno.h>
#include <zone.h>
#include <door.h>
#include <port.h>
#include <sys/resource.h>
#include <pthread.h>
static void term_handler(int);
static void init_idmapd();
static void fini_idmapd();
#define _RPCSVC_CLOSEDOWN 120
int _rpcsvccount = 0; /* Number of requests being serviced */
static int degraded = 0; /* whether the FMRI has been marked degraded */
static uint32_t num_threads = 0;
static pthread_key_t create_threads_key;
/*
* Server door thread start routine.
*
* Set a TSD value to the door thread. This enables the destructor to
* be called when this thread exits.
*/
/*ARGSUSED*/
static void *
idmapd_door_thread_start(void *arg)
{
static void *value = 0;
/*
* Disable cancellation to avoid memory leaks from not running
* the thread cleanup code.
*/
/* make lint happy */
return (NULL);
}
/*
* Server door threads creation
*/
/*ARGSUSED*/
static void
{
int num;
"thread creation refused - %d threads currently active",
num - 1);
return;
}
"created thread ID %d - %d threads currently active",
}
/*
* Server door thread cleanup
*/
/*ARGSUSED*/
static void
idmapd_door_thread_cleanup(void *arg)
{
int num;
"exiting thread ID %d - %d threads currently active",
pthread_self(), num);
}
/*
* This is needed for mech_krb5 -- we run as daemon, yes, but we want
* mech_krb5 to think we're root so it can get host/nodename.fqdn
* tickets for us so we can authenticate to AD as the machine account
* that we are. For more details look at the entry point in mech_krb5
* corresponding to gss_init_sec_context().
*
* As a side effect of faking our effective UID to mech_krb5 we will use
* another process then we won't have access to it: we run as daemon and
* keep PRIV_FILE_DAC_READ, which is insufficient to share the ccache
* to avoid this issue; see main().
*
* someday we'll have extensions to libldap to pass those through to
* libsasl. Until then this interposer will have to do.
*
* Also, we have to tell lint to shut up: it thinks app_krb5_user_uid()
* is defined but not used.
*/
/*LINTLIBRARY*/
app_krb5_user_uid(void)
{
return (0);
}
/*ARGSUSED*/
static void
term_handler(int sig)
{
fini_idmapd();
_exit(0);
}
/*ARGSUSED*/
static void
usr1_handler(int sig)
{
}
static int pipe_fd = -1;
static void
daemonize_ready(void)
{
char data = '\0';
/*
* wake the parent
*/
}
static int
daemonize_start(void)
{
char data;
int status;
int devnull;
int filedes[2];
if (devnull < 0)
return (-1);
return (-1);
return (-1);
if (pid != 0) {
/*
* parent
*/
/* presume success */
_exit(0);
}
status = -1;
else
_exit(-1);
}
/*
* child
*/
(void) setsid();
(void) umask(0077);
return (0);
}
int
{
int c;
switch (c) {
case 'd':
break;
default:
return (SMF_EXIT_ERR_CONFIG);
break;
}
}
/* set locale and domain for internationalization */
(void) textdomain(TEXT_DOMAIN);
"with Trusted Extensions idmapd runs only in the "
"global zone");
exit(1);
}
/*
* Raise the fd limit to max
*/
"Unable to raise RLIMIT_NOFILE to %d",
}
if (daemonize_start() < 0) {
exit(-1);
}
} else
(void) umask(0077);
init_idmapd();
/* signal handlers that should run only after we're initialized */
(char *)NULL) == -1) {
exit(1);
}
/* With doors RPC this just wastes this thread, oh well */
svc_run();
return (0);
}
static void
{
int error;
int connmaxrec = IDMAP_MAX_DOOR_RPC;
/* create directories as root and chown to daemon uid */
exit(1);
exit(1);
/*
* Set KRB5CCNAME in the environment. See app_krb5_user_uid()
* for more details. We blow away the existing one, if there is
* one.
*/
error);
exit(1);
}
if ((error = init_mapping_system()) < 0) {
}
idmapd_door_thread_cleanup)) != 0) {
goto errout;
}
goto errout;
}
goto errout;
}
if (dfd == -1) {
goto errout;
}
goto errout;
}
} else {
}
return;
fini_idmapd();
exit(1);
}
static void
{
}
static
const char *
get_fmri(void)
{
static char buf[60];
char *s;
s = fmri;
if (s != NULL && *s == '\0')
return (NULL);
else if (s != NULL)
return (s);
buf[0] = '\0';
else
return (get_fmri());
}
/*
* Wrappers for smf_degrade/restore_instance()
*
* smf_restore_instance() is too heavy duty to be calling every time we
* have a successful AD name<->SID lookup.
*/
void
{
const char *fmri;
/*
* If the config update thread is in a state where auto-discovery could
* be re-tried, then this will make it try it -- a sort of auto-refresh.
*/
if (poke_discovery)
if (degraded)
return;
"SMB server in workgroup mode, or if you're not running an SMB "
"server, then you can ignore this message", reason);
degraded = 1;
(void) smf_degrade_instance(fmri, 0);
}
void
restore_svc(void)
{
const char *fmri;
if (!degraded)
return;
(void) smf_restore_instance(fmri);
degraded = 0;
}
void
{
}
/*
* We don't want to fill up the logs with useless messages when
* we're degraded, but we still want to log.
*/
if (degraded)
}