1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2000 by Sun Microsystems, Inc. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * 6*7c478bd9Sstevel@tonic-gate * Usermode daemon which is responsible for sending kerberos credentials 7*7c478bd9Sstevel@tonic-gate * expiration warnings to the user, syslog or snmp (eventually), depending 8*7c478bd9Sstevel@tonic-gate * on how it is configured through /etc/krb5/warn.conf. 9*7c478bd9Sstevel@tonic-gate * the code in this file was borrowed from gssd.c 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #include <stdio.h> 15*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 16*7c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 17*7c478bd9Sstevel@tonic-gate #include <sys/termios.h> 18*7c478bd9Sstevel@tonic-gate #include <unistd.h> 19*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 20*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 21*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 22*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 23*7c478bd9Sstevel@tonic-gate #include <stropts.h> 24*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 25*7c478bd9Sstevel@tonic-gate #include <strings.h> 26*7c478bd9Sstevel@tonic-gate #include <syslog.h> 27*7c478bd9Sstevel@tonic-gate #include <thread.h> 28*7c478bd9Sstevel@tonic-gate #include "kwarnd.h" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #define MAXTHREADS 64 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate int kwarnd_debug = 0; /* enable debugging printfs */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate extern void kwarnprog_1(struct svc_req *, register SVCXPRT *); 35*7c478bd9Sstevel@tonic-gate static void usage(void); 36*7c478bd9Sstevel@tonic-gate static void detachfromtty(void); 37*7c478bd9Sstevel@tonic-gate extern int svc_create_local_service(void (*) (), 38*7c478bd9Sstevel@tonic-gate u_long, u_long, char *, char *); 39*7c478bd9Sstevel@tonic-gate extern void kwarnd_check_warning_list(void); 40*7c478bd9Sstevel@tonic-gate extern bool_t loadConfigFile(void); 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* following declarations needed in rpcgen-generated code */ 43*7c478bd9Sstevel@tonic-gate int _rpcpmstart = 0; /* Started by a port monitor ? */ 44*7c478bd9Sstevel@tonic-gate int _rpcfdtype; /* Whether Stream or Datagram ? */ 45*7c478bd9Sstevel@tonic-gate int _rpcsvcdirty; /* Still serving ? */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate int 48*7c478bd9Sstevel@tonic-gate main(argc, argv) 49*7c478bd9Sstevel@tonic-gate int argc; 50*7c478bd9Sstevel@tonic-gate char **argv; 51*7c478bd9Sstevel@tonic-gate { 52*7c478bd9Sstevel@tonic-gate register SVCXPRT *transp; 53*7c478bd9Sstevel@tonic-gate extern int optind; 54*7c478bd9Sstevel@tonic-gate int c; 55*7c478bd9Sstevel@tonic-gate char mname[FMNAMESZ + 1]; 56*7c478bd9Sstevel@tonic-gate int rpc_svc_mode = RPC_SVC_MT_AUTO; 57*7c478bd9Sstevel@tonic-gate extern int _getuid(); 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* set locale and domain for internationalization */ 61*7c478bd9Sstevel@tonic-gate setlocale(LC_ALL, ""); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 64*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 65*7c478bd9Sstevel@tonic-gate #endif 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate textdomain(TEXT_DOMAIN); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * take special note that "_getuid()" is called here. This is necessary 71*7c478bd9Sstevel@tonic-gate * since we must fake out the mechanism libraries calls to getuid() 72*7c478bd9Sstevel@tonic-gate * with a special routine that is provided as part of kwarnd. However, 73*7c478bd9Sstevel@tonic-gate * the call below MUST call the real getuid() to ensure it is running 74*7c478bd9Sstevel@tonic-gate * as root. 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 78*7c478bd9Sstevel@tonic-gate (void) setuid(0); /* DEBUG: set ruid to root */ 79*7c478bd9Sstevel@tonic-gate #endif DEBUG 80*7c478bd9Sstevel@tonic-gate if (_getuid()) { 81*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 82*7c478bd9Sstevel@tonic-gate gettext("[%s] must be run as root\n"), argv[0]); 83*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 84*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(" warning only\n")); 85*7c478bd9Sstevel@tonic-gate #else !DEBUG 86*7c478bd9Sstevel@tonic-gate exit(1); 87*7c478bd9Sstevel@tonic-gate #endif DEBUG 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "d")) != -1) 91*7c478bd9Sstevel@tonic-gate switch (c) { 92*7c478bd9Sstevel@tonic-gate case 'd': 93*7c478bd9Sstevel@tonic-gate /* turn on debugging */ 94*7c478bd9Sstevel@tonic-gate kwarnd_debug = 1; 95*7c478bd9Sstevel@tonic-gate break; 96*7c478bd9Sstevel@tonic-gate default: 97*7c478bd9Sstevel@tonic-gate usage(); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if (optind != argc) { 101*7c478bd9Sstevel@tonic-gate usage(); 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * Started by inetd if name of module just below stream 106*7c478bd9Sstevel@tonic-gate * head is either a sockmod or timod. 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate if (!ioctl(0, I_LOOK, mname) && 109*7c478bd9Sstevel@tonic-gate ((strcmp(mname, "sockmod") == 0) || 110*7c478bd9Sstevel@tonic-gate (strcmp(mname, "timod") == 0))) { 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate char *netid; 113*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate openlog("kwarnd", LOG_PID, LOG_DAEMON); 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate if ((netid = getenv("NLSPROVIDER")) == NULL) { 118*7c478bd9Sstevel@tonic-gate netid = "ticotsord"; 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate if ((nconf = getnetconfigent(netid)) == NULL) { 122*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot get transport info")); 123*7c478bd9Sstevel@tonic-gate exit(1); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate if (strcmp(mname, "sockmod") == 0) { 127*7c478bd9Sstevel@tonic-gate if (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, "timod")) { 128*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 129*7c478bd9Sstevel@tonic-gate gettext("could not get the " 130*7c478bd9Sstevel@tonic-gate "right module")); 131*7c478bd9Sstevel@tonic-gate exit(1); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* XXX - is nconf even needed here? */ 136*7c478bd9Sstevel@tonic-gate if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { 137*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("cannot create server handle")); 138*7c478bd9Sstevel@tonic-gate exit(1); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * We use a NULL nconf because KWARNPROG has already been 143*7c478bd9Sstevel@tonic-gate * registered with rpcbind. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate if (!svc_reg(transp, KWARNPROG, KWARNVERS, kwarnprog_1, NULL)) { 146*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 147*7c478bd9Sstevel@tonic-gate gettext("unable to register " 148*7c478bd9Sstevel@tonic-gate "(KWARNPROG, KWARNVERS)")); 149*7c478bd9Sstevel@tonic-gate exit(1); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate if (nconf) 153*7c478bd9Sstevel@tonic-gate freenetconfigent(nconf); 154*7c478bd9Sstevel@tonic-gate } else { 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate if (!kwarnd_debug) 157*7c478bd9Sstevel@tonic-gate detachfromtty(); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate openlog("kwarnd", LOG_PID, LOG_DAEMON); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (svc_create_local_service(kwarnprog_1, KWARNPROG, KWARNVERS, 162*7c478bd9Sstevel@tonic-gate "netpath", "kwarnd") == 0) { 163*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("unable to create service")); 164*7c478bd9Sstevel@tonic-gate exit(1); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if (kwarnd_debug) { 170*7c478bd9Sstevel@tonic-gate fprintf(stderr, 171*7c478bd9Sstevel@tonic-gate gettext("kwarnd start: \n")); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_IGN); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, 177*7c478bd9Sstevel@tonic-gate (void *(*)(void *))kwarnd_check_warning_list, NULL, 178*7c478bd9Sstevel@tonic-gate THR_DETACHED | THR_DAEMON | THR_NEW_LWP, 179*7c478bd9Sstevel@tonic-gate NULL)) { 180*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 181*7c478bd9Sstevel@tonic-gate gettext("unable to create cache_cleanup thread")); 182*7c478bd9Sstevel@tonic-gate exit(1); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate if (!loadConfigFile()) { 186*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("could not read config file\n")); 187*7c478bd9Sstevel@tonic-gate exit(1); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) { 191*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("unable to set automatic MT mode")); 192*7c478bd9Sstevel@tonic-gate exit(1); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate svc_run(); 196*7c478bd9Sstevel@tonic-gate abort(); 197*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 198*7c478bd9Sstevel@tonic-gate #ifdef lint 199*7c478bd9Sstevel@tonic-gate return (1); 200*7c478bd9Sstevel@tonic-gate #endif 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static void 204*7c478bd9Sstevel@tonic-gate usage(void) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: kwarnd [-d]\n")); 207*7c478bd9Sstevel@tonic-gate exit(1); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * detach from tty 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate static void 215*7c478bd9Sstevel@tonic-gate detachfromtty(void) 216*7c478bd9Sstevel@tonic-gate { 217*7c478bd9Sstevel@tonic-gate switch (fork()) { 218*7c478bd9Sstevel@tonic-gate case -1: 219*7c478bd9Sstevel@tonic-gate perror(gettext("kwarnd: can not fork")); 220*7c478bd9Sstevel@tonic-gate exit(1); 221*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 222*7c478bd9Sstevel@tonic-gate case 0: 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate default: 225*7c478bd9Sstevel@tonic-gate exit(0); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * Close existing file descriptors, open "/dev/null" as 230*7c478bd9Sstevel@tonic-gate * standard input, output, and error, and detach from 231*7c478bd9Sstevel@tonic-gate * controlling terminal. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate closefrom(0); 234*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", O_RDONLY); 235*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", O_WRONLY); 236*7c478bd9Sstevel@tonic-gate (void) dup(1); 237*7c478bd9Sstevel@tonic-gate (void) setsid(); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 241*7c478bd9Sstevel@tonic-gate int 242*7c478bd9Sstevel@tonic-gate kwarnprog_1_freeresult(SVCXPRT *transport, xdrproc_t xdr_res, caddr_t res) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate xdr_free(xdr_res, res); 245*7c478bd9Sstevel@tonic-gate return (1); 246*7c478bd9Sstevel@tonic-gate } 247