1*4520Snw141292 /* 2*4520Snw141292 * CDDL HEADER START 3*4520Snw141292 * 4*4520Snw141292 * The contents of this file are subject to the terms of the 5*4520Snw141292 * Common Development and Distribution License (the "License"). 6*4520Snw141292 * You may not use this file except in compliance with the License. 7*4520Snw141292 * 8*4520Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4520Snw141292 * or http://www.opensolaris.org/os/licensing. 10*4520Snw141292 * See the License for the specific language governing permissions 11*4520Snw141292 * and limitations under the License. 12*4520Snw141292 * 13*4520Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 14*4520Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4520Snw141292 * If applicable, add the following below this CDDL HEADER, with the 16*4520Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17*4520Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18*4520Snw141292 * 19*4520Snw141292 * CDDL HEADER END 20*4520Snw141292 */ 21*4520Snw141292 /* 22*4520Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*4520Snw141292 * Use is subject to license terms. 24*4520Snw141292 */ 25*4520Snw141292 26*4520Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 27*4520Snw141292 28*4520Snw141292 /* 29*4520Snw141292 * main() of idmapd(1M) 30*4520Snw141292 */ 31*4520Snw141292 32*4520Snw141292 #include "idmapd.h" 33*4520Snw141292 #include <signal.h> 34*4520Snw141292 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 35*4520Snw141292 #include <string.h> /* strcmp */ 36*4520Snw141292 #include <unistd.h> /* setsid */ 37*4520Snw141292 #include <sys/types.h> 38*4520Snw141292 #include <memory.h> 39*4520Snw141292 #include <stropts.h> 40*4520Snw141292 #include <netconfig.h> 41*4520Snw141292 #include <sys/resource.h> /* rlimit */ 42*4520Snw141292 #include <syslog.h> 43*4520Snw141292 #include <rpcsvc/daemon_utils.h> /* DAEMON_UID and DAEMON_GID */ 44*4520Snw141292 #include <priv_utils.h> /* privileges */ 45*4520Snw141292 #include <locale.h> 46*4520Snw141292 #include <sys/systeminfo.h> 47*4520Snw141292 #include <errno.h> 48*4520Snw141292 #include <sys/wait.h> 49*4520Snw141292 #include <sys/time.h> 50*4520Snw141292 #include <zone.h> 51*4520Snw141292 #include <door.h> 52*4520Snw141292 #include <tsol/label.h> 53*4520Snw141292 #include <sys/resource.h> 54*4520Snw141292 #include <sys/sid.h> 55*4520Snw141292 #include <sys/idmap.h> 56*4520Snw141292 57*4520Snw141292 static void hup_handler(int); 58*4520Snw141292 static void term_handler(int); 59*4520Snw141292 static void init_idmapd(); 60*4520Snw141292 static void fini_idmapd(); 61*4520Snw141292 62*4520Snw141292 #ifndef SIG_PF 63*4520Snw141292 #define SIG_PF void(*)(int) 64*4520Snw141292 #endif 65*4520Snw141292 66*4520Snw141292 #define _RPCSVC_CLOSEDOWN 120 67*4520Snw141292 68*4520Snw141292 int _rpcsvcstate = _IDLE; /* Set when a request is serviced */ 69*4520Snw141292 int _rpcsvccount = 0; /* Number of requests being serviced */ 70*4520Snw141292 mutex_t _svcstate_lock; /* lock for _rpcsvcstate, _rpcsvccount */ 71*4520Snw141292 idmapd_state_t _idmapdstate; 72*4520Snw141292 73*4520Snw141292 SVCXPRT *xprt = NULL; 74*4520Snw141292 75*4520Snw141292 static int dfd = -1; /* our door server fildes, for unregistration */ 76*4520Snw141292 77*4520Snw141292 #ifdef DEBUG 78*4520Snw141292 #define RPC_SVC_FG 79*4520Snw141292 #endif 80*4520Snw141292 81*4520Snw141292 /* 82*4520Snw141292 * This is needed for mech_krb5 -- we run as daemon, yes, but we want 83*4520Snw141292 * mech_krb5 to think we're root. 84*4520Snw141292 * 85*4520Snw141292 * Someday we'll have gss/mech_krb5 extensions for acquiring initiator 86*4520Snw141292 * creds with keytabs/raw keys, and someday we'll have extensions to 87*4520Snw141292 * libsasl to specify creds/name to use on the initiator side, and 88*4520Snw141292 * someday we'll have extensions to libldap to pass those through to 89*4520Snw141292 * libsasl. Until then this interposer will have to do. 90*4520Snw141292 * 91*4520Snw141292 * Also, we have to tell lint to shut up: it thinks app_krb5_user_uid() 92*4520Snw141292 * is defined but not used. 93*4520Snw141292 */ 94*4520Snw141292 /*LINTLIBRARY*/ 95*4520Snw141292 uid_t 96*4520Snw141292 app_krb5_user_uid(void) 97*4520Snw141292 { 98*4520Snw141292 return (0); 99*4520Snw141292 } 100*4520Snw141292 101*4520Snw141292 static void 102*4520Snw141292 set_signal_handlers() { 103*4520Snw141292 (void) sigset(SIGPIPE, SIG_IGN); 104*4520Snw141292 (void) sigset(SIGHUP, hup_handler); 105*4520Snw141292 (void) sigset(SIGTERM, term_handler); 106*4520Snw141292 } 107*4520Snw141292 108*4520Snw141292 /*ARGSUSED*/ 109*4520Snw141292 static void 110*4520Snw141292 hup_handler(int sig) { 111*4520Snw141292 (void) idmapdlog(LOG_INFO, "idmapd: Refreshing config."); 112*4520Snw141292 WRLOCK_CONFIG(); 113*4520Snw141292 (void) idmap_cfg_fini(_idmapdstate.cfg); 114*4520Snw141292 _idmapdstate.cfg = NULL; 115*4520Snw141292 if (load_config() < 0) { 116*4520Snw141292 UNLOCK_CONFIG(); 117*4520Snw141292 (void) idmapdlog(LOG_NOTICE, 118*4520Snw141292 "idmapd: Failed to reload config"); 119*4520Snw141292 term_handler(sig); 120*4520Snw141292 } 121*4520Snw141292 UNLOCK_CONFIG(); 122*4520Snw141292 print_idmapdstate(); 123*4520Snw141292 } 124*4520Snw141292 125*4520Snw141292 /*ARGSUSED*/ 126*4520Snw141292 static void 127*4520Snw141292 term_handler(int sig) { 128*4520Snw141292 (void) idmapdlog(LOG_INFO, "idmapd: Terminating."); 129*4520Snw141292 fini_idmapd(); 130*4520Snw141292 _exit(0); 131*4520Snw141292 } 132*4520Snw141292 133*4520Snw141292 static int pipe_fd = -1; 134*4520Snw141292 135*4520Snw141292 static void 136*4520Snw141292 daemonize_ready(void) { 137*4520Snw141292 char data = '\0'; 138*4520Snw141292 /* 139*4520Snw141292 * wake the parent 140*4520Snw141292 */ 141*4520Snw141292 (void) write(pipe_fd, &data, 1); 142*4520Snw141292 (void) close(pipe_fd); 143*4520Snw141292 } 144*4520Snw141292 145*4520Snw141292 static int 146*4520Snw141292 daemonize_start(void) { 147*4520Snw141292 char data; 148*4520Snw141292 int status; 149*4520Snw141292 int devnull; 150*4520Snw141292 int filedes[2]; 151*4520Snw141292 pid_t pid; 152*4520Snw141292 153*4520Snw141292 devnull = open("/dev/null", O_RDONLY); 154*4520Snw141292 if (devnull < 0) 155*4520Snw141292 return (-1); 156*4520Snw141292 (void) dup2(devnull, 0); 157*4520Snw141292 (void) dup2(2, 1); /* stderr only */ 158*4520Snw141292 if (pipe(filedes) < 0) 159*4520Snw141292 return (-1); 160*4520Snw141292 if ((pid = fork1()) < 0) 161*4520Snw141292 return (-1); 162*4520Snw141292 if (pid != 0) { 163*4520Snw141292 /* 164*4520Snw141292 * parent 165*4520Snw141292 */ 166*4520Snw141292 struct sigaction act; 167*4520Snw141292 act.sa_sigaction = SIG_DFL; 168*4520Snw141292 (void) sigemptyset(&act.sa_mask); 169*4520Snw141292 act.sa_flags = 0; 170*4520Snw141292 (void) sigaction(SIGPIPE, &act, NULL); /* ignore SIGPIPE */ 171*4520Snw141292 (void) close(filedes[1]); 172*4520Snw141292 if (read(filedes[0], &data, 1) == 1) { 173*4520Snw141292 /* presume success */ 174*4520Snw141292 _exit(0); 175*4520Snw141292 } 176*4520Snw141292 status = -1; 177*4520Snw141292 (void) wait4(pid, &status, 0, NULL); 178*4520Snw141292 if (WIFEXITED(status)) 179*4520Snw141292 _exit(WEXITSTATUS(status)); 180*4520Snw141292 else 181*4520Snw141292 _exit(-1); 182*4520Snw141292 } 183*4520Snw141292 184*4520Snw141292 /* 185*4520Snw141292 * child 186*4520Snw141292 */ 187*4520Snw141292 pipe_fd = filedes[1]; 188*4520Snw141292 (void) close(filedes[0]); 189*4520Snw141292 (void) setsid(); 190*4520Snw141292 (void) umask(0077); 191*4520Snw141292 openlog("idmap", LOG_PID, LOG_DAEMON); 192*4520Snw141292 _idmapdstate.daemon_mode = TRUE; 193*4520Snw141292 return (0); 194*4520Snw141292 } 195*4520Snw141292 196*4520Snw141292 197*4520Snw141292 int 198*4520Snw141292 main(int argc, char **argv) 199*4520Snw141292 { 200*4520Snw141292 int c; 201*4520Snw141292 #ifdef RPC_SVC_FG 202*4520Snw141292 bool_t daemonize = FALSE; 203*4520Snw141292 #else 204*4520Snw141292 bool_t daemonize = TRUE; 205*4520Snw141292 #endif 206*4520Snw141292 207*4520Snw141292 while ((c = getopt(argc, argv, "d")) != EOF) { 208*4520Snw141292 switch (c) { 209*4520Snw141292 case 'd': 210*4520Snw141292 daemonize = FALSE; 211*4520Snw141292 break; 212*4520Snw141292 default: 213*4520Snw141292 break; 214*4520Snw141292 } 215*4520Snw141292 } 216*4520Snw141292 217*4520Snw141292 /* set locale and domain for internationalization */ 218*4520Snw141292 (void) setlocale(LC_ALL, ""); 219*4520Snw141292 (void) textdomain(TEXT_DOMAIN); 220*4520Snw141292 221*4520Snw141292 if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID)) { 222*4520Snw141292 (void) idmapdlog(LOG_ERR, 223*4520Snw141292 "idmapd: With TX, idmapd runs only in the global zone"); 224*4520Snw141292 exit(1); 225*4520Snw141292 } 226*4520Snw141292 227*4520Snw141292 /* create directories as root and chown to daemon uid */ 228*4520Snw141292 if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) 229*4520Snw141292 exit(1); 230*4520Snw141292 if (create_directory(IDMAP_CACHEDIR, DAEMON_UID, DAEMON_GID) < 0) 231*4520Snw141292 exit(1); 232*4520Snw141292 233*4520Snw141292 INIT_IDMAPD_STATE(); 234*4520Snw141292 235*4520Snw141292 (void) mutex_init(&_svcstate_lock, USYNC_THREAD, NULL); 236*4520Snw141292 set_signal_handlers(); 237*4520Snw141292 238*4520Snw141292 if (daemonize == TRUE) { 239*4520Snw141292 if (daemonize_start() < 0) { 240*4520Snw141292 (void) perror("idmapd: unable to daemonize"); 241*4520Snw141292 exit(-1); 242*4520Snw141292 } 243*4520Snw141292 } else 244*4520Snw141292 (void) umask(0077); 245*4520Snw141292 246*4520Snw141292 init_idmapd(); 247*4520Snw141292 248*4520Snw141292 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 249*4520Snw141292 DAEMON_UID, DAEMON_GID, 250*4520Snw141292 PRIV_PROC_AUDIT, PRIV_FILE_DAC_READ, 251*4520Snw141292 (char *)NULL) == -1) { 252*4520Snw141292 (void) idmapdlog(LOG_ERR, 253*4520Snw141292 gettext("idmapd: unable to drop privileges")); 254*4520Snw141292 exit(1); 255*4520Snw141292 } 256*4520Snw141292 257*4520Snw141292 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 258*4520Snw141292 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 259*4520Snw141292 260*4520Snw141292 if (daemonize == TRUE) 261*4520Snw141292 daemonize_ready(); 262*4520Snw141292 263*4520Snw141292 /* With doors RPC this just wastes this thread, oh well */ 264*4520Snw141292 svc_run(); 265*4520Snw141292 return (0); 266*4520Snw141292 } 267*4520Snw141292 268*4520Snw141292 static void 269*4520Snw141292 init_idmapd() { 270*4520Snw141292 int error; 271*4520Snw141292 272*4520Snw141292 memset(&_idmapdstate, 0, sizeof (_idmapdstate)); 273*4520Snw141292 274*4520Snw141292 if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname, 275*4520Snw141292 sizeof (_idmapdstate.hostname)) == -1) { 276*4520Snw141292 error = errno; 277*4520Snw141292 idmapdlog(LOG_ERR, 278*4520Snw141292 "idmapd: unable to determine hostname, error: %d", 279*4520Snw141292 error); 280*4520Snw141292 exit(1); 281*4520Snw141292 } 282*4520Snw141292 283*4520Snw141292 if (sysinfo(SI_SRPC_DOMAIN, _idmapdstate.domainname, 284*4520Snw141292 sizeof (_idmapdstate.domainname)) == -1) { 285*4520Snw141292 error = errno; 286*4520Snw141292 idmapdlog(LOG_ERR, 287*4520Snw141292 "idmapd: unable to determine name service domain, error: %d", 288*4520Snw141292 error); 289*4520Snw141292 exit(1); 290*4520Snw141292 } 291*4520Snw141292 292*4520Snw141292 setegid(DAEMON_GID); 293*4520Snw141292 seteuid(DAEMON_UID); 294*4520Snw141292 if (init_mapping_system() < 0) { 295*4520Snw141292 idmapdlog(LOG_ERR, 296*4520Snw141292 "idmapd: unable to initialize mapping system"); 297*4520Snw141292 exit(1); 298*4520Snw141292 } 299*4520Snw141292 seteuid(0); 300*4520Snw141292 setegid(0); 301*4520Snw141292 302*4520Snw141292 xprt = svc_door_create(idmap_prog_1, IDMAP_PROG, IDMAP_V1, 0); 303*4520Snw141292 if (xprt == NULL) { 304*4520Snw141292 idmapdlog(LOG_ERR, 305*4520Snw141292 "idmapd: unable to create door RPC service"); 306*4520Snw141292 goto errout; 307*4520Snw141292 } 308*4520Snw141292 309*4520Snw141292 dfd = xprt->xp_fd; 310*4520Snw141292 311*4520Snw141292 if (dfd == -1) { 312*4520Snw141292 idmapdlog(LOG_ERR, "idmapd: unable to register door"); 313*4520Snw141292 goto errout; 314*4520Snw141292 } 315*4520Snw141292 if ((error = idmap_reg(dfd)) != 0) { 316*4520Snw141292 idmapdlog(LOG_ERR, "idmapd: unable to register door (%s)", 317*4520Snw141292 strerror(error)); 318*4520Snw141292 goto errout; 319*4520Snw141292 } 320*4520Snw141292 321*4520Snw141292 if ((error = allocids(_idmapdstate.new_eph_db, 322*4520Snw141292 8192, &_idmapdstate.next_uid, 323*4520Snw141292 8192, &_idmapdstate.next_gid)) != 0) { 324*4520Snw141292 idmapdlog(LOG_ERR, "idmapd: unable to allocate ephemeral IDs " 325*4520Snw141292 "(%s)", strerror(error)); 326*4520Snw141292 _idmapdstate.next_uid = _idmapdstate.limit_uid = SENTINEL_PID; 327*4520Snw141292 _idmapdstate.next_gid = _idmapdstate.limit_gid = SENTINEL_PID; 328*4520Snw141292 } else { 329*4520Snw141292 _idmapdstate.limit_uid = _idmapdstate.next_uid + 8192; 330*4520Snw141292 _idmapdstate.limit_gid = _idmapdstate.next_gid + 8192; 331*4520Snw141292 } 332*4520Snw141292 333*4520Snw141292 print_idmapdstate(); 334*4520Snw141292 335*4520Snw141292 return; 336*4520Snw141292 337*4520Snw141292 errout: 338*4520Snw141292 fini_idmapd(); 339*4520Snw141292 exit(1); 340*4520Snw141292 } 341*4520Snw141292 342*4520Snw141292 static void 343*4520Snw141292 fini_idmapd() { 344*4520Snw141292 idmap_unreg(dfd); 345*4520Snw141292 fini_mapping_system(); 346*4520Snw141292 if (xprt != NULL) 347*4520Snw141292 svc_destroy(xprt); 348*4520Snw141292 } 349*4520Snw141292 350*4520Snw141292 void 351*4520Snw141292 idmapdlog(int pri, const char *format, ...) { 352*4520Snw141292 va_list args; 353*4520Snw141292 354*4520Snw141292 va_start(args, format); 355*4520Snw141292 if (_idmapdstate.daemon_mode == FALSE) { 356*4520Snw141292 (void) vfprintf(stderr, format, args); 357*4520Snw141292 (void) fprintf(stderr, "\n"); 358*4520Snw141292 } 359*4520Snw141292 (void) vsyslog(pri, format, args); 360*4520Snw141292 va_end(args); 361*4520Snw141292 } 362