1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* 9*0Sstevel@tonic-gate * RPC server procedures for the usermode daemon kwarnd. 10*0Sstevel@tonic-gate */ 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate #include <stdio.h> 13*0Sstevel@tonic-gate #include <unistd.h> 14*0Sstevel@tonic-gate #include <pwd.h> 15*0Sstevel@tonic-gate #include <grp.h> 16*0Sstevel@tonic-gate #include <strings.h> 17*0Sstevel@tonic-gate #include <string.h> 18*0Sstevel@tonic-gate #include <sys/param.h> 19*0Sstevel@tonic-gate #include <sys/syslog.h> 20*0Sstevel@tonic-gate #include "kwarnd.h" 21*0Sstevel@tonic-gate #include <rpc/rpc.h> 22*0Sstevel@tonic-gate #include <stdlib.h> 23*0Sstevel@tonic-gate #include <syslog.h> 24*0Sstevel@tonic-gate #include <poll.h> 25*0Sstevel@tonic-gate #include <utmpx.h> 26*0Sstevel@tonic-gate #include <pwd.h> 27*0Sstevel@tonic-gate #include <strings.h> 28*0Sstevel@tonic-gate #include <ctype.h> 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <k5-int.h> 31*0Sstevel@tonic-gate #include <profile/prof_int.h> 32*0Sstevel@tonic-gate #include <com_err.h> 33*0Sstevel@tonic-gate #include <libintl.h> 34*0Sstevel@tonic-gate #include <krb5.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate struct k5_data 37*0Sstevel@tonic-gate { 38*0Sstevel@tonic-gate krb5_context ctx; 39*0Sstevel@tonic-gate krb5_ccache cc; 40*0Sstevel@tonic-gate krb5_principal me; 41*0Sstevel@tonic-gate char *name; 42*0Sstevel@tonic-gate }; 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #define MAIL "mail" 46*0Sstevel@tonic-gate #define MAILPATH "/usr/bin/mail" 47*0Sstevel@tonic-gate #define DEFAULT_CONFIG "* terminal 30m" 48*0Sstevel@tonic-gate #define CONF_FILENAME "/etc/krb5/warn.conf" 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* warn.conf info */ 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate typedef struct config_entry_s { 53*0Sstevel@tonic-gate struct config_entry_s *next; 54*0Sstevel@tonic-gate int seconds_to_warn; 55*0Sstevel@tonic-gate char *principal; 56*0Sstevel@tonic-gate char *where_to; 57*0Sstevel@tonic-gate char *email; 58*0Sstevel@tonic-gate int renew; 59*0Sstevel@tonic-gate int log_success; 60*0Sstevel@tonic-gate int log_failure; 61*0Sstevel@tonic-gate } config_entry_list_t; 62*0Sstevel@tonic-gate static config_entry_list_t *config_entry_list; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* list of principals to be warned */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate typedef struct cred_warning_list_s { 67*0Sstevel@tonic-gate struct cred_warning_list_s *next; 68*0Sstevel@tonic-gate WARNING_NAME_T warn_name; 69*0Sstevel@tonic-gate time_t cred_exp_time; 70*0Sstevel@tonic-gate time_t cred_warn_time; 71*0Sstevel@tonic-gate mutex_t cwm; 72*0Sstevel@tonic-gate } cred_warning_list_t; 73*0Sstevel@tonic-gate static cred_warning_list_t *cred_warning_list; 74*0Sstevel@tonic-gate static rwlock_t cred_lock = DEFAULTRWLOCK; 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate static bool_t 77*0Sstevel@tonic-gate del_warning_pvt(char *); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate static config_entry_list_t * 80*0Sstevel@tonic-gate find_warning_info(char *); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate static bool_t 83*0Sstevel@tonic-gate parseConfigLine(char *buffer); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate extern 86*0Sstevel@tonic-gate warn_send(char *, char *); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate extern int kwarnd_debug; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate cred_warning_list_t * 91*0Sstevel@tonic-gate find_cred_warning(WARNING_NAME_T warn_name) 92*0Sstevel@tonic-gate { 93*0Sstevel@tonic-gate cred_warning_list_t *cw; 94*0Sstevel@tonic-gate if (!cred_warning_list) 95*0Sstevel@tonic-gate return (NULL); 96*0Sstevel@tonic-gate for (cw = cred_warning_list; cw != NULL; cw = cw->next) { 97*0Sstevel@tonic-gate if (strcmp(warn_name, cw->warn_name) != 0) 98*0Sstevel@tonic-gate continue; 99*0Sstevel@tonic-gate return (cw); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate return (NULL); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * add a principal to the principal warning list 106*0Sstevel@tonic-gate */ 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate bool_t 109*0Sstevel@tonic-gate kwarn_add_warning_1_svc(kwarn_add_warning_arg *argp, 110*0Sstevel@tonic-gate kwarn_add_warning_res *res, 111*0Sstevel@tonic-gate struct svc_req *rqstp) 112*0Sstevel@tonic-gate { 113*0Sstevel@tonic-gate cred_warning_list_t *cred_warning; 114*0Sstevel@tonic-gate config_entry_list_t *config_entry; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate if (kwarnd_debug) { 117*0Sstevel@tonic-gate printf("kwarn_add_warning_1_svc start; cWlist=%p\n", 118*0Sstevel@tonic-gate cred_warning_list); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate printf("kwarn_add_warning_1_svc: principal %s", 121*0Sstevel@tonic-gate argp->warning_name); 122*0Sstevel@tonic-gate printf(" exp time: %d\n", argp->cred_exp_time); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * if there is no entry in the config file that matches the principal to 127*0Sstevel@tonic-gate * be added to the warning list, return true because we are not going to 128*0Sstevel@tonic-gate * send a warning for this principal. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if ((config_entry = find_warning_info(argp->warning_name)) == NULL) { 132*0Sstevel@tonic-gate if (kwarnd_debug) 133*0Sstevel@tonic-gate printf( 134*0Sstevel@tonic-gate "kwarn_add_warning_1_svc find_warn_info: fails, cWlist=%p\n", 135*0Sstevel@tonic-gate cred_warning_list); 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate return (TRUE); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* 141*0Sstevel@tonic-gate * see if a warning has already been created for this principal, if so 142*0Sstevel@tonic-gate * update the warning time. 143*0Sstevel@tonic-gate */ 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate rw_wrlock(&cred_lock); 146*0Sstevel@tonic-gate if (cred_warning = find_cred_warning(argp->warning_name)) { 147*0Sstevel@tonic-gate rw_unlock(&cred_lock); 148*0Sstevel@tonic-gate mutex_lock(&cred_warning->cwm); 149*0Sstevel@tonic-gate cred_warning->cred_exp_time = argp->cred_exp_time; 150*0Sstevel@tonic-gate cred_warning->cred_warn_time = argp->cred_exp_time 151*0Sstevel@tonic-gate - config_entry->seconds_to_warn; 152*0Sstevel@tonic-gate mutex_unlock(&cred_warning->cwm); 153*0Sstevel@tonic-gate } else { 154*0Sstevel@tonic-gate cred_warning = (cred_warning_list_t *)malloc( 155*0Sstevel@tonic-gate sizeof (*cred_warning_list)); 156*0Sstevel@tonic-gate if (cred_warning == NULL) { 157*0Sstevel@tonic-gate rw_unlock(&cred_lock); 158*0Sstevel@tonic-gate res->status = 1; 159*0Sstevel@tonic-gate return (FALSE); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate (void) memset((char *)cred_warning, 0, 162*0Sstevel@tonic-gate sizeof (*cred_warning_list)); 163*0Sstevel@tonic-gate cred_warning->cred_exp_time = argp->cred_exp_time; 164*0Sstevel@tonic-gate cred_warning->cred_warn_time = argp->cred_exp_time 165*0Sstevel@tonic-gate - config_entry->seconds_to_warn; 166*0Sstevel@tonic-gate cred_warning->warn_name = strdup(argp->warning_name); 167*0Sstevel@tonic-gate if (cred_warning->warn_name == NULL) { 168*0Sstevel@tonic-gate free(cred_warning); 169*0Sstevel@tonic-gate rw_unlock(&cred_lock); 170*0Sstevel@tonic-gate res->status = 1; 171*0Sstevel@tonic-gate return (FALSE); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate mutex_init(&cred_warning->cwm, USYNC_THREAD, NULL); 174*0Sstevel@tonic-gate cred_warning->next = cred_warning_list; 175*0Sstevel@tonic-gate cred_warning_list = cred_warning; 176*0Sstevel@tonic-gate rw_unlock(&cred_lock); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate res->status = 0; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate if (kwarnd_debug) 181*0Sstevel@tonic-gate printf( 182*0Sstevel@tonic-gate "kwarn_add_warning_1_svc end: returns true; cWlist=%p\n", 183*0Sstevel@tonic-gate cred_warning_list); 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate return (TRUE); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * delete a warning request for a given principal 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate bool_t 193*0Sstevel@tonic-gate kwarn_del_warning_1_svc(kwarn_del_warning_arg *argp, 194*0Sstevel@tonic-gate kwarn_del_warning_res *res, 195*0Sstevel@tonic-gate struct svc_req *rqstp) 196*0Sstevel@tonic-gate { 197*0Sstevel@tonic-gate if (kwarnd_debug) 198*0Sstevel@tonic-gate printf(gettext("delete principal %s requested\n"), 199*0Sstevel@tonic-gate argp->warning_name); 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (del_warning_pvt(argp->warning_name) == TRUE) { 202*0Sstevel@tonic-gate res->status = 0; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate if (kwarnd_debug) 205*0Sstevel@tonic-gate printf(gettext("delete principal %s completed\n"), 206*0Sstevel@tonic-gate argp->warning_name); 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate return (TRUE); 209*0Sstevel@tonic-gate } else { 210*0Sstevel@tonic-gate res->status = 1; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate if (kwarnd_debug) 213*0Sstevel@tonic-gate printf(gettext("delete principal %s failed\n"), 214*0Sstevel@tonic-gate argp->warning_name); 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate return (TRUE); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate static bool_t 221*0Sstevel@tonic-gate del_warning_pvt(char *warning_name) 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate cred_warning_list_t *cred_warning, *prev; 224*0Sstevel@tonic-gate rw_wrlock(&cred_lock); 225*0Sstevel@tonic-gate for (prev = NULL, cred_warning = cred_warning_list; 226*0Sstevel@tonic-gate cred_warning != NULL; prev = cred_warning, 227*0Sstevel@tonic-gate cred_warning = cred_warning->next) { 228*0Sstevel@tonic-gate if (strcmp(cred_warning->warn_name, warning_name) == 0) { 229*0Sstevel@tonic-gate if (!prev) 230*0Sstevel@tonic-gate cred_warning_list = cred_warning->next; 231*0Sstevel@tonic-gate else 232*0Sstevel@tonic-gate prev->next = cred_warning->next; 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate free(cred_warning->warn_name); 235*0Sstevel@tonic-gate free(cred_warning); 236*0Sstevel@tonic-gate rw_unlock(&cred_lock); 237*0Sstevel@tonic-gate return (TRUE); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate rw_unlock(&cred_lock); 241*0Sstevel@tonic-gate return (FALSE); 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate /* 245*0Sstevel@tonic-gate * load the warn.conf file into the config_entry list. 246*0Sstevel@tonic-gate */ 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate bool_t 249*0Sstevel@tonic-gate loadConfigFile(void) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate char buffer[BUFSIZ]; 252*0Sstevel@tonic-gate FILE *cfgfile; 253*0Sstevel@tonic-gate bool_t retval = TRUE; 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate if ((cfgfile = fopen(CONF_FILENAME, "r")) == NULL) { 256*0Sstevel@tonic-gate syslog(LOG_ERR, gettext( 257*0Sstevel@tonic-gate "could not open config file \"%s\"\n"), 258*0Sstevel@tonic-gate CONF_FILENAME); 259*0Sstevel@tonic-gate syslog(LOG_ERR, gettext( 260*0Sstevel@tonic-gate "using default options \"%s\"\n"), 261*0Sstevel@tonic-gate DEFAULT_CONFIG); 262*0Sstevel@tonic-gate retval = parseConfigLine(DEFAULT_CONFIG); 263*0Sstevel@tonic-gate } else { 264*0Sstevel@tonic-gate (void) memset(buffer, 0, sizeof (buffer)); 265*0Sstevel@tonic-gate while ((fgets(buffer, BUFSIZ, cfgfile) != NULL) && 266*0Sstevel@tonic-gate (retval == TRUE)) 267*0Sstevel@tonic-gate retval = parseConfigLine(buffer); 268*0Sstevel@tonic-gate fclose(cfgfile); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate return (retval); 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Return TRUE if we get a valid opt and update flags appro. 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate static bool_t 277*0Sstevel@tonic-gate cmp_renew_opts(char *opt, 278*0Sstevel@tonic-gate int *log_success, /* out */ 279*0Sstevel@tonic-gate int *log_failure) /* out */ 280*0Sstevel@tonic-gate { 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate if (strncasecmp(opt, "log", 283*0Sstevel@tonic-gate sizeof ("log")) == 0) { 284*0Sstevel@tonic-gate *log_success = *log_failure = 1; 285*0Sstevel@tonic-gate } else if (strncasecmp(opt, "log-success", 286*0Sstevel@tonic-gate sizeof ("log-success")) == 0) { 287*0Sstevel@tonic-gate *log_success = 1; 288*0Sstevel@tonic-gate } else if (strncasecmp(opt, "log-failure", 289*0Sstevel@tonic-gate sizeof ("log-failure")) == 0) { 290*0Sstevel@tonic-gate *log_failure = 1; 291*0Sstevel@tonic-gate } else { 292*0Sstevel@tonic-gate if (kwarnd_debug) 293*0Sstevel@tonic-gate printf("cmp_renew_opts: renew bad opt=`%s'\n", 294*0Sstevel@tonic-gate opt ? opt : "null"); 295*0Sstevel@tonic-gate return (FALSE); 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate return (TRUE); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate /* 302*0Sstevel@tonic-gate * Make the config_entry item for the config_entry_list, based on 303*0Sstevel@tonic-gate * buffer. The formats are 304*0Sstevel@tonic-gate * 305*0Sstevel@tonic-gate * <principal> [renew[:<opt1,...optN>]] syslog|terminal <time> 306*0Sstevel@tonic-gate * <principal> [renew[:<opt1,...optN>]] mail <time> <e-mail address> 307*0Sstevel@tonic-gate * 308*0Sstevel@tonic-gate * where renew opts will be: 309*0Sstevel@tonic-gate * 310*0Sstevel@tonic-gate * log-success 311*0Sstevel@tonic-gate * - Log the result of the renew attempt on success using 312*0Sstevel@tonic-gate * the specified method (syslog|terminal|mail) 313*0Sstevel@tonic-gate * 314*0Sstevel@tonic-gate * log-failure 315*0Sstevel@tonic-gate * - Log the result of the renew attempt on failure using 316*0Sstevel@tonic-gate * the specified method (syslog|terminal|mail) 317*0Sstevel@tonic-gate * 318*0Sstevel@tonic-gate * log 319*0Sstevel@tonic-gate * - Same as specifing both log-failure and log-success 320*0Sstevel@tonic-gate * 321*0Sstevel@tonic-gate * Note if no log options are given, there will be no logging. 322*0Sstevel@tonic-gate * 323*0Sstevel@tonic-gate */ 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate static bool_t 326*0Sstevel@tonic-gate parseConfigLine(char *buffer) 327*0Sstevel@tonic-gate { 328*0Sstevel@tonic-gate char *principal, *send_to, *emailid, *ends, *tm; 329*0Sstevel@tonic-gate char *exptime; 330*0Sstevel@tonic-gate int time_mode; 331*0Sstevel@tonic-gate time_t etime; 332*0Sstevel@tonic-gate config_entry_list_t *config_entry; 333*0Sstevel@tonic-gate int renew = 0; 334*0Sstevel@tonic-gate int log_success = 0; 335*0Sstevel@tonic-gate int log_failure = 0; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* ignore comments */ 338*0Sstevel@tonic-gate if (*buffer == '#') 339*0Sstevel@tonic-gate return (TRUE); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate if (kwarnd_debug) 342*0Sstevel@tonic-gate printf("parseconf: buffer=%s", buffer); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate /* find end of principal */ 345*0Sstevel@tonic-gate principal = buffer; 346*0Sstevel@tonic-gate for (send_to = buffer; *send_to && !isspace(*send_to); 347*0Sstevel@tonic-gate send_to++); 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* find first non whitespace after principal (start of send_to) */ 350*0Sstevel@tonic-gate if (*send_to) { 351*0Sstevel@tonic-gate *send_to = '\0'; 352*0Sstevel@tonic-gate send_to++; 353*0Sstevel@tonic-gate while (*send_to && isspace(*send_to)) 354*0Sstevel@tonic-gate send_to++; 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate /* if no send_to, continue, bad entry */ 358*0Sstevel@tonic-gate if (! *send_to) 359*0Sstevel@tonic-gate return (TRUE); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate /* find end of send_to */ 362*0Sstevel@tonic-gate for (ends = send_to; *ends && !isspace(*ends); 363*0Sstevel@tonic-gate ends++); 364*0Sstevel@tonic-gate if (*ends) 365*0Sstevel@tonic-gate *ends = '\0'; 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (strchr(send_to, ':')) { 369*0Sstevel@tonic-gate /* we've got renew opts */ 370*0Sstevel@tonic-gate char *st = NULL, *op = NULL; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate op = strdup(send_to); 373*0Sstevel@tonic-gate if (!op) 374*0Sstevel@tonic-gate return (FALSE); 375*0Sstevel@tonic-gate st = strchr(op, ':'); 376*0Sstevel@tonic-gate *st = '\0'; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate if (strncasecmp(op, "renew", sizeof ("renew")) == 0) { 379*0Sstevel@tonic-gate renew = 1; 380*0Sstevel@tonic-gate } else { 381*0Sstevel@tonic-gate free(op); 382*0Sstevel@tonic-gate /* got a ':' but not preceeded w/renew, badent, skip */ 383*0Sstevel@tonic-gate if (kwarnd_debug) 384*0Sstevel@tonic-gate printf("parseconf: colon badent, skip\n"); 385*0Sstevel@tonic-gate return (TRUE); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate free(op); 388*0Sstevel@tonic-gate op = NULL; 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate st++; 391*0Sstevel@tonic-gate if (!st || !*st || isspace(*st)) { 392*0Sstevel@tonic-gate if (kwarnd_debug) 393*0Sstevel@tonic-gate printf("parseconf: st badent, skip\n"); 394*0Sstevel@tonic-gate /* bad ent, skip */ 395*0Sstevel@tonic-gate return (TRUE); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate if (renew && strchr(st, ',')) { 398*0Sstevel@tonic-gate while (1) { 399*0Sstevel@tonic-gate /* loop thru comma seperated list-o-opts */ 400*0Sstevel@tonic-gate char *comma = NULL, *c = NULL, *l = NULL; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if (st && (comma = strchr(st, ','))) { 403*0Sstevel@tonic-gate l = strdup(st); 404*0Sstevel@tonic-gate if (!l) 405*0Sstevel@tonic-gate return (FALSE); 406*0Sstevel@tonic-gate c = strchr(l, ','); 407*0Sstevel@tonic-gate *c = '\0'; 408*0Sstevel@tonic-gate if (!cmp_renew_opts(l, &log_success, 409*0Sstevel@tonic-gate &log_failure)) { 410*0Sstevel@tonic-gate free(l); 411*0Sstevel@tonic-gate /* badent, skip */ 412*0Sstevel@tonic-gate return (TRUE); 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate free(l); 415*0Sstevel@tonic-gate l = NULL; 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate st = comma; 418*0Sstevel@tonic-gate st++; 419*0Sstevel@tonic-gate } else { 420*0Sstevel@tonic-gate if (st) { 421*0Sstevel@tonic-gate if (!cmp_renew_opts(st, 422*0Sstevel@tonic-gate &log_success, 423*0Sstevel@tonic-gate &log_failure)) { 424*0Sstevel@tonic-gate /* badent, skip */ 425*0Sstevel@tonic-gate return (TRUE); 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate break; 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate } /* while */ 431*0Sstevel@tonic-gate } else if (st) { 432*0Sstevel@tonic-gate /* we just have one opt */ 433*0Sstevel@tonic-gate if (!cmp_renew_opts(st, &log_success, &log_failure)) { 434*0Sstevel@tonic-gate /* badent, skip */ 435*0Sstevel@tonic-gate return (TRUE); 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate /* if send_to is "renew", note it and refind send_to */ 440*0Sstevel@tonic-gate } else if (strncasecmp(send_to, "renew", 441*0Sstevel@tonic-gate sizeof ("renew")) == 0) { 442*0Sstevel@tonic-gate renew = 1; 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate if (kwarnd_debug) { 447*0Sstevel@tonic-gate printf("parseconf: renew=%d, log failure=%d, log success=%d\n", 448*0Sstevel@tonic-gate renew, log_failure, log_success); 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if (renew) { 452*0Sstevel@tonic-gate /* find first non whitespace after send_to (start of exptime) */ 453*0Sstevel@tonic-gate for (send_to = ends+1; *send_to && isspace(*send_to); 454*0Sstevel@tonic-gate send_to++); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* if no send_to, continue, bad entry */ 457*0Sstevel@tonic-gate if (! *send_to) { 458*0Sstevel@tonic-gate if (kwarnd_debug) 459*0Sstevel@tonic-gate printf("parseconf: no send_to, badent, skip\n"); 460*0Sstevel@tonic-gate return (TRUE); 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /* find end of send_to */ 464*0Sstevel@tonic-gate for (ends = send_to; *ends && !isspace(*ends); 465*0Sstevel@tonic-gate ends++); 466*0Sstevel@tonic-gate if (*ends) 467*0Sstevel@tonic-gate *ends = '\0'; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate /* find first non whitespace after send_to (start of exptime) */ 472*0Sstevel@tonic-gate for (exptime = ends+1; *exptime && isspace(*exptime); 473*0Sstevel@tonic-gate exptime++); 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate /* if no exptime, continue, bad entry */ 476*0Sstevel@tonic-gate if (! *exptime) { 477*0Sstevel@tonic-gate if (kwarnd_debug) 478*0Sstevel@tonic-gate printf("parseconf: no exptime, badent, skip\n"); 479*0Sstevel@tonic-gate return (TRUE); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* find end of exptime */ 483*0Sstevel@tonic-gate for (ends = exptime; *ends && !isspace(*ends); ends++); 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate tm = ends - 1; 486*0Sstevel@tonic-gate if (*tm == 's') 487*0Sstevel@tonic-gate time_mode = 1; 488*0Sstevel@tonic-gate else if (*tm == 'm') 489*0Sstevel@tonic-gate time_mode = 2; 490*0Sstevel@tonic-gate else if (*tm == 'h') 491*0Sstevel@tonic-gate time_mode = 3; 492*0Sstevel@tonic-gate else 493*0Sstevel@tonic-gate time_mode = 1; 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate if (*tm) 496*0Sstevel@tonic-gate *tm = '\0'; 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate if (kwarnd_debug) { 499*0Sstevel@tonic-gate printf("parseconf: send_to = '%s', exptime='%s'\n", 500*0Sstevel@tonic-gate send_to, exptime); 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate /* find first non whitespace after exptime (start of emailid) */ 504*0Sstevel@tonic-gate for (emailid = ends+1; *emailid && isspace(*emailid); emailid++); 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate /* find end of emailid */ 507*0Sstevel@tonic-gate if (*emailid) { 508*0Sstevel@tonic-gate for (ends = emailid; *ends && !isspace(*ends); 509*0Sstevel@tonic-gate ends++); 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate if (*ends) 512*0Sstevel@tonic-gate *ends = '\0'; 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* if send to mail and no mail address, bad entry */ 516*0Sstevel@tonic-gate if ((strcmp(send_to, "mail") == 0) && (!*emailid)) { 517*0Sstevel@tonic-gate if (kwarnd_debug) 518*0Sstevel@tonic-gate printf("parseconf: returns true; no mail addr\n"); 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate syslog(LOG_ERR, gettext("missing mail address" 521*0Sstevel@tonic-gate " in config entry: \n%s %s %s " 522*0Sstevel@tonic-gate " cannot mail warning"), principal, 523*0Sstevel@tonic-gate send_to, exptime); 524*0Sstevel@tonic-gate return (TRUE); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate /* create an entry */ 528*0Sstevel@tonic-gate config_entry = (config_entry_list_t *) 529*0Sstevel@tonic-gate malloc(sizeof (*config_entry_list)); 530*0Sstevel@tonic-gate if (config_entry == NULL) 531*0Sstevel@tonic-gate return (FALSE); 532*0Sstevel@tonic-gate (void) memset(config_entry, 0, sizeof (*config_entry_list)); 533*0Sstevel@tonic-gate config_entry->principal = strdup(principal); 534*0Sstevel@tonic-gate if (config_entry->principal == NULL) 535*0Sstevel@tonic-gate return (FALSE); 536*0Sstevel@tonic-gate config_entry->where_to = strdup(send_to); 537*0Sstevel@tonic-gate if (config_entry->where_to == NULL) 538*0Sstevel@tonic-gate return (FALSE); 539*0Sstevel@tonic-gate etime = atol(exptime); 540*0Sstevel@tonic-gate if (time_mode == 1) 541*0Sstevel@tonic-gate config_entry->seconds_to_warn = etime; 542*0Sstevel@tonic-gate else if (time_mode == 2) 543*0Sstevel@tonic-gate config_entry->seconds_to_warn = etime * 60; 544*0Sstevel@tonic-gate else if (time_mode == 3) 545*0Sstevel@tonic-gate config_entry->seconds_to_warn = etime * 60 * 60; 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate if (*emailid) { 548*0Sstevel@tonic-gate config_entry->email = strdup(emailid); 549*0Sstevel@tonic-gate if (config_entry->email == NULL) 550*0Sstevel@tonic-gate return (FALSE); 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate config_entry->renew = renew; 554*0Sstevel@tonic-gate config_entry->log_success = log_success; 555*0Sstevel@tonic-gate config_entry->log_failure = log_failure; 556*0Sstevel@tonic-gate config_entry->next = config_entry_list; 557*0Sstevel@tonic-gate config_entry_list = config_entry; 558*0Sstevel@tonic-gate if (kwarnd_debug) 559*0Sstevel@tonic-gate printf("parseconf: returns true; celist=%p\n", 560*0Sstevel@tonic-gate config_entry_list); 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate return (TRUE); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* 566*0Sstevel@tonic-gate * find a specific warn.conf entry. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate static config_entry_list_t * 570*0Sstevel@tonic-gate find_warning_info(char *principal) 571*0Sstevel@tonic-gate { 572*0Sstevel@tonic-gate config_entry_list_t *config_entry; 573*0Sstevel@tonic-gate /* look for a specific entry */ 574*0Sstevel@tonic-gate for (config_entry = config_entry_list; config_entry; 575*0Sstevel@tonic-gate config_entry = config_entry->next) { 576*0Sstevel@tonic-gate if (strcmp(config_entry->principal, principal) == 0) { 577*0Sstevel@tonic-gate return (config_entry); 578*0Sstevel@tonic-gate } 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate /* look for a wild card entry */ 581*0Sstevel@tonic-gate for (config_entry = config_entry_list; config_entry; 582*0Sstevel@tonic-gate config_entry = config_entry->next) { 583*0Sstevel@tonic-gate if (strcmp(config_entry->principal, "*") == 0) { 584*0Sstevel@tonic-gate return (config_entry); 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate /* nothing found */ 588*0Sstevel@tonic-gate return (NULL); 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate /* 593*0Sstevel@tonic-gate * create a pipe, fork and exec a command, 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate static FILE * 596*0Sstevel@tonic-gate safe_popen_w(char *path_to_cmd, char **argv) 597*0Sstevel@tonic-gate { 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate int fd[2]; 600*0Sstevel@tonic-gate FILE *fp; 601*0Sstevel@tonic-gate char *envp[2]; 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate if (pipe(fd) == -1) 604*0Sstevel@tonic-gate return (NULL); 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate switch (fork()) { 608*0Sstevel@tonic-gate case -1: 609*0Sstevel@tonic-gate (void) close(fd[0]); 610*0Sstevel@tonic-gate (void) close(fd[1]); 611*0Sstevel@tonic-gate return (NULL); 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate case 0: 614*0Sstevel@tonic-gate close(fd[1]); 615*0Sstevel@tonic-gate /* fd[0] is the end we read from */ 616*0Sstevel@tonic-gate if (fd[0] != 0) { 617*0Sstevel@tonic-gate close(0); 618*0Sstevel@tonic-gate dup(fd[0]); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate close(1); 621*0Sstevel@tonic-gate close(2); 622*0Sstevel@tonic-gate envp[0] = "PATH=/usr/bin"; 623*0Sstevel@tonic-gate envp[1] = NULL; 624*0Sstevel@tonic-gate #ifdef DEBUG 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate int fd; 627*0Sstevel@tonic-gate fd = open("/tmp/kwarn.out", O_WRONLY|O_TRUNC|O_CREAT, 628*0Sstevel@tonic-gate 0666); 629*0Sstevel@tonic-gate if (fd != 1) 630*0Sstevel@tonic-gate dup(fd); 631*0Sstevel@tonic-gate if (fd != 2) 632*0Sstevel@tonic-gate dup(fd); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate #endif 635*0Sstevel@tonic-gate (void) execve(path_to_cmd, argv, envp); 636*0Sstevel@tonic-gate syslog(LOG_ERR, "warnd: %m"); 637*0Sstevel@tonic-gate _exit(1); 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate default: 640*0Sstevel@tonic-gate close(fd[0]); 641*0Sstevel@tonic-gate /* fd[1] is the end we write to */ 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate fp = fdopen(fd[1], "w"); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate if (fp == NULL) { 646*0Sstevel@tonic-gate (void) close(fd[1]); 647*0Sstevel@tonic-gate return (NULL); 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate return (fp); 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate static uid_t gssd_uid; 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate void 657*0Sstevel@tonic-gate set_warnd_uid(uid_t uid) 658*0Sstevel@tonic-gate { 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate /* 661*0Sstevel@tonic-gate * set the value of gssd_uid, so it can be retrieved when getuid() 662*0Sstevel@tonic-gate * is called by the underlying mechanism libraries 663*0Sstevel@tonic-gate */ 664*0Sstevel@tonic-gate if (kwarnd_debug) 665*0Sstevel@tonic-gate printf("set_warnd_uid called with uid = %d\n", uid); 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate gssd_uid = uid; 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate uid_t 671*0Sstevel@tonic-gate getuid(void) 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate { 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * return the value set when one of the gssd procedures was 677*0Sstevel@tonic-gate * entered. This is the value of the uid under which the 678*0Sstevel@tonic-gate * underlying mechanism library must operate in order to 679*0Sstevel@tonic-gate * get the user's credentials. This call is necessary since 680*0Sstevel@tonic-gate * gssd runs as root and credentials are many times stored 681*0Sstevel@tonic-gate * in files and directories specific to the user 682*0Sstevel@tonic-gate */ 683*0Sstevel@tonic-gate if (kwarnd_debug) 684*0Sstevel@tonic-gate printf("getuid called and returning gsssd_uid = %d\n", 685*0Sstevel@tonic-gate gssd_uid); 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate return (gssd_uid); 688*0Sstevel@tonic-gate } 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate static bool_t 692*0Sstevel@tonic-gate getpruid(char *pr, uid_t *uid) 693*0Sstevel@tonic-gate { 694*0Sstevel@tonic-gate char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL; 695*0Sstevel@tonic-gate struct passwd *pw; 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate rcp1 = strdup(pr); 698*0Sstevel@tonic-gate if (!rcp1) 699*0Sstevel@tonic-gate return (FALSE); 700*0Sstevel@tonic-gate rcp2 = strtok(rcp1, "@"); 701*0Sstevel@tonic-gate rcp3 = strtok(rcp2, "/"); 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate if (rcp3) { 704*0Sstevel@tonic-gate pw = getpwnam(rcp3); 705*0Sstevel@tonic-gate *uid = pw->pw_uid; 706*0Sstevel@tonic-gate free(rcp1); 707*0Sstevel@tonic-gate return (TRUE); 708*0Sstevel@tonic-gate } 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate free(rcp1); 711*0Sstevel@tonic-gate return (FALSE); 712*0Sstevel@tonic-gate } 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate static krb5_error_code 716*0Sstevel@tonic-gate renew_creds( 717*0Sstevel@tonic-gate char *princ, 718*0Sstevel@tonic-gate time_t *new_exp_time) /* out */ 719*0Sstevel@tonic-gate { 720*0Sstevel@tonic-gate krb5_creds my_creds; 721*0Sstevel@tonic-gate krb5_error_code code = 0; 722*0Sstevel@tonic-gate struct k5_data k5; 723*0Sstevel@tonic-gate char *progname = "warnd"; 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate uid_t saved_u = getuid(); 726*0Sstevel@tonic-gate uid_t u; 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate if (kwarnd_debug) 729*0Sstevel@tonic-gate printf("renew start: uid=%d\n", getuid()); 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate if (!getpruid(princ, &u)) { 732*0Sstevel@tonic-gate if (kwarnd_debug) 733*0Sstevel@tonic-gate printf("renew: getpruid failed, princ='%s'\n", 734*0Sstevel@tonic-gate princ ? princ : "<null>"); 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate return (-1); /* better err num? */ 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate set_warnd_uid(u); 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate (void) memset(&my_creds, 0, sizeof (my_creds)); 742*0Sstevel@tonic-gate (void) memset(&k5, 0, sizeof (k5)); 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate if (code = krb5_init_context(&k5.ctx)) { 745*0Sstevel@tonic-gate com_err(progname, code, 746*0Sstevel@tonic-gate gettext("while initializing Kerberos 5 library")); 747*0Sstevel@tonic-gate goto out; 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate if ((code = krb5_cc_default(k5.ctx, &k5.cc))) { 751*0Sstevel@tonic-gate com_err(progname, code, 752*0Sstevel@tonic-gate gettext("while getting default ccache")); 753*0Sstevel@tonic-gate goto out; 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate } 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if ((code = krb5_parse_name(k5.ctx, princ, 758*0Sstevel@tonic-gate &k5.me))) { 759*0Sstevel@tonic-gate com_err(progname, code, gettext("when parsing name %s"), 760*0Sstevel@tonic-gate princ); 761*0Sstevel@tonic-gate goto out; 762*0Sstevel@tonic-gate } 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate if ((code = krb5_get_renewed_creds(k5.ctx, &my_creds, k5.me, k5.cc, 765*0Sstevel@tonic-gate NULL))) { 766*0Sstevel@tonic-gate com_err(progname, code, gettext("while renewing creds")); 767*0Sstevel@tonic-gate goto out; 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (code = krb5_cc_initialize(k5.ctx, k5.cc, k5.me)) { 771*0Sstevel@tonic-gate com_err(progname, code, gettext("when initializing cache %s"), 772*0Sstevel@tonic-gate "defcc"); 773*0Sstevel@tonic-gate goto out; 774*0Sstevel@tonic-gate } 775*0Sstevel@tonic-gate 776*0Sstevel@tonic-gate if (code = krb5_cc_store_cred(k5.ctx, k5.cc, &my_creds)) { 777*0Sstevel@tonic-gate com_err(progname, code, gettext("while storing credentials")); 778*0Sstevel@tonic-gate goto out; 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate /* "return" new expire time */ 782*0Sstevel@tonic-gate *new_exp_time = my_creds.times.endtime; 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate out: 785*0Sstevel@tonic-gate krb5_free_cred_contents(k5.ctx, &my_creds); 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate if (k5.name) 788*0Sstevel@tonic-gate krb5_free_unparsed_name(k5.ctx, k5.name); 789*0Sstevel@tonic-gate if (k5.me) 790*0Sstevel@tonic-gate krb5_free_principal(k5.ctx, k5.me); 791*0Sstevel@tonic-gate if (k5.cc) 792*0Sstevel@tonic-gate krb5_cc_close(k5.ctx, k5.cc); 793*0Sstevel@tonic-gate if (k5.ctx) 794*0Sstevel@tonic-gate krb5_free_context(k5.ctx); 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate set_warnd_uid(saved_u); 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate if (kwarnd_debug) 799*0Sstevel@tonic-gate printf("renew end: code=%s, uid=%d\n", error_message(code), 800*0Sstevel@tonic-gate getuid()); 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate return (code); 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate static bool_t 806*0Sstevel@tonic-gate loggedon(char *name) 807*0Sstevel@tonic-gate { 808*0Sstevel@tonic-gate register struct utmpx *ubuf; 809*0Sstevel@tonic-gate char *rcp1 = NULL, *rcp2 = NULL, *rcp3 = NULL; 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate /* 812*0Sstevel@tonic-gate * strip any realm or instance from principal so we can match 813*0Sstevel@tonic-gate * against unix userid. 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate rcp1 = strdup(name); 816*0Sstevel@tonic-gate if (!rcp1) 817*0Sstevel@tonic-gate return (FALSE); 818*0Sstevel@tonic-gate rcp2 = strtok(rcp1, "@"); 819*0Sstevel@tonic-gate rcp3 = strtok(rcp2, "/"); 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate /* 822*0Sstevel@tonic-gate * Scan through the "utmpx" file for the 823*0Sstevel@tonic-gate * entry for the person we want to send to. 824*0Sstevel@tonic-gate */ 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate setutxent(); 827*0Sstevel@tonic-gate while ((ubuf = getutxent()) != NULL) { 828*0Sstevel@tonic-gate if (ubuf->ut_type == USER_PROCESS) { 829*0Sstevel@tonic-gate if (strncmp(rcp3, ubuf->ut_user, 830*0Sstevel@tonic-gate sizeof (ubuf->ut_user)) == 0) { 831*0Sstevel@tonic-gate free(rcp1); 832*0Sstevel@tonic-gate endutxent(); 833*0Sstevel@tonic-gate return (TRUE); 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate } 838*0Sstevel@tonic-gate free(rcp1); 839*0Sstevel@tonic-gate endutxent(); 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate if (kwarnd_debug) 842*0Sstevel@tonic-gate printf("loggedon: returning false for user `%s'\n", rcp1); 843*0Sstevel@tonic-gate 844*0Sstevel@tonic-gate return (FALSE); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* 848*0Sstevel@tonic-gate * main loop to check the cred warning list and send the warnings 849*0Sstevel@tonic-gate * the appropriate location based on warn.conf or auto-renew creds. 850*0Sstevel@tonic-gate */ 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate void 853*0Sstevel@tonic-gate kwarnd_check_warning_list(void) 854*0Sstevel@tonic-gate { /* func */ 855*0Sstevel@tonic-gate cred_warning_list_t *cw; /* cred warning */ 856*0Sstevel@tonic-gate config_entry_list_t *ce; /* config entry */ 857*0Sstevel@tonic-gate time_t now; 858*0Sstevel@tonic-gate int minutes; 859*0Sstevel@tonic-gate char buff[256]; 860*0Sstevel@tonic-gate char cmdline[256]; 861*0Sstevel@tonic-gate FILE *fp; 862*0Sstevel@tonic-gate char *subj = "Kerberos credentials expiring"; 863*0Sstevel@tonic-gate char *renew_subj = "Kerberos credentials renewed"; 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate if (kwarnd_debug) 866*0Sstevel@tonic-gate printf("check list: start: getuid=%d, cw list=%p\n", getuid(), 867*0Sstevel@tonic-gate cred_warning_list); 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate while (1) { 870*0Sstevel@tonic-gate (void) poll(NULL, NULL, 60000); 871*0Sstevel@tonic-gate 872*0Sstevel@tonic-gate for (cw = cred_warning_list; 873*0Sstevel@tonic-gate cw != NULL; 874*0Sstevel@tonic-gate cw = cw->next) { 875*0Sstevel@tonic-gate int send_msg = 0; 876*0Sstevel@tonic-gate 877*0Sstevel@tonic-gate time(&now); 878*0Sstevel@tonic-gate if (now >= cw->cred_warn_time) { 879*0Sstevel@tonic-gate int renew_attempted = 0; 880*0Sstevel@tonic-gate int renew_failed = 0; 881*0Sstevel@tonic-gate int renew_tooclose = 0; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (kwarnd_debug) 884*0Sstevel@tonic-gate printf("checklist: now >= warn_t\n"); 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate ce = find_warning_info(cw->warn_name); 887*0Sstevel@tonic-gate minutes = (cw->cred_exp_time - 888*0Sstevel@tonic-gate now + 59) / 60; 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate if (kwarnd_debug) 891*0Sstevel@tonic-gate printf("checklist: where_to=%s\n", 892*0Sstevel@tonic-gate ce->where_to ? 893*0Sstevel@tonic-gate ce->where_to : "null"); 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate if (ce->renew && 896*0Sstevel@tonic-gate loggedon(cw->warn_name)) { 897*0Sstevel@tonic-gate krb5_error_code code; 898*0Sstevel@tonic-gate time_t new_exp_time; 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate renew_attempted = 1; 901*0Sstevel@tonic-gate code = renew_creds( 902*0Sstevel@tonic-gate cw->warn_name, 903*0Sstevel@tonic-gate &new_exp_time); 904*0Sstevel@tonic-gate if (!code) { 905*0Sstevel@tonic-gate /* krb5 api renew success */ 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate /* 908*0Sstevel@tonic-gate * So we had api success 909*0Sstevel@tonic-gate * but the new exp time 910*0Sstevel@tonic-gate * is same as current one 911*0Sstevel@tonic-gate * so we are too close 912*0Sstevel@tonic-gate * to Renewable_life time. 913*0Sstevel@tonic-gate */ 914*0Sstevel@tonic-gate if (cw->cred_exp_time 915*0Sstevel@tonic-gate == new_exp_time) { 916*0Sstevel@tonic-gate renew_tooclose = 1; 917*0Sstevel@tonic-gate if (kwarnd_debug) 918*0Sstevel@tonic-gate printf( 919*0Sstevel@tonic-gate "checklist: new expire time same as old expire time\n"); 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate if (ce->log_failure) { 922*0Sstevel@tonic-gate send_msg = 1; 923*0Sstevel@tonic-gate snprintf(buff, 924*0Sstevel@tonic-gate sizeof (buff), 925*0Sstevel@tonic-gate gettext("%s:\r\nYour kerberos" 926*0Sstevel@tonic-gate " credentials have not been renewed" 927*0Sstevel@tonic-gate " (too close to Renewable_life).\r\n" 928*0Sstevel@tonic-gate "Please run kinit(1).\r\n"), 929*0Sstevel@tonic-gate cw->warn_name); 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate } else { 932*0Sstevel@tonic-gate /* update times */ 933*0Sstevel@tonic-gate cw->cred_exp_time = 934*0Sstevel@tonic-gate new_exp_time; 935*0Sstevel@tonic-gate cw->cred_warn_time = 936*0Sstevel@tonic-gate new_exp_time - 937*0Sstevel@tonic-gate ce->seconds_to_warn; 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate if (kwarnd_debug) 941*0Sstevel@tonic-gate printf( 942*0Sstevel@tonic-gate "check list: new_w_t=%d\n", 943*0Sstevel@tonic-gate cw->cred_warn_time); 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate if (!renew_tooclose && 946*0Sstevel@tonic-gate ce->log_success) { 947*0Sstevel@tonic-gate if (kwarnd_debug) 948*0Sstevel@tonic-gate printf( 949*0Sstevel@tonic-gate "check list: log success\n"); 950*0Sstevel@tonic-gate 951*0Sstevel@tonic-gate send_msg = 1; 952*0Sstevel@tonic-gate snprintf(buff, 953*0Sstevel@tonic-gate sizeof (buff), 954*0Sstevel@tonic-gate gettext("%s:\r\nYour kerberos" 955*0Sstevel@tonic-gate " credentials have been renewed.\r\n"), 956*0Sstevel@tonic-gate cw->warn_name); 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate } /* !(code) */ 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate if (!renew_tooclose && code && 962*0Sstevel@tonic-gate ce->log_failure) { 963*0Sstevel@tonic-gate if (kwarnd_debug) 964*0Sstevel@tonic-gate printf( 965*0Sstevel@tonic-gate "check list: log FAIL\n"); 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate send_msg = 1; 968*0Sstevel@tonic-gate snprintf(buff, 969*0Sstevel@tonic-gate sizeof (buff), 970*0Sstevel@tonic-gate gettext("%s:\r\nYour kerberos" 971*0Sstevel@tonic-gate " credentials failed to be renewed (%s).\r\n"), 972*0Sstevel@tonic-gate cw->warn_name, 973*0Sstevel@tonic-gate error_message(code)); 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate renew_failed = code ? 1 : 0; 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate } else if (minutes > 0) { 978*0Sstevel@tonic-gate send_msg = 1; 979*0Sstevel@tonic-gate snprintf(buff, sizeof (buff), 980*0Sstevel@tonic-gate gettext("%s:\r\nyour kerberos" 981*0Sstevel@tonic-gate " credentials expire in less than" 982*0Sstevel@tonic-gate " %d minutes.\r\n"), 983*0Sstevel@tonic-gate cw->warn_name, 984*0Sstevel@tonic-gate minutes); 985*0Sstevel@tonic-gate } else { 986*0Sstevel@tonic-gate send_msg = 1; 987*0Sstevel@tonic-gate snprintf(buff, sizeof (buff), 988*0Sstevel@tonic-gate gettext("%s:\r\nyour kerberos" 989*0Sstevel@tonic-gate " credentials have expired.\r\n"), 990*0Sstevel@tonic-gate cw->warn_name); 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate if (kwarnd_debug) 994*0Sstevel@tonic-gate printf("checklist: send_msg=%d\n", 995*0Sstevel@tonic-gate send_msg); 996*0Sstevel@tonic-gate if (!send_msg) 997*0Sstevel@tonic-gate goto del_warning; 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate if (strncmp(ce->where_to, 1000*0Sstevel@tonic-gate "mail", sizeof ("mail")) == 0) { 1001*0Sstevel@tonic-gate char *argv[3]; 1002*0Sstevel@tonic-gate 1003*0Sstevel@tonic-gate argv[0] = MAIL; 1004*0Sstevel@tonic-gate (void) snprintf(cmdline, 1005*0Sstevel@tonic-gate sizeof (cmdline), 1006*0Sstevel@tonic-gate "%s", 1007*0Sstevel@tonic-gate ce->email); 1008*0Sstevel@tonic-gate argv[1] = cmdline; 1009*0Sstevel@tonic-gate argv[2] = NULL; 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate fp = safe_popen_w(MAILPATH, argv); 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate if (fp) { 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate (void) fprintf(fp, 1016*0Sstevel@tonic-gate "To: %s\nSubject: %s\n\n%s\n", 1017*0Sstevel@tonic-gate ce->email, 1018*0Sstevel@tonic-gate renew_attempted 1019*0Sstevel@tonic-gate ? renew_subj : subj, 1020*0Sstevel@tonic-gate buff); 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate fclose(fp); 1023*0Sstevel@tonic-gate } else { 1024*0Sstevel@tonic-gate syslog(LOG_ERR, 1025*0Sstevel@tonic-gate gettext("could not fork " 1026*0Sstevel@tonic-gate "mail program to e-mail " 1027*0Sstevel@tonic-gate "warning to %s\n"), 1028*0Sstevel@tonic-gate cmdline); 1029*0Sstevel@tonic-gate } 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate } else if (strncmp(ce->where_to, 1032*0Sstevel@tonic-gate "terminal", 1033*0Sstevel@tonic-gate sizeof ("terminal")) == 0) { 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate warn_send(cw->warn_name, 1036*0Sstevel@tonic-gate buff); 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate } else if (send_msg && strncmp(ce->where_to, 1039*0Sstevel@tonic-gate "syslog", 1040*0Sstevel@tonic-gate sizeof ("syslog")) == 0) { 1041*0Sstevel@tonic-gate syslog(LOG_NOTICE|LOG_AUTH, 1042*0Sstevel@tonic-gate "%s", 1043*0Sstevel@tonic-gate buff); 1044*0Sstevel@tonic-gate #if 0 1045*0Sstevel@tonic-gate } else if (strncmp(ce->where_to, 1046*0Sstevel@tonic-gate "snmp", 1047*0Sstevel@tonic-gate sizeof ("snmp")) == 0) { 1048*0Sstevel@tonic-gate #endif 1049*0Sstevel@tonic-gate } else { 1050*0Sstevel@tonic-gate if (kwarnd_debug) 1051*0Sstevel@tonic-gate printf( 1052*0Sstevel@tonic-gate "unknown msg method=`%s'\n", 1053*0Sstevel@tonic-gate ce->where_to); 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate exit(1); 1056*0Sstevel@tonic-gate } 1057*0Sstevel@tonic-gate 1058*0Sstevel@tonic-gate del_warning: 1059*0Sstevel@tonic-gate if (!renew_attempted || renew_failed || 1060*0Sstevel@tonic-gate renew_tooclose) { 1061*0Sstevel@tonic-gate if (del_warning_pvt(cw->warn_name) 1062*0Sstevel@tonic-gate == TRUE) { 1063*0Sstevel@tonic-gate 1064*0Sstevel@tonic-gate if (kwarnd_debug) 1065*0Sstevel@tonic-gate printf( 1066*0Sstevel@tonic-gate "check list: del warn succ\n"); 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate break; 1069*0Sstevel@tonic-gate } else { 1070*0Sstevel@tonic-gate if (kwarnd_debug) 1071*0Sstevel@tonic-gate printf( 1072*0Sstevel@tonic-gate "could not delete warning\n"); 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate syslog(LOG_ERR, gettext( 1075*0Sstevel@tonic-gate "could not delete warning")); 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate exit(1); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate } /* if (now) */ 1082*0Sstevel@tonic-gate } /* for */ 1083*0Sstevel@tonic-gate } /* while */ 1084*0Sstevel@tonic-gate } /* func */ 1085