17c478bd9Sstevel@tonic-gate /* 2*faebf794Sgtb * CDDL HEADER START 3*faebf794Sgtb * 4*faebf794Sgtb * The contents of this file are subject to the terms of the 5*faebf794Sgtb * Common Development and Distribution License (the "License"). 6*faebf794Sgtb * You may not use this file except in compliance with the License. 7*faebf794Sgtb * 8*faebf794Sgtb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*faebf794Sgtb * or http://www.opensolaris.org/os/licensing. 10*faebf794Sgtb * See the License for the specific language governing permissions 11*faebf794Sgtb * and limitations under the License. 12*faebf794Sgtb * 13*faebf794Sgtb * When distributing Covered Code, include this CDDL HEADER in each 14*faebf794Sgtb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*faebf794Sgtb * If applicable, add the following below this CDDL HEADER, with the 16*faebf794Sgtb * fields enclosed by brackets "[]" replaced with your own identifying 17*faebf794Sgtb * information: Portions Copyright [yyyy] [name of copyright owner] 18*faebf794Sgtb * 19*faebf794Sgtb * CDDL HEADER END 20*faebf794Sgtb */ 21*faebf794Sgtb /* 22*faebf794Sgtb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23814a60b1Sgtb * Use is subject to license terms. 24814a60b1Sgtb */ 25814a60b1Sgtb 26814a60b1Sgtb /* 277c478bd9Sstevel@tonic-gate * Usermode daemon which is responsible for sending kerberos credentials 287c478bd9Sstevel@tonic-gate * expiration warnings to the user, syslog or snmp (eventually), depending 297c478bd9Sstevel@tonic-gate * on how it is configured through /etc/krb5/warn.conf. 307c478bd9Sstevel@tonic-gate * the code in this file was borrowed from gssd.c 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <stdio.h> 367c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 377c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 387c478bd9Sstevel@tonic-gate #include <sys/termios.h> 397c478bd9Sstevel@tonic-gate #include <unistd.h> 407c478bd9Sstevel@tonic-gate #include <sys/resource.h> 417c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 427c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 437c478bd9Sstevel@tonic-gate #include <stdlib.h> 447c478bd9Sstevel@tonic-gate #include <stropts.h> 457c478bd9Sstevel@tonic-gate #include <fcntl.h> 467c478bd9Sstevel@tonic-gate #include <strings.h> 477c478bd9Sstevel@tonic-gate #include <syslog.h> 487c478bd9Sstevel@tonic-gate #include <thread.h> 49*faebf794Sgtb #include <netdb.h> 50*faebf794Sgtb #include <libgen.h> 517c478bd9Sstevel@tonic-gate #include "kwarnd.h" 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #define MAXTHREADS 64 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate int kwarnd_debug = 0; /* enable debugging printfs */ 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate extern void kwarnprog_1(struct svc_req *, register SVCXPRT *); 587c478bd9Sstevel@tonic-gate static void usage(void); 597c478bd9Sstevel@tonic-gate static void detachfromtty(void); 607c478bd9Sstevel@tonic-gate extern int svc_create_local_service(void (*) (), 61*faebf794Sgtb ulong_t, ulong_t, char *, char *); 627c478bd9Sstevel@tonic-gate extern void kwarnd_check_warning_list(void); 637c478bd9Sstevel@tonic-gate extern bool_t loadConfigFile(void); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* following declarations needed in rpcgen-generated code */ 667c478bd9Sstevel@tonic-gate int _rpcpmstart = 0; /* Started by a port monitor ? */ 677c478bd9Sstevel@tonic-gate int _rpcfdtype; /* Whether Stream or Datagram ? */ 687c478bd9Sstevel@tonic-gate int _rpcsvcdirty; /* Still serving ? */ 697c478bd9Sstevel@tonic-gate 70*faebf794Sgtb char myhostname[MAXHOSTNAMELEN] = {0}; 71*faebf794Sgtb char progname[MAXNAMELEN] = {0}; 72*faebf794Sgtb 73*faebf794Sgtb 747c478bd9Sstevel@tonic-gate int 757c478bd9Sstevel@tonic-gate main(argc, argv) 767c478bd9Sstevel@tonic-gate int argc; 777c478bd9Sstevel@tonic-gate char **argv; 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate register SVCXPRT *transp; 807c478bd9Sstevel@tonic-gate extern int optind; 817c478bd9Sstevel@tonic-gate int c; 827c478bd9Sstevel@tonic-gate char mname[FMNAMESZ + 1]; 837c478bd9Sstevel@tonic-gate int rpc_svc_mode = RPC_SVC_MT_AUTO; 847c478bd9Sstevel@tonic-gate extern int _getuid(); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* set locale and domain for internationalization */ 887c478bd9Sstevel@tonic-gate setlocale(LC_ALL, ""); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 917c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 927c478bd9Sstevel@tonic-gate #endif 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate textdomain(TEXT_DOMAIN); 957c478bd9Sstevel@tonic-gate 96*faebf794Sgtb (void) strlcpy(progname, basename(argv[0]), sizeof (progname)); 97*faebf794Sgtb 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * take special note that "_getuid()" is called here. This is necessary 1007c478bd9Sstevel@tonic-gate * since we must fake out the mechanism libraries calls to getuid() 1017c478bd9Sstevel@tonic-gate * with a special routine that is provided as part of kwarnd. However, 1027c478bd9Sstevel@tonic-gate * the call below MUST call the real getuid() to ensure it is running 1037c478bd9Sstevel@tonic-gate * as root. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #ifdef DEBUG 1077c478bd9Sstevel@tonic-gate (void) setuid(0); /* DEBUG: set ruid to root */ 108814a60b1Sgtb #endif /* DEBUG */ 1097c478bd9Sstevel@tonic-gate if (_getuid()) { 1107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1117c478bd9Sstevel@tonic-gate gettext("[%s] must be run as root\n"), argv[0]); 1127c478bd9Sstevel@tonic-gate #ifdef DEBUG 1137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(" warning only\n")); 114814a60b1Sgtb #else /* !DEBUG */ 1157c478bd9Sstevel@tonic-gate exit(1); 116814a60b1Sgtb #endif /* DEBUG */ 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "d")) != -1) 1207c478bd9Sstevel@tonic-gate switch (c) { 1217c478bd9Sstevel@tonic-gate case 'd': 1227c478bd9Sstevel@tonic-gate /* turn on debugging */ 1237c478bd9Sstevel@tonic-gate kwarnd_debug = 1; 1247c478bd9Sstevel@tonic-gate break; 1257c478bd9Sstevel@tonic-gate default: 1267c478bd9Sstevel@tonic-gate usage(); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (optind != argc) { 1307c478bd9Sstevel@tonic-gate usage(); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 133*faebf794Sgtb (void) gethostname(myhostname, sizeof (myhostname)); 134*faebf794Sgtb 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Started by inetd if name of module just below stream 1377c478bd9Sstevel@tonic-gate * head is either a sockmod or timod. 1387c478bd9Sstevel@tonic-gate */ 1397c478bd9Sstevel@tonic-gate if (!ioctl(0, I_LOOK, mname) && 1407c478bd9Sstevel@tonic-gate ((strcmp(mname, "sockmod") == 0) || 1417c478bd9Sstevel@tonic-gate (strcmp(mname, "timod") == 0))) { 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate char *netid; 1447c478bd9Sstevel@tonic-gate struct netconfig *nconf; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate openlog("kwarnd", LOG_PID, LOG_DAEMON); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 1497c478bd9Sstevel@tonic-gate netid = "ticotsord"; 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL) { 1537c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot get transport info")); 1547c478bd9Sstevel@tonic-gate exit(1); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if (strcmp(mname, "sockmod") == 0) { 1587c478bd9Sstevel@tonic-gate if (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, "timod")) { 1597c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1607c478bd9Sstevel@tonic-gate gettext("could not get the " 1617c478bd9Sstevel@tonic-gate "right module")); 1627c478bd9Sstevel@tonic-gate exit(1); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* XXX - is nconf even needed here? */ 1677c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 1687c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle")); 1697c478bd9Sstevel@tonic-gate exit(1); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * We use a NULL nconf because KWARNPROG has already been 1747c478bd9Sstevel@tonic-gate * registered with rpcbind. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate if (!svc_reg(transp, KWARNPROG, KWARNVERS, kwarnprog_1, NULL)) { 1777c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1787c478bd9Sstevel@tonic-gate gettext("unable to register " 1797c478bd9Sstevel@tonic-gate "(KWARNPROG, KWARNVERS)")); 1807c478bd9Sstevel@tonic-gate exit(1); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if (nconf) 1847c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 1857c478bd9Sstevel@tonic-gate } else { 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (!kwarnd_debug) 1887c478bd9Sstevel@tonic-gate detachfromtty(); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate openlog("kwarnd", LOG_PID, LOG_DAEMON); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (svc_create_local_service(kwarnprog_1, KWARNPROG, KWARNVERS, 1937c478bd9Sstevel@tonic-gate "netpath", "kwarnd") == 0) { 1947c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("unable to create service")); 1957c478bd9Sstevel@tonic-gate exit(1); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate if (kwarnd_debug) { 2017c478bd9Sstevel@tonic-gate fprintf(stderr, 2027c478bd9Sstevel@tonic-gate gettext("kwarnd start: \n")); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_IGN); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, 2087c478bd9Sstevel@tonic-gate (void *(*)(void *))kwarnd_check_warning_list, NULL, 2097c478bd9Sstevel@tonic-gate THR_DETACHED | THR_DAEMON | THR_NEW_LWP, 2107c478bd9Sstevel@tonic-gate NULL)) { 2117c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2127c478bd9Sstevel@tonic-gate gettext("unable to create cache_cleanup thread")); 2137c478bd9Sstevel@tonic-gate exit(1); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if (!loadConfigFile()) { 2177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("could not read config file\n")); 2187c478bd9Sstevel@tonic-gate exit(1); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) { 2227c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("unable to set automatic MT mode")); 2237c478bd9Sstevel@tonic-gate exit(1); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate svc_run(); 2277c478bd9Sstevel@tonic-gate abort(); 2287c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2297c478bd9Sstevel@tonic-gate #ifdef lint 2307c478bd9Sstevel@tonic-gate return (1); 2317c478bd9Sstevel@tonic-gate #endif 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate static void 2357c478bd9Sstevel@tonic-gate usage(void) 2367c478bd9Sstevel@tonic-gate { 237*faebf794Sgtb (void) fprintf(stderr, gettext("usage: %s [-d]\n"), progname); 2387c478bd9Sstevel@tonic-gate exit(1); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * detach from tty 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate static void 2467c478bd9Sstevel@tonic-gate detachfromtty(void) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate switch (fork()) { 2497c478bd9Sstevel@tonic-gate case -1: 2507c478bd9Sstevel@tonic-gate perror(gettext("kwarnd: can not fork")); 2517c478bd9Sstevel@tonic-gate exit(1); 2527c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2537c478bd9Sstevel@tonic-gate case 0: 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate default: 2567c478bd9Sstevel@tonic-gate exit(0); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Close existing file descriptors, open "/dev/null" as 2617c478bd9Sstevel@tonic-gate * standard input, output, and error, and detach from 2627c478bd9Sstevel@tonic-gate * controlling terminal. 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate closefrom(0); 2657c478bd9Sstevel@tonic-gate (void) open("/dev/null", O_RDONLY); 2667c478bd9Sstevel@tonic-gate (void) open("/dev/null", O_WRONLY); 2677c478bd9Sstevel@tonic-gate (void) dup(1); 2687c478bd9Sstevel@tonic-gate (void) setsid(); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate kwarnprog_1_freeresult(SVCXPRT *transport, xdrproc_t xdr_res, caddr_t res) 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate xdr_free(xdr_res, res); 2767c478bd9Sstevel@tonic-gate return (1); 2777c478bd9Sstevel@tonic-gate } 278