17c478bd9Sstevel@tonic-gate /*
2faebf794Sgtb  * CDDL HEADER START
3faebf794Sgtb  *
4faebf794Sgtb  * The contents of this file are subject to the terms of the
5faebf794Sgtb  * Common Development and Distribution License (the "License").
6faebf794Sgtb  * You may not use this file except in compliance with the License.
7faebf794Sgtb  *
8faebf794Sgtb  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9faebf794Sgtb  * or http://www.opensolaris.org/os/licensing.
10faebf794Sgtb  * See the License for the specific language governing permissions
11faebf794Sgtb  * and limitations under the License.
12faebf794Sgtb  *
13faebf794Sgtb  * When distributing Covered Code, include this CDDL HEADER in each
14faebf794Sgtb  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15faebf794Sgtb  * If applicable, add the following below this CDDL HEADER, with the
16faebf794Sgtb  * fields enclosed by brackets "[]" replaced with your own identifying
17faebf794Sgtb  * information: Portions Copyright [yyyy] [name of copyright owner]
18faebf794Sgtb  *
19faebf794Sgtb  * CDDL HEADER END
20faebf794Sgtb  */
21faebf794Sgtb /*
2224da5b34Srie  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  *  RPC server procedures for the usermode daemon kwarnd.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <pwd.h>
337c478bd9Sstevel@tonic-gate #include <grp.h>
347c478bd9Sstevel@tonic-gate #include <strings.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
387c478bd9Sstevel@tonic-gate #include "kwarnd.h"
397c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <syslog.h>
427c478bd9Sstevel@tonic-gate #include <poll.h>
437c478bd9Sstevel@tonic-gate #include <utmpx.h>
447c478bd9Sstevel@tonic-gate #include <pwd.h>
457c478bd9Sstevel@tonic-gate #include <strings.h>
467c478bd9Sstevel@tonic-gate #include <ctype.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #include <k5-int.h>
497c478bd9Sstevel@tonic-gate #include <profile/prof_int.h>
507c478bd9Sstevel@tonic-gate #include <com_err.h>
517c478bd9Sstevel@tonic-gate #include <libintl.h>
527c478bd9Sstevel@tonic-gate #include <krb5.h>
537c478bd9Sstevel@tonic-gate 
54faebf794Sgtb extern char progname[];
55faebf794Sgtb 
567c478bd9Sstevel@tonic-gate struct k5_data
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	krb5_context ctx;
597c478bd9Sstevel@tonic-gate 	krb5_ccache cc;
607c478bd9Sstevel@tonic-gate 	krb5_principal me;
617c478bd9Sstevel@tonic-gate 	char *name;
627c478bd9Sstevel@tonic-gate };
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #define	MAIL		"mail"
667c478bd9Sstevel@tonic-gate #define	MAILPATH	"/usr/bin/mail"
677c478bd9Sstevel@tonic-gate #define	DEFAULT_CONFIG	"* terminal 30m"
687c478bd9Sstevel@tonic-gate #define	CONF_FILENAME	"/etc/krb5/warn.conf"
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /* warn.conf info */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate typedef struct config_entry_s {
737c478bd9Sstevel@tonic-gate 	struct config_entry_s		*next;
747c478bd9Sstevel@tonic-gate 	int				seconds_to_warn;
757c478bd9Sstevel@tonic-gate 	char				*principal;
767c478bd9Sstevel@tonic-gate 	char				*where_to;
777c478bd9Sstevel@tonic-gate 	char				*email;
787c478bd9Sstevel@tonic-gate 	int				renew;
797c478bd9Sstevel@tonic-gate 	int				log_success;
807c478bd9Sstevel@tonic-gate 	int				log_failure;
817c478bd9Sstevel@tonic-gate } config_entry_list_t;
827c478bd9Sstevel@tonic-gate static config_entry_list_t		*config_entry_list;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* list of principals to be warned */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate typedef struct cred_warning_list_s {
877c478bd9Sstevel@tonic-gate 	struct cred_warning_list_s 	*next;
887c478bd9Sstevel@tonic-gate 	WARNING_NAME_T			warn_name;
897c478bd9Sstevel@tonic-gate 	time_t				cred_exp_time;
907c478bd9Sstevel@tonic-gate 	time_t				cred_warn_time;
917c478bd9Sstevel@tonic-gate 	mutex_t				cwm;
927c478bd9Sstevel@tonic-gate } cred_warning_list_t;
937c478bd9Sstevel@tonic-gate static cred_warning_list_t		*cred_warning_list;
947c478bd9Sstevel@tonic-gate static rwlock_t				cred_lock = DEFAULTRWLOCK;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate static bool_t
977c478bd9Sstevel@tonic-gate del_warning_pvt(char *);
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static config_entry_list_t *
1007c478bd9Sstevel@tonic-gate find_warning_info(char *);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate static bool_t
1037c478bd9Sstevel@tonic-gate parseConfigLine(char *buffer);
1047c478bd9Sstevel@tonic-gate 
105814a60b1Sgtb extern int warn_send(char *, char *);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate extern int kwarnd_debug;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate cred_warning_list_t *
find_cred_warning(WARNING_NAME_T warn_name)1107c478bd9Sstevel@tonic-gate find_cred_warning(WARNING_NAME_T warn_name)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	cred_warning_list_t	*cw;
1137c478bd9Sstevel@tonic-gate 	if (!cred_warning_list)
1147c478bd9Sstevel@tonic-gate 		return (NULL);
1157c478bd9Sstevel@tonic-gate 	for (cw = cred_warning_list; cw != NULL; cw = cw->next) {
1167c478bd9Sstevel@tonic-gate 		if (strcmp(warn_name, cw->warn_name) != 0)
1177c478bd9Sstevel@tonic-gate 			continue;
1187c478bd9Sstevel@tonic-gate 		return (cw);
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 	return (NULL);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate  * add a principal to the principal warning list
1257c478bd9Sstevel@tonic-gate  */
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate bool_t
kwarn_add_warning_1_svc(kwarn_add_warning_arg * argp,kwarn_add_warning_res * res,struct svc_req * rqstp)1287c478bd9Sstevel@tonic-gate kwarn_add_warning_1_svc(kwarn_add_warning_arg *argp,
1297c478bd9Sstevel@tonic-gate 			kwarn_add_warning_res *res,
1307c478bd9Sstevel@tonic-gate 			struct svc_req *rqstp)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	cred_warning_list_t	*cred_warning;
1337c478bd9Sstevel@tonic-gate 	config_entry_list_t *config_entry;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (kwarnd_debug) {
1367c478bd9Sstevel@tonic-gate 		printf("kwarn_add_warning_1_svc start; cWlist=%p\n",
1377c478bd9Sstevel@tonic-gate 		    cred_warning_list);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 		printf("kwarn_add_warning_1_svc: principal %s",
1407c478bd9Sstevel@tonic-gate 		    argp->warning_name);
1417c478bd9Sstevel@tonic-gate 		printf(" exp time: %d\n", argp->cred_exp_time);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  *  if there is no entry in the config file that matches the principal to
1467c478bd9Sstevel@tonic-gate  *  be added to the warning list, return true because we are not going to
1477c478bd9Sstevel@tonic-gate  *  send a warning for this principal.
1487c478bd9Sstevel@tonic-gate  */
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if ((config_entry = find_warning_info(argp->warning_name)) == NULL) {
1517c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
1527c478bd9Sstevel@tonic-gate 			printf(
1537c478bd9Sstevel@tonic-gate 		"kwarn_add_warning_1_svc find_warn_info: fails, cWlist=%p\n",
1547c478bd9Sstevel@tonic-gate 				cred_warning_list);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 		return (TRUE);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate  * see if a warning has already been created for this principal, if so
1617c478bd9Sstevel@tonic-gate  * update the warning time.
1627c478bd9Sstevel@tonic-gate  */
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	rw_wrlock(&cred_lock);
1657c478bd9Sstevel@tonic-gate 	if (cred_warning = find_cred_warning(argp->warning_name)) {
1667c478bd9Sstevel@tonic-gate 		rw_unlock(&cred_lock);
1677c478bd9Sstevel@tonic-gate 		mutex_lock(&cred_warning->cwm);
1687c478bd9Sstevel@tonic-gate 		cred_warning->cred_exp_time = argp->cred_exp_time;
1697c478bd9Sstevel@tonic-gate 		cred_warning->cred_warn_time = argp->cred_exp_time
1707c478bd9Sstevel@tonic-gate 			- config_entry->seconds_to_warn;
1717c478bd9Sstevel@tonic-gate 		mutex_unlock(&cred_warning->cwm);
1727c478bd9Sstevel@tonic-gate 	} else {
1737c478bd9Sstevel@tonic-gate 		cred_warning = (cred_warning_list_t *)malloc(
1747c478bd9Sstevel@tonic-gate 				sizeof (*cred_warning_list));
1757c478bd9Sstevel@tonic-gate 		if (cred_warning == NULL) {
1767c478bd9Sstevel@tonic-gate 			rw_unlock(&cred_lock);
1777c478bd9Sstevel@tonic-gate 			res->status = 1;
1787c478bd9Sstevel@tonic-gate 			return (FALSE);
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 		(void) memset((char *)cred_warning, 0,
1817c478bd9Sstevel@tonic-gate 			    sizeof (*cred_warning_list));
1827c478bd9Sstevel@tonic-gate 		cred_warning->cred_exp_time = argp->cred_exp_time;
1837c478bd9Sstevel@tonic-gate 		cred_warning->cred_warn_time = argp->cred_exp_time
1847c478bd9Sstevel@tonic-gate 			- config_entry->seconds_to_warn;
1857c478bd9Sstevel@tonic-gate 		cred_warning->warn_name = strdup(argp->warning_name);
1867c478bd9Sstevel@tonic-gate 		if (cred_warning->warn_name == NULL) {
1877c478bd9Sstevel@tonic-gate 			free(cred_warning);
1887c478bd9Sstevel@tonic-gate 			rw_unlock(&cred_lock);
1897c478bd9Sstevel@tonic-gate 			res->status = 1;
1907c478bd9Sstevel@tonic-gate 			return (FALSE);
1917c478bd9Sstevel@tonic-gate 		}
1927c478bd9Sstevel@tonic-gate 		mutex_init(&cred_warning->cwm,  USYNC_THREAD, NULL);
1937c478bd9Sstevel@tonic-gate 		cred_warning->next = cred_warning_list;
1947c478bd9Sstevel@tonic-gate 		cred_warning_list = cred_warning;
1957c478bd9Sstevel@tonic-gate 		rw_unlock(&cred_lock);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 	res->status = 0;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
2007c478bd9Sstevel@tonic-gate 		printf(
2017c478bd9Sstevel@tonic-gate 		"kwarn_add_warning_1_svc end: returns true; cWlist=%p\n",
2027c478bd9Sstevel@tonic-gate 		cred_warning_list);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	return (TRUE);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * delete a warning request for a given principal
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate bool_t
kwarn_del_warning_1_svc(kwarn_del_warning_arg * argp,kwarn_del_warning_res * res,struct svc_req * rqstp)2127c478bd9Sstevel@tonic-gate kwarn_del_warning_1_svc(kwarn_del_warning_arg *argp,
2137c478bd9Sstevel@tonic-gate 			kwarn_del_warning_res *res,
2147c478bd9Sstevel@tonic-gate 			struct svc_req *rqstp)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
2177c478bd9Sstevel@tonic-gate 		printf(gettext("delete principal %s requested\n"),
2187c478bd9Sstevel@tonic-gate 		    argp->warning_name);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	if (del_warning_pvt(argp->warning_name) == TRUE) {
2217c478bd9Sstevel@tonic-gate 		res->status = 0;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
2247c478bd9Sstevel@tonic-gate 			printf(gettext("delete principal %s completed\n"),
2257c478bd9Sstevel@tonic-gate 			    argp->warning_name);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 		return (TRUE);
2287c478bd9Sstevel@tonic-gate 	} else {
2297c478bd9Sstevel@tonic-gate 		res->status = 1;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
2327c478bd9Sstevel@tonic-gate 			printf(gettext("delete principal %s failed\n"),
2337c478bd9Sstevel@tonic-gate 				argp->warning_name);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 		return (TRUE);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate static bool_t
del_warning_pvt(char * warning_name)2407c478bd9Sstevel@tonic-gate del_warning_pvt(char *warning_name)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	cred_warning_list_t	*cred_warning, *prev;
2437c478bd9Sstevel@tonic-gate 	rw_wrlock(&cred_lock);
2447c478bd9Sstevel@tonic-gate 	for (prev = NULL, cred_warning = cred_warning_list;
2457c478bd9Sstevel@tonic-gate 		cred_warning != NULL; prev = cred_warning,
2467c478bd9Sstevel@tonic-gate 		cred_warning = cred_warning->next) {
2477c478bd9Sstevel@tonic-gate 		if (strcmp(cred_warning->warn_name, warning_name) == 0) {
2487c478bd9Sstevel@tonic-gate 			if (!prev)
2497c478bd9Sstevel@tonic-gate 				cred_warning_list = cred_warning->next;
2507c478bd9Sstevel@tonic-gate 			else
2517c478bd9Sstevel@tonic-gate 				prev->next = cred_warning->next;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 			free(cred_warning->warn_name);
2547c478bd9Sstevel@tonic-gate 			free(cred_warning);
2557c478bd9Sstevel@tonic-gate 			rw_unlock(&cred_lock);
2567c478bd9Sstevel@tonic-gate 			return (TRUE);
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 	rw_unlock(&cred_lock);
2607c478bd9Sstevel@tonic-gate 	return (FALSE);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate  * load the warn.conf file into the config_entry list.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate bool_t
loadConfigFile(void)2687c478bd9Sstevel@tonic-gate loadConfigFile(void)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	char	buffer[BUFSIZ];
2717c478bd9Sstevel@tonic-gate 	FILE	*cfgfile;
2727c478bd9Sstevel@tonic-gate 	bool_t	retval = TRUE;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if ((cfgfile = fopen(CONF_FILENAME, "r")) == NULL) {
2757c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, gettext(
2767c478bd9Sstevel@tonic-gate 			"could not open config file \"%s\"\n"),
2777c478bd9Sstevel@tonic-gate 			CONF_FILENAME);
2787c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, gettext(
2797c478bd9Sstevel@tonic-gate 			"using default options \"%s\"\n"),
2807c478bd9Sstevel@tonic-gate 			DEFAULT_CONFIG);
2817c478bd9Sstevel@tonic-gate 		retval = parseConfigLine(DEFAULT_CONFIG);
2827c478bd9Sstevel@tonic-gate 	} else {
2837c478bd9Sstevel@tonic-gate 		(void) memset(buffer, 0, sizeof (buffer));
2847c478bd9Sstevel@tonic-gate 		while ((fgets(buffer, BUFSIZ, cfgfile) != NULL) &&
2857c478bd9Sstevel@tonic-gate 			(retval == TRUE))
2867c478bd9Sstevel@tonic-gate 			retval = parseConfigLine(buffer);
2877c478bd9Sstevel@tonic-gate 		fclose(cfgfile);
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	return (retval);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate  * Return TRUE if we get a valid opt and update flags appro.
2947c478bd9Sstevel@tonic-gate  */
2957c478bd9Sstevel@tonic-gate static bool_t
cmp_renew_opts(char * opt,int * log_success,int * log_failure)2967c478bd9Sstevel@tonic-gate cmp_renew_opts(char *opt,
2977c478bd9Sstevel@tonic-gate 	    int *log_success, /* out */
2987c478bd9Sstevel@tonic-gate 	    int *log_failure) /* out */
2997c478bd9Sstevel@tonic-gate {
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (strncasecmp(opt, "log",
3027c478bd9Sstevel@tonic-gate 			sizeof ("log")) == 0) {
3037c478bd9Sstevel@tonic-gate 		*log_success = *log_failure = 1;
3047c478bd9Sstevel@tonic-gate 	} else if (strncasecmp(opt, "log-success",
3057c478bd9Sstevel@tonic-gate 			    sizeof ("log-success")) == 0) {
3067c478bd9Sstevel@tonic-gate 		*log_success = 1;
3077c478bd9Sstevel@tonic-gate 	} else if (strncasecmp(opt, "log-failure",
3087c478bd9Sstevel@tonic-gate 			    sizeof ("log-failure")) == 0) {
3097c478bd9Sstevel@tonic-gate 		*log_failure = 1;
3107c478bd9Sstevel@tonic-gate 	} else {
3117c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
3127c478bd9Sstevel@tonic-gate 			printf("cmp_renew_opts: renew bad opt=`%s'\n",
3137c478bd9Sstevel@tonic-gate 			    opt ? opt : "null");
3147c478bd9Sstevel@tonic-gate 		return (FALSE);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	return (TRUE);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate  * Make the config_entry item for the config_entry_list, based on
3227c478bd9Sstevel@tonic-gate  * buffer.  The formats are
3237c478bd9Sstevel@tonic-gate  *
3247c478bd9Sstevel@tonic-gate  *    <principal> [renew[:<opt1,...optN>]] syslog|terminal <time>
3257c478bd9Sstevel@tonic-gate  *    <principal> [renew[:<opt1,...optN>]] mail <time> <e-mail address>
3267c478bd9Sstevel@tonic-gate  *
3277c478bd9Sstevel@tonic-gate  * where renew opts will be:
3287c478bd9Sstevel@tonic-gate  *
3297c478bd9Sstevel@tonic-gate  *     log-success
3307c478bd9Sstevel@tonic-gate  *		- Log the result of the renew attempt on success using
3317c478bd9Sstevel@tonic-gate  *		  the specified method (syslog|terminal|mail)
3327c478bd9Sstevel@tonic-gate  *
3337c478bd9Sstevel@tonic-gate  *      log-failure
3347c478bd9Sstevel@tonic-gate  *		- Log the result of the renew attempt on failure using
3357c478bd9Sstevel@tonic-gate  *		  the specified method (syslog|terminal|mail)
3367c478bd9Sstevel@tonic-gate  *
3377c478bd9Sstevel@tonic-gate  *      log
3387c478bd9Sstevel@tonic-gate  *               - Same as specifing both log-failure and log-success
3397c478bd9Sstevel@tonic-gate  *
3407c478bd9Sstevel@tonic-gate  *		  Note if no log options are given, there will be no logging.
3417c478bd9Sstevel@tonic-gate  *
3427c478bd9Sstevel@tonic-gate  */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate static bool_t
parseConfigLine(char * buffer)3457c478bd9Sstevel@tonic-gate parseConfigLine(char *buffer)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	char *principal, *send_to, *emailid, *ends, *tm;
3487c478bd9Sstevel@tonic-gate 	char			*exptime;
3497c478bd9Sstevel@tonic-gate 	int			time_mode;
3507c478bd9Sstevel@tonic-gate 	time_t			etime;
3517c478bd9Sstevel@tonic-gate 	config_entry_list_t	*config_entry;
3527c478bd9Sstevel@tonic-gate 	int renew = 0;
3537c478bd9Sstevel@tonic-gate 	int log_success = 0;
3547c478bd9Sstevel@tonic-gate 	int log_failure = 0;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/* ignore comments */
3577c478bd9Sstevel@tonic-gate 	if (*buffer == '#')
3587c478bd9Sstevel@tonic-gate 		return (TRUE);
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
3617c478bd9Sstevel@tonic-gate 		printf("parseconf: buffer=%s", buffer);
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	/* find end of principal */
3647c478bd9Sstevel@tonic-gate 	principal = buffer;
3657c478bd9Sstevel@tonic-gate 	for (send_to = buffer; *send_to && !isspace(*send_to);
3667c478bd9Sstevel@tonic-gate 		send_to++);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	/* find first non whitespace after principal (start of send_to) */
3697c478bd9Sstevel@tonic-gate 	if (*send_to) {
3707c478bd9Sstevel@tonic-gate 		*send_to = '\0';
3717c478bd9Sstevel@tonic-gate 		send_to++;
3727c478bd9Sstevel@tonic-gate 		while (*send_to && isspace(*send_to))
3737c478bd9Sstevel@tonic-gate 			send_to++;
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	/* if no send_to, continue, bad entry */
3777c478bd9Sstevel@tonic-gate 	if (! *send_to)
3787c478bd9Sstevel@tonic-gate 		return (TRUE);
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	/* find end of send_to */
3817c478bd9Sstevel@tonic-gate 	for (ends = send_to; *ends && !isspace(*ends);
3827c478bd9Sstevel@tonic-gate 		ends++);
3837c478bd9Sstevel@tonic-gate 	if (*ends)
3847c478bd9Sstevel@tonic-gate 		*ends = '\0';
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (strchr(send_to, ':')) {
3887c478bd9Sstevel@tonic-gate 		/* we've got renew opts */
3897c478bd9Sstevel@tonic-gate 		char *st = NULL, *op = NULL;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		op = strdup(send_to);
3927c478bd9Sstevel@tonic-gate 		if (!op)
3937c478bd9Sstevel@tonic-gate 			return (FALSE);
3947c478bd9Sstevel@tonic-gate 		st = strchr(op, ':');
3957c478bd9Sstevel@tonic-gate 		*st = '\0';
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		if (strncasecmp(op, "renew", sizeof ("renew")) == 0) {
3987c478bd9Sstevel@tonic-gate 			renew = 1;
3997c478bd9Sstevel@tonic-gate 		} else {
4007c478bd9Sstevel@tonic-gate 			free(op);
4017c478bd9Sstevel@tonic-gate 			/* got a ':' but not preceeded w/renew, badent, skip */
4027c478bd9Sstevel@tonic-gate 			if (kwarnd_debug)
4037c478bd9Sstevel@tonic-gate 				printf("parseconf: colon badent, skip\n");
4047c478bd9Sstevel@tonic-gate 			return (TRUE);
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 		free(op);
4077c478bd9Sstevel@tonic-gate 		op = NULL;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 		st++;
4107c478bd9Sstevel@tonic-gate 		if (!st || !*st || isspace(*st)) {
4117c478bd9Sstevel@tonic-gate 			if (kwarnd_debug)
4127c478bd9Sstevel@tonic-gate 				printf("parseconf: st badent, skip\n");
4137c478bd9Sstevel@tonic-gate 			/* bad ent, skip */
4147c478bd9Sstevel@tonic-gate 			return (TRUE);
4157c478bd9Sstevel@tonic-gate 		}
4167c478bd9Sstevel@tonic-gate 		if (renew && strchr(st, ',')) {
4177c478bd9Sstevel@tonic-gate 			while (1) {
4187c478bd9Sstevel@tonic-gate 				/* loop thru comma seperated list-o-opts */
4197c478bd9Sstevel@tonic-gate 				char *comma = NULL, *c = NULL, *l = NULL;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 				if (st && (comma = strchr(st, ','))) {
4227c478bd9Sstevel@tonic-gate 					l = strdup(st);
4237c478bd9Sstevel@tonic-gate 					if (!l)
4247c478bd9Sstevel@tonic-gate 						return (FALSE);
4257c478bd9Sstevel@tonic-gate 					c = strchr(l, ',');
4267c478bd9Sstevel@tonic-gate 					*c = '\0';
4277c478bd9Sstevel@tonic-gate 					if (!cmp_renew_opts(l, &log_success,
4287c478bd9Sstevel@tonic-gate 							    &log_failure)) {
4297c478bd9Sstevel@tonic-gate 						free(l);
4307c478bd9Sstevel@tonic-gate 						/* badent, skip */
4317c478bd9Sstevel@tonic-gate 						return (TRUE);
4327c478bd9Sstevel@tonic-gate 					}
4337c478bd9Sstevel@tonic-gate 					free(l);
4347c478bd9Sstevel@tonic-gate 					l = NULL;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 					st = comma;
4377c478bd9Sstevel@tonic-gate 					st++;
4387c478bd9Sstevel@tonic-gate 				} else {
4397c478bd9Sstevel@tonic-gate 					if (st) {
4407c478bd9Sstevel@tonic-gate 						if (!cmp_renew_opts(st,
4417c478bd9Sstevel@tonic-gate 							    &log_success,
4427c478bd9Sstevel@tonic-gate 							    &log_failure)) {
4437c478bd9Sstevel@tonic-gate 							/* badent, skip */
4447c478bd9Sstevel@tonic-gate 							return (TRUE);
4457c478bd9Sstevel@tonic-gate 						}
4467c478bd9Sstevel@tonic-gate 					}
4477c478bd9Sstevel@tonic-gate 					break;
4487c478bd9Sstevel@tonic-gate 				}
4497c478bd9Sstevel@tonic-gate 			} /* while */
4507c478bd9Sstevel@tonic-gate 		} else if (st) {
4517c478bd9Sstevel@tonic-gate 			/* we just have one opt */
4527c478bd9Sstevel@tonic-gate 			if (!cmp_renew_opts(st, &log_success, &log_failure)) {
4537c478bd9Sstevel@tonic-gate 				/* badent, skip */
4547c478bd9Sstevel@tonic-gate 				return (TRUE);
4557c478bd9Sstevel@tonic-gate 			}
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		/* if send_to is "renew", note it and refind send_to */
4597c478bd9Sstevel@tonic-gate 	} else if (strncasecmp(send_to, "renew",
4607c478bd9Sstevel@tonic-gate 			    sizeof ("renew")) == 0) {
4617c478bd9Sstevel@tonic-gate 		renew = 1;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	if (kwarnd_debug) {
4667c478bd9Sstevel@tonic-gate 		printf("parseconf: renew=%d, log failure=%d, log success=%d\n",
4677c478bd9Sstevel@tonic-gate 		    renew, log_failure, log_success);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	if (renew) {
4717c478bd9Sstevel@tonic-gate 		/* find first non whitespace after send_to (start of exptime) */
4727c478bd9Sstevel@tonic-gate 		for (send_to = ends+1; *send_to && isspace(*send_to);
4737c478bd9Sstevel@tonic-gate 		    send_to++);
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		/* if no send_to, continue, bad entry */
4767c478bd9Sstevel@tonic-gate 		if (! *send_to) {
4777c478bd9Sstevel@tonic-gate 			if (kwarnd_debug)
4787c478bd9Sstevel@tonic-gate 				printf("parseconf: no send_to, badent, skip\n");
4797c478bd9Sstevel@tonic-gate 			return (TRUE);
4807c478bd9Sstevel@tonic-gate 		}
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 		/* find end of send_to */
4837c478bd9Sstevel@tonic-gate 		for (ends = send_to; *ends && !isspace(*ends);
4847c478bd9Sstevel@tonic-gate 		    ends++);
4857c478bd9Sstevel@tonic-gate 		if (*ends)
4867c478bd9Sstevel@tonic-gate 			*ends = '\0';
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	/* find first non whitespace after send_to (start of exptime) */
4917c478bd9Sstevel@tonic-gate 	for (exptime = ends+1; *exptime && isspace(*exptime);
4927c478bd9Sstevel@tonic-gate 		exptime++);
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	/* if no exptime, continue, bad entry */
4957c478bd9Sstevel@tonic-gate 	if (! *exptime) {
4967c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
4977c478bd9Sstevel@tonic-gate 			printf("parseconf: no exptime, badent, skip\n");
4987c478bd9Sstevel@tonic-gate 		return (TRUE);
4997c478bd9Sstevel@tonic-gate 	}
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	/* find end of exptime */
5027c478bd9Sstevel@tonic-gate 	for (ends = exptime; *ends && !isspace(*ends); ends++);
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	tm = ends - 1;
5057c478bd9Sstevel@tonic-gate 	if (*tm == 's')
5067c478bd9Sstevel@tonic-gate 		time_mode = 1;
5077c478bd9Sstevel@tonic-gate 	else if (*tm == 'm')
5087c478bd9Sstevel@tonic-gate 		time_mode = 2;
5097c478bd9Sstevel@tonic-gate 	else if (*tm == 'h')
5107c478bd9Sstevel@tonic-gate 		time_mode = 3;
5117c478bd9Sstevel@tonic-gate 	else
5127c478bd9Sstevel@tonic-gate 		time_mode = 1;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if (*tm)
5157c478bd9Sstevel@tonic-gate 		*tm = '\0';
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	if (kwarnd_debug) {
5187c478bd9Sstevel@tonic-gate 		printf("parseconf: send_to = '%s', exptime='%s'\n",
5197c478bd9Sstevel@tonic-gate 		    send_to, exptime);
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	/* find first non whitespace after exptime (start of emailid) */
5237c478bd9Sstevel@tonic-gate 	for (emailid = ends+1; *emailid && isspace(*emailid); emailid++);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/* find end of emailid */
5267c478bd9Sstevel@tonic-gate 	if (*emailid) {
5277c478bd9Sstevel@tonic-gate 		for (ends = emailid; *ends && !isspace(*ends);
5287c478bd9Sstevel@tonic-gate 			ends++);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		if (*ends)
5317c478bd9Sstevel@tonic-gate 			*ends = '\0';
5327c478bd9Sstevel@tonic-gate 	}
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	/* if send to mail and no mail address, bad entry */
5357c478bd9Sstevel@tonic-gate 	if ((strcmp(send_to, "mail") == 0) && (!*emailid)) {
5367c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
5377c478bd9Sstevel@tonic-gate 			printf("parseconf: returns true; no mail addr\n");
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, gettext("missing mail address"
5407c478bd9Sstevel@tonic-gate 			" in config entry: \n%s %s %s "
5417c478bd9Sstevel@tonic-gate 			" cannot mail warning"), principal,
5427c478bd9Sstevel@tonic-gate 			send_to, exptime);
5437c478bd9Sstevel@tonic-gate 		return (TRUE);
5447c478bd9Sstevel@tonic-gate 	}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	/* create an entry */
5477c478bd9Sstevel@tonic-gate 	config_entry = (config_entry_list_t *)
5487c478bd9Sstevel@tonic-gate 		malloc(sizeof (*config_entry_list));
5497c478bd9Sstevel@tonic-gate 	if (config_entry == NULL)
5507c478bd9Sstevel@tonic-gate 		return (FALSE);
5517c478bd9Sstevel@tonic-gate 	(void) memset(config_entry, 0, sizeof (*config_entry_list));
5527c478bd9Sstevel@tonic-gate 	config_entry->principal = strdup(principal);
5537c478bd9Sstevel@tonic-gate 	if (config_entry->principal == NULL)
5547c478bd9Sstevel@tonic-gate 		return (FALSE);
5557c478bd9Sstevel@tonic-gate 	config_entry->where_to = strdup(send_to);
5567c478bd9Sstevel@tonic-gate 	if (config_entry->where_to == NULL)
5577c478bd9Sstevel@tonic-gate 		return (FALSE);
5587c478bd9Sstevel@tonic-gate 	etime = atol(exptime);
5597c478bd9Sstevel@tonic-gate 	if (time_mode == 1)
5607c478bd9Sstevel@tonic-gate 		config_entry->seconds_to_warn = etime;
5617c478bd9Sstevel@tonic-gate 	else if (time_mode == 2)
5627c478bd9Sstevel@tonic-gate 		config_entry->seconds_to_warn = etime * 60;
5637c478bd9Sstevel@tonic-gate 	else if (time_mode == 3)
5647c478bd9Sstevel@tonic-gate 		config_entry->seconds_to_warn = etime * 60 * 60;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if (*emailid) {
5677c478bd9Sstevel@tonic-gate 		config_entry->email = strdup(emailid);
5687c478bd9Sstevel@tonic-gate 		if (config_entry->email == NULL)
5697c478bd9Sstevel@tonic-gate 			return (FALSE);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	config_entry->renew = renew;
5737c478bd9Sstevel@tonic-gate 	config_entry->log_success = log_success;
5747c478bd9Sstevel@tonic-gate 	config_entry->log_failure = log_failure;
5757c478bd9Sstevel@tonic-gate 	config_entry->next = config_entry_list;
5767c478bd9Sstevel@tonic-gate 	config_entry_list = config_entry;
5777c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
5787c478bd9Sstevel@tonic-gate 		printf("parseconf: returns true; celist=%p\n",
5797c478bd9Sstevel@tonic-gate 		    config_entry_list);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	return (TRUE);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate  * find a specific warn.conf entry.
5867c478bd9Sstevel@tonic-gate  */
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate static config_entry_list_t *
find_warning_info(char * principal)5897c478bd9Sstevel@tonic-gate find_warning_info(char *principal)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	config_entry_list_t	*config_entry;
5927c478bd9Sstevel@tonic-gate 	/* look for a specific entry */
5937c478bd9Sstevel@tonic-gate 	for (config_entry = config_entry_list; config_entry;
5947c478bd9Sstevel@tonic-gate 		config_entry = config_entry->next) {
5957c478bd9Sstevel@tonic-gate 		if (strcmp(config_entry->principal, principal) == 0) {
5967c478bd9Sstevel@tonic-gate 			return (config_entry);
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 	}
5997c478bd9Sstevel@tonic-gate 	/* look for a wild card entry */
6007c478bd9Sstevel@tonic-gate 	for (config_entry = config_entry_list; config_entry;
6017c478bd9Sstevel@tonic-gate 		config_entry = config_entry->next) {
6027c478bd9Sstevel@tonic-gate 		if (strcmp(config_entry->principal, "*") == 0) {
6037c478bd9Sstevel@tonic-gate 			return (config_entry);
6047c478bd9Sstevel@tonic-gate 		}
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 	/* nothing found */
6077c478bd9Sstevel@tonic-gate 	return (NULL);
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate  * create a pipe, fork and exec a command,
6137c478bd9Sstevel@tonic-gate  */
6147c478bd9Sstevel@tonic-gate static FILE *
safe_popen_w(char * path_to_cmd,char ** argv)6157c478bd9Sstevel@tonic-gate safe_popen_w(char *path_to_cmd, char **argv)
6167c478bd9Sstevel@tonic-gate {
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	int fd[2];
6197c478bd9Sstevel@tonic-gate 	FILE *fp;
6207c478bd9Sstevel@tonic-gate 	char *envp[2];
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	if (pipe(fd) == -1)
6237c478bd9Sstevel@tonic-gate 		return (NULL);
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	switch (fork()) {
6277c478bd9Sstevel@tonic-gate 	case -1:
6287c478bd9Sstevel@tonic-gate 		(void) close(fd[0]);
6297c478bd9Sstevel@tonic-gate 		(void) close(fd[1]);
6307c478bd9Sstevel@tonic-gate 		return (NULL);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	case 0:
6337c478bd9Sstevel@tonic-gate 		close(fd[1]);
6347c478bd9Sstevel@tonic-gate 		/* fd[0] is the end we read from */
6357c478bd9Sstevel@tonic-gate 		if (fd[0] != 0) {
6367c478bd9Sstevel@tonic-gate 			close(0);
6377c478bd9Sstevel@tonic-gate 			dup(fd[0]);
6387c478bd9Sstevel@tonic-gate 		}
6397c478bd9Sstevel@tonic-gate 		close(1);
6407c478bd9Sstevel@tonic-gate 		close(2);
6417c478bd9Sstevel@tonic-gate 		envp[0] = "PATH=/usr/bin";
6427c478bd9Sstevel@tonic-gate 		envp[1] = NULL;
6437c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6447c478bd9Sstevel@tonic-gate 		{
6457c478bd9Sstevel@tonic-gate 			int fd;
6467c478bd9Sstevel@tonic-gate 			fd = open("/tmp/kwarn.out", O_WRONLY|O_TRUNC|O_CREAT,
6477c478bd9Sstevel@tonic-gate 				0666);
6487c478bd9Sstevel@tonic-gate 			if (fd != 1)
6497c478bd9Sstevel@tonic-gate 				dup(fd);
6507c478bd9Sstevel@tonic-gate 			if (fd != 2)
6517c478bd9Sstevel@tonic-gate 				dup(fd);
6527c478bd9Sstevel@tonic-gate 		}
6537c478bd9Sstevel@tonic-gate #endif
6547c478bd9Sstevel@tonic-gate 		(void) execve(path_to_cmd, argv, envp);
6557c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "warnd: %m");
6567c478bd9Sstevel@tonic-gate 		_exit(1);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	default:
6597c478bd9Sstevel@tonic-gate 		close(fd[0]);
6607c478bd9Sstevel@tonic-gate 		/* fd[1] is the end we write to */
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 		fp = fdopen(fd[1], "w");
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
6657c478bd9Sstevel@tonic-gate 			(void) close(fd[1]);
6667c478bd9Sstevel@tonic-gate 			return (NULL);
6677c478bd9Sstevel@tonic-gate 		}
6687c478bd9Sstevel@tonic-gate 		return (fp);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 
67324da5b34Srie static uid_t krb5_cc_uid;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate void
set_warnd_uid(uid_t uid)6767c478bd9Sstevel@tonic-gate set_warnd_uid(uid_t uid)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate 	/*
67924da5b34Srie 	 * set the value of krb5_cc_uid, so it can be retrieved when
68024da5b34Srie 	 * app_krb5_user_uid() is called by the underlying mechanism libraries.
6817c478bd9Sstevel@tonic-gate 	 */
6827c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
6837c478bd9Sstevel@tonic-gate 		printf("set_warnd_uid called with uid = %d\n", uid);
68424da5b34Srie 	krb5_cc_uid = uid;
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate uid_t
app_krb5_user_uid(void)68824da5b34Srie app_krb5_user_uid(void)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	/*
69224da5b34Srie 	 * return the value set when one of the kwarnd procedures was
6937c478bd9Sstevel@tonic-gate 	 * entered. This is the value of the uid under which the
6947c478bd9Sstevel@tonic-gate 	 * underlying mechanism library must operate in order to
6957c478bd9Sstevel@tonic-gate 	 * get the user's credentials. This call is necessary since
69624da5b34Srie 	 * kwarnd runs as root and credentials are many times stored
6977c478bd9Sstevel@tonic-gate 	 * in files and directories specific to the user
6987c478bd9Sstevel@tonic-gate 	 */
6997c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
70024da5b34Srie 		printf("app_krb5_user_uid called and returning uid = %d\n",
70124da5b34Srie 		    krb5_cc_uid);
70224da5b34Srie 	return (krb5_cc_uid);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate static bool_t
getpruid(char * pr,uid_t * uid)7077c478bd9Sstevel@tonic-gate getpruid(char *pr, uid_t *uid)
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate 	char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL;
7107c478bd9Sstevel@tonic-gate 	struct passwd *pw;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	rcp1 = strdup(pr);
7137c478bd9Sstevel@tonic-gate 	if (!rcp1)
7147c478bd9Sstevel@tonic-gate 		return (FALSE);
7157c478bd9Sstevel@tonic-gate 	rcp2 = strtok(rcp1, "@");
7167c478bd9Sstevel@tonic-gate 	rcp3 = strtok(rcp2, "/");
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	if (rcp3) {
7197c478bd9Sstevel@tonic-gate 		pw = getpwnam(rcp3);
7207c478bd9Sstevel@tonic-gate 		*uid = pw->pw_uid;
7217c478bd9Sstevel@tonic-gate 		free(rcp1);
7227c478bd9Sstevel@tonic-gate 		return (TRUE);
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	free(rcp1);
7267c478bd9Sstevel@tonic-gate 	return (FALSE);
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate static krb5_error_code
renew_creds(char * princ,time_t * new_exp_time)7317c478bd9Sstevel@tonic-gate renew_creds(
7327c478bd9Sstevel@tonic-gate 	char *princ,
7337c478bd9Sstevel@tonic-gate 	time_t *new_exp_time) /* out */
7347c478bd9Sstevel@tonic-gate {
7357c478bd9Sstevel@tonic-gate 	krb5_creds my_creds;
7367c478bd9Sstevel@tonic-gate 	krb5_error_code code = 0;
7377c478bd9Sstevel@tonic-gate 	struct k5_data k5;
7387c478bd9Sstevel@tonic-gate 
73924da5b34Srie 	uid_t saved_u = app_krb5_user_uid();
7407c478bd9Sstevel@tonic-gate 	uid_t u;
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
74324da5b34Srie 		printf("renew start: uid=%d\n", app_krb5_user_uid());
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	if (!getpruid(princ, &u)) {
7467c478bd9Sstevel@tonic-gate 		if (kwarnd_debug)
7477c478bd9Sstevel@tonic-gate 			printf("renew: getpruid failed, princ='%s'\n",
7487c478bd9Sstevel@tonic-gate 			    princ ? princ : "<null>");
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		return (-1); /* better err num? */
7517c478bd9Sstevel@tonic-gate 	}
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	set_warnd_uid(u);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	(void) memset(&my_creds, 0, sizeof (my_creds));
7567c478bd9Sstevel@tonic-gate 	(void) memset(&k5, 0, sizeof (k5));
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	if (code = krb5_init_context(&k5.ctx)) {
7597c478bd9Sstevel@tonic-gate 		com_err(progname, code,
7607c478bd9Sstevel@tonic-gate 			gettext("while initializing Kerberos 5 library"));
7617c478bd9Sstevel@tonic-gate 		goto out;
7627c478bd9Sstevel@tonic-gate 	}
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 	if ((code = krb5_cc_default(k5.ctx, &k5.cc))) {
7657c478bd9Sstevel@tonic-gate 		com_err(progname, code,
7667c478bd9Sstevel@tonic-gate 			gettext("while getting default ccache"));
7677c478bd9Sstevel@tonic-gate 		goto out;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	}
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	if ((code = krb5_parse_name(k5.ctx, princ,
7727c478bd9Sstevel@tonic-gate 				    &k5.me))) {
7737c478bd9Sstevel@tonic-gate 		com_err(progname, code, gettext("when parsing name %s"),
7747c478bd9Sstevel@tonic-gate 			princ);
7757c478bd9Sstevel@tonic-gate 		goto out;
7767c478bd9Sstevel@tonic-gate 	}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if ((code = krb5_get_renewed_creds(k5.ctx, &my_creds, k5.me, k5.cc,
7797c478bd9Sstevel@tonic-gate 					NULL))) {
7807c478bd9Sstevel@tonic-gate 		com_err(progname, code, gettext("while renewing creds"));
7817c478bd9Sstevel@tonic-gate 		goto out;
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 	if (code = krb5_cc_initialize(k5.ctx, k5.cc, k5.me)) {
7857c478bd9Sstevel@tonic-gate 		com_err(progname, code, gettext("when initializing cache %s"),
7867c478bd9Sstevel@tonic-gate 			"defcc");
7877c478bd9Sstevel@tonic-gate 		goto out;
7887c478bd9Sstevel@tonic-gate 	}
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	if (code = krb5_cc_store_cred(k5.ctx, k5.cc, &my_creds)) {
7917c478bd9Sstevel@tonic-gate 		com_err(progname, code, gettext("while storing credentials"));
7927c478bd9Sstevel@tonic-gate 		goto out;
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	/* "return" new expire time */
7967c478bd9Sstevel@tonic-gate 	*new_exp_time = my_creds.times.endtime;
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate out:
7997c478bd9Sstevel@tonic-gate 	krb5_free_cred_contents(k5.ctx, &my_creds);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	if (k5.name)
8027c478bd9Sstevel@tonic-gate 		krb5_free_unparsed_name(k5.ctx, k5.name);
8037c478bd9Sstevel@tonic-gate 	if (k5.me)
8047c478bd9Sstevel@tonic-gate 		krb5_free_principal(k5.ctx, k5.me);
8057c478bd9Sstevel@tonic-gate 	if (k5.cc)
8067c478bd9Sstevel@tonic-gate 		krb5_cc_close(k5.ctx, k5.cc);
8077c478bd9Sstevel@tonic-gate 	if (k5.ctx)
8087c478bd9Sstevel@tonic-gate 		krb5_free_context(k5.ctx);
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	set_warnd_uid(saved_u);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
8137c478bd9Sstevel@tonic-gate 		printf("renew end: code=%s, uid=%d\n", error_message(code),
81424da5b34Srie 		    app_krb5_user_uid());
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	return (code);
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate static bool_t
loggedon(char * name)8207c478bd9Sstevel@tonic-gate loggedon(char *name)
8217c478bd9Sstevel@tonic-gate {
8227c478bd9Sstevel@tonic-gate 	register struct utmpx *ubuf;
8237c478bd9Sstevel@tonic-gate 	char    *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL;
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	/*
8267c478bd9Sstevel@tonic-gate 	 * strip any realm or instance from principal so we can match
8277c478bd9Sstevel@tonic-gate 	 * against unix userid.
8287c478bd9Sstevel@tonic-gate 	 */
8297c478bd9Sstevel@tonic-gate 	rcp1 = strdup(name);
8307c478bd9Sstevel@tonic-gate 	if (!rcp1)
8317c478bd9Sstevel@tonic-gate 		return (FALSE);
8327c478bd9Sstevel@tonic-gate 	rcp2 = strtok(rcp1, "@");
8337c478bd9Sstevel@tonic-gate 	rcp3 = strtok(rcp2, "/");
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	/*
8367c478bd9Sstevel@tonic-gate 	 * Scan through the "utmpx" file for the
8377c478bd9Sstevel@tonic-gate 	 * entry for the person we want to send to.
8387c478bd9Sstevel@tonic-gate 	 */
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 	setutxent();
8417c478bd9Sstevel@tonic-gate 	while ((ubuf = getutxent()) != NULL) {
8427c478bd9Sstevel@tonic-gate 		if (ubuf->ut_type == USER_PROCESS) {
8437c478bd9Sstevel@tonic-gate 			if (strncmp(rcp3, ubuf->ut_user,
8447c478bd9Sstevel@tonic-gate 				    sizeof (ubuf->ut_user)) == 0) {
8457c478bd9Sstevel@tonic-gate 				free(rcp1);
8467c478bd9Sstevel@tonic-gate 				endutxent();
8477c478bd9Sstevel@tonic-gate 				return (TRUE);
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 			}
8507c478bd9Sstevel@tonic-gate 		}
8517c478bd9Sstevel@tonic-gate 	}
8527c478bd9Sstevel@tonic-gate 	free(rcp1);
8537c478bd9Sstevel@tonic-gate 	endutxent();
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
8567c478bd9Sstevel@tonic-gate 		printf("loggedon: returning false for user `%s'\n", rcp1);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	return (FALSE);
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate  * main loop to check the cred warning list and send the warnings
8637c478bd9Sstevel@tonic-gate  * the appropriate location based on warn.conf or auto-renew creds.
8647c478bd9Sstevel@tonic-gate  */
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate void
kwarnd_check_warning_list(void)8677c478bd9Sstevel@tonic-gate kwarnd_check_warning_list(void)
8687c478bd9Sstevel@tonic-gate { /* func */
8697c478bd9Sstevel@tonic-gate 	cred_warning_list_t	*cw;  /* cred warning */
8707c478bd9Sstevel@tonic-gate 	config_entry_list_t	*ce;  /* config entry */
8717c478bd9Sstevel@tonic-gate 	time_t			now;
8727c478bd9Sstevel@tonic-gate 	int			minutes;
8737c478bd9Sstevel@tonic-gate 	char			buff[256];
8747c478bd9Sstevel@tonic-gate 	char			cmdline[256];
8757c478bd9Sstevel@tonic-gate 	FILE			*fp;
8767c478bd9Sstevel@tonic-gate 	char			*subj = "Kerberos credentials expiring";
8777c478bd9Sstevel@tonic-gate 	char			*renew_subj = "Kerberos credentials renewed";
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	if (kwarnd_debug)
88024da5b34Srie 		printf("check list: start: uid=%d, cw list=%p\n",
88124da5b34Srie 		    app_krb5_user_uid(), cred_warning_list);
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	while (1) {
884*b89e8170SToomas Soome 		(void) poll(NULL, 0, 60000);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 		for (cw = cred_warning_list;
8877c478bd9Sstevel@tonic-gate 			cw != NULL;
8887c478bd9Sstevel@tonic-gate 			cw = cw->next) {
8897c478bd9Sstevel@tonic-gate 			int send_msg = 0;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 			time(&now);
8927c478bd9Sstevel@tonic-gate 			if (now >= cw->cred_warn_time) {
8937c478bd9Sstevel@tonic-gate 				int renew_attempted = 0;
8947c478bd9Sstevel@tonic-gate 				int renew_failed = 0;
8957c478bd9Sstevel@tonic-gate 				int renew_tooclose = 0;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 				if (kwarnd_debug)
8987c478bd9Sstevel@tonic-gate 					printf("checklist: now >= warn_t\n");
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 				ce = find_warning_info(cw->warn_name);
9017c478bd9Sstevel@tonic-gate 				minutes = (cw->cred_exp_time -
9027c478bd9Sstevel@tonic-gate 					now + 59) / 60;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 				if (kwarnd_debug)
9057c478bd9Sstevel@tonic-gate 					printf("checklist: where_to=%s\n",
9067c478bd9Sstevel@tonic-gate 					    ce->where_to ?
9077c478bd9Sstevel@tonic-gate 					    ce->where_to : "null");
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 				if (ce->renew &&
9107c478bd9Sstevel@tonic-gate 				    loggedon(cw->warn_name)) {
9117c478bd9Sstevel@tonic-gate 					krb5_error_code code;
9127c478bd9Sstevel@tonic-gate 					time_t new_exp_time;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 					renew_attempted = 1;
9157c478bd9Sstevel@tonic-gate 					code = renew_creds(
9167c478bd9Sstevel@tonic-gate 						cw->warn_name,
9177c478bd9Sstevel@tonic-gate 						&new_exp_time);
9187c478bd9Sstevel@tonic-gate 					if (!code) {
9197c478bd9Sstevel@tonic-gate 						/* krb5 api renew success */
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 						/*
9227c478bd9Sstevel@tonic-gate 						 * So we had api success
9237c478bd9Sstevel@tonic-gate 						 * but the new exp time
9247c478bd9Sstevel@tonic-gate 						 * is same as current one
9257c478bd9Sstevel@tonic-gate 						 * so we are too close
9267c478bd9Sstevel@tonic-gate 						 * to Renewable_life time.
9277c478bd9Sstevel@tonic-gate 						 */
9287c478bd9Sstevel@tonic-gate 						if (cw->cred_exp_time
9297c478bd9Sstevel@tonic-gate 						    == new_exp_time) {
9307c478bd9Sstevel@tonic-gate 							renew_tooclose = 1;
9317c478bd9Sstevel@tonic-gate 							if (kwarnd_debug)
9327c478bd9Sstevel@tonic-gate 								printf(
9337c478bd9Sstevel@tonic-gate 		"checklist: new expire time same as old expire time\n");
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 							if (ce->log_failure) {
9367c478bd9Sstevel@tonic-gate 								send_msg = 1;
9377c478bd9Sstevel@tonic-gate 								snprintf(buff,
9387c478bd9Sstevel@tonic-gate 								sizeof (buff),
9397c478bd9Sstevel@tonic-gate 					gettext("%s:\r\nYour kerberos"
9407c478bd9Sstevel@tonic-gate 					" credentials have not been renewed"
9417c478bd9Sstevel@tonic-gate 					" (too close to Renewable_life).\r\n"
9427c478bd9Sstevel@tonic-gate 					"Please run kinit(1).\r\n"),
9437c478bd9Sstevel@tonic-gate 								cw->warn_name);
9447c478bd9Sstevel@tonic-gate 							}
9457c478bd9Sstevel@tonic-gate 						} else {
9467c478bd9Sstevel@tonic-gate 							/* update times */
9477c478bd9Sstevel@tonic-gate 							cw->cred_exp_time =
9487c478bd9Sstevel@tonic-gate 								new_exp_time;
9497c478bd9Sstevel@tonic-gate 							cw->cred_warn_time =
9507c478bd9Sstevel@tonic-gate 							    new_exp_time -
9517c478bd9Sstevel@tonic-gate 							    ce->seconds_to_warn;
9527c478bd9Sstevel@tonic-gate 						}
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 						if (kwarnd_debug)
9557c478bd9Sstevel@tonic-gate 							printf(
9567c478bd9Sstevel@tonic-gate 						    "check list: new_w_t=%d\n",
9577c478bd9Sstevel@tonic-gate 						    cw->cred_warn_time);
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 						if (!renew_tooclose &&
9607c478bd9Sstevel@tonic-gate 						    ce->log_success) {
9617c478bd9Sstevel@tonic-gate 							if (kwarnd_debug)
9627c478bd9Sstevel@tonic-gate 								printf(
9637c478bd9Sstevel@tonic-gate 						"check list: log success\n");
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 							send_msg = 1;
9667c478bd9Sstevel@tonic-gate 							snprintf(buff,
9677c478bd9Sstevel@tonic-gate 								sizeof (buff),
9687c478bd9Sstevel@tonic-gate 						gettext("%s:\r\nYour kerberos"
9697c478bd9Sstevel@tonic-gate 					" credentials have been renewed.\r\n"),
9707c478bd9Sstevel@tonic-gate 								cw->warn_name);
9717c478bd9Sstevel@tonic-gate 						}
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 					}  /* !(code) */
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 					if (!renew_tooclose && code &&
9767c478bd9Sstevel@tonic-gate 					    ce->log_failure) {
9777c478bd9Sstevel@tonic-gate 						if (kwarnd_debug)
9787c478bd9Sstevel@tonic-gate 							printf(
9797c478bd9Sstevel@tonic-gate 						"check list: log FAIL\n");
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 						send_msg = 1;
9827c478bd9Sstevel@tonic-gate 						snprintf(buff,
9837c478bd9Sstevel@tonic-gate 							sizeof (buff),
9847c478bd9Sstevel@tonic-gate 					    gettext("%s:\r\nYour kerberos"
9857c478bd9Sstevel@tonic-gate 				" credentials failed to be renewed (%s).\r\n"),
9867c478bd9Sstevel@tonic-gate 							cw->warn_name,
9877c478bd9Sstevel@tonic-gate 							error_message(code));
9887c478bd9Sstevel@tonic-gate 					}
9897c478bd9Sstevel@tonic-gate 					renew_failed = code ? 1 : 0;
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 				} else if (minutes > 0) {
9927c478bd9Sstevel@tonic-gate 					send_msg = 1;
9937c478bd9Sstevel@tonic-gate 					snprintf(buff, sizeof (buff),
9947c478bd9Sstevel@tonic-gate 					gettext("%s:\r\nyour kerberos"
9957c478bd9Sstevel@tonic-gate 					" credentials expire in less than"
9967c478bd9Sstevel@tonic-gate 					" %d minutes.\r\n"),
9977c478bd9Sstevel@tonic-gate 					cw->warn_name,
9987c478bd9Sstevel@tonic-gate 					minutes);
9997c478bd9Sstevel@tonic-gate 				} else {
10007c478bd9Sstevel@tonic-gate 					send_msg = 1;
10017c478bd9Sstevel@tonic-gate 					snprintf(buff, sizeof (buff),
10027c478bd9Sstevel@tonic-gate 					gettext("%s:\r\nyour kerberos"
10037c478bd9Sstevel@tonic-gate 					" credentials have expired.\r\n"),
10047c478bd9Sstevel@tonic-gate 					cw->warn_name);
10057c478bd9Sstevel@tonic-gate 				}
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 				if (kwarnd_debug)
10087c478bd9Sstevel@tonic-gate 					printf("checklist: send_msg=%d\n",
10097c478bd9Sstevel@tonic-gate 					    send_msg);
10107c478bd9Sstevel@tonic-gate 				if (!send_msg)
10117c478bd9Sstevel@tonic-gate 					goto del_warning;
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 				if (strncmp(ce->where_to,
10147c478bd9Sstevel@tonic-gate 					    "mail", sizeof ("mail")) == 0) {
10157c478bd9Sstevel@tonic-gate 					char *argv[3];
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 					argv[0] = MAIL;
10187c478bd9Sstevel@tonic-gate 					(void) snprintf(cmdline,
10197c478bd9Sstevel@tonic-gate 							sizeof (cmdline),
10207c478bd9Sstevel@tonic-gate 							"%s",
10217c478bd9Sstevel@tonic-gate 							ce->email);
10227c478bd9Sstevel@tonic-gate 					argv[1] = cmdline;
10237c478bd9Sstevel@tonic-gate 					argv[2] = NULL;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 					fp = safe_popen_w(MAILPATH, argv);
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 					if (fp) {
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 						(void) fprintf(fp,
10307c478bd9Sstevel@tonic-gate 						"To: %s\nSubject: %s\n\n%s\n",
10317c478bd9Sstevel@tonic-gate 							    ce->email,
10327c478bd9Sstevel@tonic-gate 							    renew_attempted
10337c478bd9Sstevel@tonic-gate 							    ? renew_subj : subj,
10347c478bd9Sstevel@tonic-gate 							    buff);
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 					    fclose(fp);
10377c478bd9Sstevel@tonic-gate 					} else {
10387c478bd9Sstevel@tonic-gate 					    syslog(LOG_ERR,
10397c478bd9Sstevel@tonic-gate 						gettext("could not fork "
10407c478bd9Sstevel@tonic-gate 						"mail program to e-mail "
10417c478bd9Sstevel@tonic-gate 						"warning to %s\n"),
10427c478bd9Sstevel@tonic-gate 						cmdline);
10437c478bd9Sstevel@tonic-gate 					}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 				} else if (strncmp(ce->where_to,
10467c478bd9Sstevel@tonic-gate 						"terminal",
10477c478bd9Sstevel@tonic-gate 						sizeof ("terminal")) == 0) {
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 					warn_send(cw->warn_name,
10507c478bd9Sstevel@tonic-gate 						buff);
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 				} else if (send_msg && strncmp(ce->where_to,
10537c478bd9Sstevel@tonic-gate 							    "syslog",
10547c478bd9Sstevel@tonic-gate 						sizeof ("syslog")) == 0) {
10557c478bd9Sstevel@tonic-gate 					syslog(LOG_NOTICE|LOG_AUTH,
10567c478bd9Sstevel@tonic-gate 					    "%s",
10577c478bd9Sstevel@tonic-gate 					    buff);
10587c478bd9Sstevel@tonic-gate #if 0
10597c478bd9Sstevel@tonic-gate 				} else if (strncmp(ce->where_to,
10607c478bd9Sstevel@tonic-gate 						"snmp",
10617c478bd9Sstevel@tonic-gate 						sizeof ("snmp")) == 0) {
10627c478bd9Sstevel@tonic-gate #endif
10637c478bd9Sstevel@tonic-gate 				} else {
10647c478bd9Sstevel@tonic-gate 					if (kwarnd_debug)
10657c478bd9Sstevel@tonic-gate 						printf(
10667c478bd9Sstevel@tonic-gate 						"unknown msg method=`%s'\n",
10677c478bd9Sstevel@tonic-gate 						ce->where_to);
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 					exit(1);
10707c478bd9Sstevel@tonic-gate 				}
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 			del_warning:
10737c478bd9Sstevel@tonic-gate 				if (!renew_attempted || renew_failed ||
10747c478bd9Sstevel@tonic-gate 				    renew_tooclose) {
10757c478bd9Sstevel@tonic-gate 					if (del_warning_pvt(cw->warn_name)
10767c478bd9Sstevel@tonic-gate 					    == TRUE) {
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 						if (kwarnd_debug)
10797c478bd9Sstevel@tonic-gate 							printf(
10807c478bd9Sstevel@tonic-gate 						"check list: del warn succ\n");
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 						break;
10837c478bd9Sstevel@tonic-gate 					} else {
10847c478bd9Sstevel@tonic-gate 						if (kwarnd_debug)
10857c478bd9Sstevel@tonic-gate 							printf(
10867c478bd9Sstevel@tonic-gate 						"could not delete warning\n");
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 						syslog(LOG_ERR, gettext(
10897c478bd9Sstevel@tonic-gate 						"could not delete warning"));
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 						exit(1);
10927c478bd9Sstevel@tonic-gate 					    }
10937c478bd9Sstevel@tonic-gate 					}
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 				} /* if (now) */
10967c478bd9Sstevel@tonic-gate 		} /* for */
10977c478bd9Sstevel@tonic-gate 	} /* while */
10987c478bd9Sstevel@tonic-gate }  /* func */
1099