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