dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / krb5 / kwarn / kwarnd_proc.c
blobbe4e18dd31aeaed04d3d2a6dabed5c0042e49344
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * RPC server procedures for the usermode daemon kwarnd.
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <strings.h>
35 #include <string.h>
36 #include <sys/param.h>
37 #include <sys/syslog.h>
38 #include "kwarnd.h"
39 #include <rpc/rpc.h>
40 #include <stdlib.h>
41 #include <syslog.h>
42 #include <poll.h>
43 #include <utmpx.h>
44 #include <pwd.h>
45 #include <strings.h>
46 #include <ctype.h>
48 #include <k5-int.h>
49 #include <profile/prof_int.h>
50 #include <com_err.h>
51 #include <libintl.h>
52 #include <krb5.h>
54 extern char progname[];
56 struct k5_data
58 krb5_context ctx;
59 krb5_ccache cc;
60 krb5_principal me;
61 char *name;
65 #define MAIL "mail"
66 #define MAILPATH "/usr/bin/mail"
67 #define DEFAULT_CONFIG "* terminal 30m"
68 #define CONF_FILENAME "/etc/krb5/warn.conf"
70 /* warn.conf info */
72 typedef struct config_entry_s {
73 struct config_entry_s *next;
74 int seconds_to_warn;
75 char *principal;
76 char *where_to;
77 char *email;
78 int renew;
79 int log_success;
80 int log_failure;
81 } config_entry_list_t;
82 static config_entry_list_t *config_entry_list;
84 /* list of principals to be warned */
86 typedef struct cred_warning_list_s {
87 struct cred_warning_list_s *next;
88 WARNING_NAME_T warn_name;
89 time_t cred_exp_time;
90 time_t cred_warn_time;
91 mutex_t cwm;
92 } cred_warning_list_t;
93 static cred_warning_list_t *cred_warning_list;
94 static rwlock_t cred_lock = DEFAULTRWLOCK;
96 static bool_t
97 del_warning_pvt(char *);
99 static config_entry_list_t *
100 find_warning_info(char *);
102 static bool_t
103 parseConfigLine(char *buffer);
105 extern int warn_send(char *, char *);
107 extern int kwarnd_debug;
109 cred_warning_list_t *
110 find_cred_warning(WARNING_NAME_T warn_name)
112 cred_warning_list_t *cw;
113 if (!cred_warning_list)
114 return (NULL);
115 for (cw = cred_warning_list; cw != NULL; cw = cw->next) {
116 if (strcmp(warn_name, cw->warn_name) != 0)
117 continue;
118 return (cw);
120 return (NULL);
124 * add a principal to the principal warning list
127 bool_t
128 kwarn_add_warning_1_svc(kwarn_add_warning_arg *argp,
129 kwarn_add_warning_res *res,
130 struct svc_req *rqstp)
132 cred_warning_list_t *cred_warning;
133 config_entry_list_t *config_entry;
135 if (kwarnd_debug) {
136 printf("kwarn_add_warning_1_svc start; cWlist=%p\n",
137 cred_warning_list);
139 printf("kwarn_add_warning_1_svc: principal %s",
140 argp->warning_name);
141 printf(" exp time: %d\n", argp->cred_exp_time);
145 * if there is no entry in the config file that matches the principal to
146 * be added to the warning list, return true because we are not going to
147 * send a warning for this principal.
150 if ((config_entry = find_warning_info(argp->warning_name)) == NULL) {
151 if (kwarnd_debug)
152 printf(
153 "kwarn_add_warning_1_svc find_warn_info: fails, cWlist=%p\n",
154 cred_warning_list);
156 return (TRUE);
160 * see if a warning has already been created for this principal, if so
161 * update the warning time.
164 rw_wrlock(&cred_lock);
165 if (cred_warning = find_cred_warning(argp->warning_name)) {
166 rw_unlock(&cred_lock);
167 mutex_lock(&cred_warning->cwm);
168 cred_warning->cred_exp_time = argp->cred_exp_time;
169 cred_warning->cred_warn_time = argp->cred_exp_time
170 - config_entry->seconds_to_warn;
171 mutex_unlock(&cred_warning->cwm);
172 } else {
173 cred_warning = (cred_warning_list_t *)malloc(
174 sizeof (*cred_warning_list));
175 if (cred_warning == NULL) {
176 rw_unlock(&cred_lock);
177 res->status = 1;
178 return (FALSE);
180 (void) memset((char *)cred_warning, 0,
181 sizeof (*cred_warning_list));
182 cred_warning->cred_exp_time = argp->cred_exp_time;
183 cred_warning->cred_warn_time = argp->cred_exp_time
184 - config_entry->seconds_to_warn;
185 cred_warning->warn_name = strdup(argp->warning_name);
186 if (cred_warning->warn_name == NULL) {
187 free(cred_warning);
188 rw_unlock(&cred_lock);
189 res->status = 1;
190 return (FALSE);
192 mutex_init(&cred_warning->cwm, USYNC_THREAD, NULL);
193 cred_warning->next = cred_warning_list;
194 cred_warning_list = cred_warning;
195 rw_unlock(&cred_lock);
197 res->status = 0;
199 if (kwarnd_debug)
200 printf(
201 "kwarn_add_warning_1_svc end: returns true; cWlist=%p\n",
202 cred_warning_list);
204 return (TRUE);
208 * delete a warning request for a given principal
211 bool_t
212 kwarn_del_warning_1_svc(kwarn_del_warning_arg *argp,
213 kwarn_del_warning_res *res,
214 struct svc_req *rqstp)
216 if (kwarnd_debug)
217 printf(gettext("delete principal %s requested\n"),
218 argp->warning_name);
220 if (del_warning_pvt(argp->warning_name) == TRUE) {
221 res->status = 0;
223 if (kwarnd_debug)
224 printf(gettext("delete principal %s completed\n"),
225 argp->warning_name);
227 return (TRUE);
228 } else {
229 res->status = 1;
231 if (kwarnd_debug)
232 printf(gettext("delete principal %s failed\n"),
233 argp->warning_name);
235 return (TRUE);
239 static bool_t
240 del_warning_pvt(char *warning_name)
242 cred_warning_list_t *cred_warning, *prev;
243 rw_wrlock(&cred_lock);
244 for (prev = NULL, cred_warning = cred_warning_list;
245 cred_warning != NULL; prev = cred_warning,
246 cred_warning = cred_warning->next) {
247 if (strcmp(cred_warning->warn_name, warning_name) == 0) {
248 if (!prev)
249 cred_warning_list = cred_warning->next;
250 else
251 prev->next = cred_warning->next;
253 free(cred_warning->warn_name);
254 free(cred_warning);
255 rw_unlock(&cred_lock);
256 return (TRUE);
259 rw_unlock(&cred_lock);
260 return (FALSE);
264 * load the warn.conf file into the config_entry list.
267 bool_t
268 loadConfigFile(void)
270 char buffer[BUFSIZ];
271 FILE *cfgfile;
272 bool_t retval = TRUE;
274 if ((cfgfile = fopen(CONF_FILENAME, "r")) == NULL) {
275 syslog(LOG_ERR, gettext(
276 "could not open config file \"%s\"\n"),
277 CONF_FILENAME);
278 syslog(LOG_ERR, gettext(
279 "using default options \"%s\"\n"),
280 DEFAULT_CONFIG);
281 retval = parseConfigLine(DEFAULT_CONFIG);
282 } else {
283 (void) memset(buffer, 0, sizeof (buffer));
284 while ((fgets(buffer, BUFSIZ, cfgfile) != NULL) &&
285 (retval == TRUE))
286 retval = parseConfigLine(buffer);
287 fclose(cfgfile);
289 return (retval);
293 * Return TRUE if we get a valid opt and update flags appro.
295 static bool_t
296 cmp_renew_opts(char *opt,
297 int *log_success, /* out */
298 int *log_failure) /* out */
301 if (strncasecmp(opt, "log",
302 sizeof ("log")) == 0) {
303 *log_success = *log_failure = 1;
304 } else if (strncasecmp(opt, "log-success",
305 sizeof ("log-success")) == 0) {
306 *log_success = 1;
307 } else if (strncasecmp(opt, "log-failure",
308 sizeof ("log-failure")) == 0) {
309 *log_failure = 1;
310 } else {
311 if (kwarnd_debug)
312 printf("cmp_renew_opts: renew bad opt=`%s'\n",
313 opt ? opt : "null");
314 return (FALSE);
317 return (TRUE);
321 * Make the config_entry item for the config_entry_list, based on
322 * buffer. The formats are
324 * <principal> [renew[:<opt1,...optN>]] syslog|terminal <time>
325 * <principal> [renew[:<opt1,...optN>]] mail <time> <e-mail address>
327 * where renew opts will be:
329 * log-success
330 * - Log the result of the renew attempt on success using
331 * the specified method (syslog|terminal|mail)
333 * log-failure
334 * - Log the result of the renew attempt on failure using
335 * the specified method (syslog|terminal|mail)
337 * log
338 * - Same as specifing both log-failure and log-success
340 * Note if no log options are given, there will be no logging.
344 static bool_t
345 parseConfigLine(char *buffer)
347 char *principal, *send_to, *emailid, *ends, *tm;
348 char *exptime;
349 int time_mode;
350 time_t etime;
351 config_entry_list_t *config_entry;
352 int renew = 0;
353 int log_success = 0;
354 int log_failure = 0;
356 /* ignore comments */
357 if (*buffer == '#')
358 return (TRUE);
360 if (kwarnd_debug)
361 printf("parseconf: buffer=%s", buffer);
363 /* find end of principal */
364 principal = buffer;
365 for (send_to = buffer; *send_to && !isspace(*send_to);
366 send_to++);
368 /* find first non whitespace after principal (start of send_to) */
369 if (*send_to) {
370 *send_to = '\0';
371 send_to++;
372 while (*send_to && isspace(*send_to))
373 send_to++;
376 /* if no send_to, continue, bad entry */
377 if (! *send_to)
378 return (TRUE);
380 /* find end of send_to */
381 for (ends = send_to; *ends && !isspace(*ends);
382 ends++);
383 if (*ends)
384 *ends = '\0';
387 if (strchr(send_to, ':')) {
388 /* we've got renew opts */
389 char *st = NULL, *op = NULL;
391 op = strdup(send_to);
392 if (!op)
393 return (FALSE);
394 st = strchr(op, ':');
395 *st = '\0';
397 if (strncasecmp(op, "renew", sizeof ("renew")) == 0) {
398 renew = 1;
399 } else {
400 free(op);
401 /* got a ':' but not preceeded w/renew, badent, skip */
402 if (kwarnd_debug)
403 printf("parseconf: colon badent, skip\n");
404 return (TRUE);
406 free(op);
407 op = NULL;
409 st++;
410 if (!st || !*st || isspace(*st)) {
411 if (kwarnd_debug)
412 printf("parseconf: st badent, skip\n");
413 /* bad ent, skip */
414 return (TRUE);
416 if (renew && strchr(st, ',')) {
417 while (1) {
418 /* loop thru comma seperated list-o-opts */
419 char *comma = NULL, *c = NULL, *l = NULL;
421 if (st && (comma = strchr(st, ','))) {
422 l = strdup(st);
423 if (!l)
424 return (FALSE);
425 c = strchr(l, ',');
426 *c = '\0';
427 if (!cmp_renew_opts(l, &log_success,
428 &log_failure)) {
429 free(l);
430 /* badent, skip */
431 return (TRUE);
433 free(l);
434 l = NULL;
436 st = comma;
437 st++;
438 } else {
439 if (st) {
440 if (!cmp_renew_opts(st,
441 &log_success,
442 &log_failure)) {
443 /* badent, skip */
444 return (TRUE);
447 break;
449 } /* while */
450 } else if (st) {
451 /* we just have one opt */
452 if (!cmp_renew_opts(st, &log_success, &log_failure)) {
453 /* badent, skip */
454 return (TRUE);
458 /* if send_to is "renew", note it and refind send_to */
459 } else if (strncasecmp(send_to, "renew",
460 sizeof ("renew")) == 0) {
461 renew = 1;
465 if (kwarnd_debug) {
466 printf("parseconf: renew=%d, log failure=%d, log success=%d\n",
467 renew, log_failure, log_success);
470 if (renew) {
471 /* find first non whitespace after send_to (start of exptime) */
472 for (send_to = ends+1; *send_to && isspace(*send_to);
473 send_to++);
475 /* if no send_to, continue, bad entry */
476 if (! *send_to) {
477 if (kwarnd_debug)
478 printf("parseconf: no send_to, badent, skip\n");
479 return (TRUE);
482 /* find end of send_to */
483 for (ends = send_to; *ends && !isspace(*ends);
484 ends++);
485 if (*ends)
486 *ends = '\0';
490 /* find first non whitespace after send_to (start of exptime) */
491 for (exptime = ends+1; *exptime && isspace(*exptime);
492 exptime++);
494 /* if no exptime, continue, bad entry */
495 if (! *exptime) {
496 if (kwarnd_debug)
497 printf("parseconf: no exptime, badent, skip\n");
498 return (TRUE);
501 /* find end of exptime */
502 for (ends = exptime; *ends && !isspace(*ends); ends++);
504 tm = ends - 1;
505 if (*tm == 's')
506 time_mode = 1;
507 else if (*tm == 'm')
508 time_mode = 2;
509 else if (*tm == 'h')
510 time_mode = 3;
511 else
512 time_mode = 1;
514 if (*tm)
515 *tm = '\0';
517 if (kwarnd_debug) {
518 printf("parseconf: send_to = '%s', exptime='%s'\n",
519 send_to, exptime);
522 /* find first non whitespace after exptime (start of emailid) */
523 for (emailid = ends+1; *emailid && isspace(*emailid); emailid++);
525 /* find end of emailid */
526 if (*emailid) {
527 for (ends = emailid; *ends && !isspace(*ends);
528 ends++);
530 if (*ends)
531 *ends = '\0';
534 /* if send to mail and no mail address, bad entry */
535 if ((strcmp(send_to, "mail") == 0) && (!*emailid)) {
536 if (kwarnd_debug)
537 printf("parseconf: returns true; no mail addr\n");
539 syslog(LOG_ERR, gettext("missing mail address"
540 " in config entry: \n%s %s %s "
541 " cannot mail warning"), principal,
542 send_to, exptime);
543 return (TRUE);
546 /* create an entry */
547 config_entry = (config_entry_list_t *)
548 malloc(sizeof (*config_entry_list));
549 if (config_entry == NULL)
550 return (FALSE);
551 (void) memset(config_entry, 0, sizeof (*config_entry_list));
552 config_entry->principal = strdup(principal);
553 if (config_entry->principal == NULL)
554 return (FALSE);
555 config_entry->where_to = strdup(send_to);
556 if (config_entry->where_to == NULL)
557 return (FALSE);
558 etime = atol(exptime);
559 if (time_mode == 1)
560 config_entry->seconds_to_warn = etime;
561 else if (time_mode == 2)
562 config_entry->seconds_to_warn = etime * 60;
563 else if (time_mode == 3)
564 config_entry->seconds_to_warn = etime * 60 * 60;
566 if (*emailid) {
567 config_entry->email = strdup(emailid);
568 if (config_entry->email == NULL)
569 return (FALSE);
572 config_entry->renew = renew;
573 config_entry->log_success = log_success;
574 config_entry->log_failure = log_failure;
575 config_entry->next = config_entry_list;
576 config_entry_list = config_entry;
577 if (kwarnd_debug)
578 printf("parseconf: returns true; celist=%p\n",
579 config_entry_list);
581 return (TRUE);
585 * find a specific warn.conf entry.
588 static config_entry_list_t *
589 find_warning_info(char *principal)
591 config_entry_list_t *config_entry;
592 /* look for a specific entry */
593 for (config_entry = config_entry_list; config_entry;
594 config_entry = config_entry->next) {
595 if (strcmp(config_entry->principal, principal) == 0) {
596 return (config_entry);
599 /* look for a wild card entry */
600 for (config_entry = config_entry_list; config_entry;
601 config_entry = config_entry->next) {
602 if (strcmp(config_entry->principal, "*") == 0) {
603 return (config_entry);
606 /* nothing found */
607 return (NULL);
612 * create a pipe, fork and exec a command,
614 static FILE *
615 safe_popen_w(char *path_to_cmd, char **argv)
618 int fd[2];
619 FILE *fp;
620 char *envp[2];
622 if (pipe(fd) == -1)
623 return (NULL);
626 switch (fork()) {
627 case -1:
628 (void) close(fd[0]);
629 (void) close(fd[1]);
630 return (NULL);
632 case 0:
633 close(fd[1]);
634 /* fd[0] is the end we read from */
635 if (fd[0] != 0) {
636 close(0);
637 dup(fd[0]);
639 close(1);
640 close(2);
641 envp[0] = "PATH=/usr/bin";
642 envp[1] = NULL;
643 #ifdef DEBUG
645 int fd;
646 fd = open("/tmp/kwarn.out", O_WRONLY|O_TRUNC|O_CREAT,
647 0666);
648 if (fd != 1)
649 dup(fd);
650 if (fd != 2)
651 dup(fd);
653 #endif
654 (void) execve(path_to_cmd, argv, envp);
655 syslog(LOG_ERR, "warnd: %m");
656 _exit(1);
658 default:
659 close(fd[0]);
660 /* fd[1] is the end we write to */
662 fp = fdopen(fd[1], "w");
664 if (fp == NULL) {
665 (void) close(fd[1]);
666 return (NULL);
668 return (fp);
673 static uid_t krb5_cc_uid;
675 void
676 set_warnd_uid(uid_t uid)
679 * set the value of krb5_cc_uid, so it can be retrieved when
680 * app_krb5_user_uid() is called by the underlying mechanism libraries.
682 if (kwarnd_debug)
683 printf("set_warnd_uid called with uid = %d\n", uid);
684 krb5_cc_uid = uid;
687 uid_t
688 app_krb5_user_uid(void)
692 * return the value set when one of the kwarnd procedures was
693 * entered. This is the value of the uid under which the
694 * underlying mechanism library must operate in order to
695 * get the user's credentials. This call is necessary since
696 * kwarnd runs as root and credentials are many times stored
697 * in files and directories specific to the user
699 if (kwarnd_debug)
700 printf("app_krb5_user_uid called and returning uid = %d\n",
701 krb5_cc_uid);
702 return (krb5_cc_uid);
706 static bool_t
707 getpruid(char *pr, uid_t *uid)
709 char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL;
710 struct passwd *pw;
712 rcp1 = strdup(pr);
713 if (!rcp1)
714 return (FALSE);
715 rcp2 = strtok(rcp1, "@");
716 rcp3 = strtok(rcp2, "/");
718 if (rcp3) {
719 pw = getpwnam(rcp3);
720 *uid = pw->pw_uid;
721 free(rcp1);
722 return (TRUE);
725 free(rcp1);
726 return (FALSE);
730 static krb5_error_code
731 renew_creds(
732 char *princ,
733 time_t *new_exp_time) /* out */
735 krb5_creds my_creds;
736 krb5_error_code code = 0;
737 struct k5_data k5;
739 uid_t saved_u = app_krb5_user_uid();
740 uid_t u;
742 if (kwarnd_debug)
743 printf("renew start: uid=%d\n", app_krb5_user_uid());
745 if (!getpruid(princ, &u)) {
746 if (kwarnd_debug)
747 printf("renew: getpruid failed, princ='%s'\n",
748 princ ? princ : "<null>");
750 return (-1); /* better err num? */
753 set_warnd_uid(u);
755 (void) memset(&my_creds, 0, sizeof (my_creds));
756 (void) memset(&k5, 0, sizeof (k5));
758 if (code = krb5_init_context(&k5.ctx)) {
759 com_err(progname, code,
760 gettext("while initializing Kerberos 5 library"));
761 goto out;
764 if ((code = krb5_cc_default(k5.ctx, &k5.cc))) {
765 com_err(progname, code,
766 gettext("while getting default ccache"));
767 goto out;
771 if ((code = krb5_parse_name(k5.ctx, princ,
772 &k5.me))) {
773 com_err(progname, code, gettext("when parsing name %s"),
774 princ);
775 goto out;
778 if ((code = krb5_get_renewed_creds(k5.ctx, &my_creds, k5.me, k5.cc,
779 NULL))) {
780 com_err(progname, code, gettext("while renewing creds"));
781 goto out;
784 if (code = krb5_cc_initialize(k5.ctx, k5.cc, k5.me)) {
785 com_err(progname, code, gettext("when initializing cache %s"),
786 "defcc");
787 goto out;
790 if (code = krb5_cc_store_cred(k5.ctx, k5.cc, &my_creds)) {
791 com_err(progname, code, gettext("while storing credentials"));
792 goto out;
795 /* "return" new expire time */
796 *new_exp_time = my_creds.times.endtime;
798 out:
799 krb5_free_cred_contents(k5.ctx, &my_creds);
801 if (k5.name)
802 krb5_free_unparsed_name(k5.ctx, k5.name);
803 if (k5.me)
804 krb5_free_principal(k5.ctx, k5.me);
805 if (k5.cc)
806 krb5_cc_close(k5.ctx, k5.cc);
807 if (k5.ctx)
808 krb5_free_context(k5.ctx);
810 set_warnd_uid(saved_u);
812 if (kwarnd_debug)
813 printf("renew end: code=%s, uid=%d\n", error_message(code),
814 app_krb5_user_uid());
816 return (code);
819 static bool_t
820 loggedon(char *name)
822 register struct utmpx *ubuf;
823 char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL;
826 * strip any realm or instance from principal so we can match
827 * against unix userid.
829 rcp1 = strdup(name);
830 if (!rcp1)
831 return (FALSE);
832 rcp2 = strtok(rcp1, "@");
833 rcp3 = strtok(rcp2, "/");
836 * Scan through the "utmpx" file for the
837 * entry for the person we want to send to.
840 setutxent();
841 while ((ubuf = getutxent()) != NULL) {
842 if (ubuf->ut_type == USER_PROCESS) {
843 if (strncmp(rcp3, ubuf->ut_user,
844 sizeof (ubuf->ut_user)) == 0) {
845 free(rcp1);
846 endutxent();
847 return (TRUE);
852 free(rcp1);
853 endutxent();
855 if (kwarnd_debug)
856 printf("loggedon: returning false for user `%s'\n", rcp1);
858 return (FALSE);
862 * main loop to check the cred warning list and send the warnings
863 * the appropriate location based on warn.conf or auto-renew creds.
866 void
867 kwarnd_check_warning_list(void)
868 { /* func */
869 cred_warning_list_t *cw; /* cred warning */
870 config_entry_list_t *ce; /* config entry */
871 time_t now;
872 int minutes;
873 char buff[256];
874 char cmdline[256];
875 FILE *fp;
876 char *subj = "Kerberos credentials expiring";
877 char *renew_subj = "Kerberos credentials renewed";
879 if (kwarnd_debug)
880 printf("check list: start: uid=%d, cw list=%p\n",
881 app_krb5_user_uid(), cred_warning_list);
883 while (1) {
884 (void) poll(NULL, 0, 60000);
886 for (cw = cred_warning_list;
887 cw != NULL;
888 cw = cw->next) {
889 int send_msg = 0;
891 time(&now);
892 if (now >= cw->cred_warn_time) {
893 int renew_attempted = 0;
894 int renew_failed = 0;
895 int renew_tooclose = 0;
897 if (kwarnd_debug)
898 printf("checklist: now >= warn_t\n");
900 ce = find_warning_info(cw->warn_name);
901 minutes = (cw->cred_exp_time -
902 now + 59) / 60;
904 if (kwarnd_debug)
905 printf("checklist: where_to=%s\n",
906 ce->where_to ?
907 ce->where_to : "null");
909 if (ce->renew &&
910 loggedon(cw->warn_name)) {
911 krb5_error_code code;
912 time_t new_exp_time;
914 renew_attempted = 1;
915 code = renew_creds(
916 cw->warn_name,
917 &new_exp_time);
918 if (!code) {
919 /* krb5 api renew success */
922 * So we had api success
923 * but the new exp time
924 * is same as current one
925 * so we are too close
926 * to Renewable_life time.
928 if (cw->cred_exp_time
929 == new_exp_time) {
930 renew_tooclose = 1;
931 if (kwarnd_debug)
932 printf(
933 "checklist: new expire time same as old expire time\n");
935 if (ce->log_failure) {
936 send_msg = 1;
937 snprintf(buff,
938 sizeof (buff),
939 gettext("%s:\r\nYour kerberos"
940 " credentials have not been renewed"
941 " (too close to Renewable_life).\r\n"
942 "Please run kinit(1).\r\n"),
943 cw->warn_name);
945 } else {
946 /* update times */
947 cw->cred_exp_time =
948 new_exp_time;
949 cw->cred_warn_time =
950 new_exp_time -
951 ce->seconds_to_warn;
954 if (kwarnd_debug)
955 printf(
956 "check list: new_w_t=%d\n",
957 cw->cred_warn_time);
959 if (!renew_tooclose &&
960 ce->log_success) {
961 if (kwarnd_debug)
962 printf(
963 "check list: log success\n");
965 send_msg = 1;
966 snprintf(buff,
967 sizeof (buff),
968 gettext("%s:\r\nYour kerberos"
969 " credentials have been renewed.\r\n"),
970 cw->warn_name);
973 } /* !(code) */
975 if (!renew_tooclose && code &&
976 ce->log_failure) {
977 if (kwarnd_debug)
978 printf(
979 "check list: log FAIL\n");
981 send_msg = 1;
982 snprintf(buff,
983 sizeof (buff),
984 gettext("%s:\r\nYour kerberos"
985 " credentials failed to be renewed (%s).\r\n"),
986 cw->warn_name,
987 error_message(code));
989 renew_failed = code ? 1 : 0;
991 } else if (minutes > 0) {
992 send_msg = 1;
993 snprintf(buff, sizeof (buff),
994 gettext("%s:\r\nyour kerberos"
995 " credentials expire in less than"
996 " %d minutes.\r\n"),
997 cw->warn_name,
998 minutes);
999 } else {
1000 send_msg = 1;
1001 snprintf(buff, sizeof (buff),
1002 gettext("%s:\r\nyour kerberos"
1003 " credentials have expired.\r\n"),
1004 cw->warn_name);
1007 if (kwarnd_debug)
1008 printf("checklist: send_msg=%d\n",
1009 send_msg);
1010 if (!send_msg)
1011 goto del_warning;
1013 if (strncmp(ce->where_to,
1014 "mail", sizeof ("mail")) == 0) {
1015 char *argv[3];
1017 argv[0] = MAIL;
1018 (void) snprintf(cmdline,
1019 sizeof (cmdline),
1020 "%s",
1021 ce->email);
1022 argv[1] = cmdline;
1023 argv[2] = NULL;
1025 fp = safe_popen_w(MAILPATH, argv);
1027 if (fp) {
1029 (void) fprintf(fp,
1030 "To: %s\nSubject: %s\n\n%s\n",
1031 ce->email,
1032 renew_attempted
1033 ? renew_subj : subj,
1034 buff);
1036 fclose(fp);
1037 } else {
1038 syslog(LOG_ERR,
1039 gettext("could not fork "
1040 "mail program to e-mail "
1041 "warning to %s\n"),
1042 cmdline);
1045 } else if (strncmp(ce->where_to,
1046 "terminal",
1047 sizeof ("terminal")) == 0) {
1049 warn_send(cw->warn_name,
1050 buff);
1052 } else if (send_msg && strncmp(ce->where_to,
1053 "syslog",
1054 sizeof ("syslog")) == 0) {
1055 syslog(LOG_NOTICE|LOG_AUTH,
1056 "%s",
1057 buff);
1058 #if 0
1059 } else if (strncmp(ce->where_to,
1060 "snmp",
1061 sizeof ("snmp")) == 0) {
1062 #endif
1063 } else {
1064 if (kwarnd_debug)
1065 printf(
1066 "unknown msg method=`%s'\n",
1067 ce->where_to);
1069 exit(1);
1072 del_warning:
1073 if (!renew_attempted || renew_failed ||
1074 renew_tooclose) {
1075 if (del_warning_pvt(cw->warn_name)
1076 == TRUE) {
1078 if (kwarnd_debug)
1079 printf(
1080 "check list: del warn succ\n");
1082 break;
1083 } else {
1084 if (kwarnd_debug)
1085 printf(
1086 "could not delete warning\n");
1088 syslog(LOG_ERR, gettext(
1089 "could not delete warning"));
1091 exit(1);
1095 } /* if (now) */
1096 } /* for */
1097 } /* while */
1098 } /* func */