xref: /titanic_50/usr/src/cmd/krb5/kwarn/kwarnd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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