void sh_kill_sub() { SH_MUTEX_LOCK(mutex_sub); if (sh_child_pid != -1) { int status; #ifdef WCONTINUED int wflags = WNOHANG|WUNTRACED|WCONTINUED; #else int wflags = WNOHANG|WUNTRACED; #endif close (parent2child[1]); close (child2parent[0]); /* Let's be rude. */ kill(sh_child_pid, SIGKILL); retry_msleep(1,0); if (sh_wait_ret == 0) sh_wait_ret = waitpid( -1, &status, wflags); else sh_wait_ret = waitpid(sh_child_pid, &status, wflags); sh_child_pid = -1; } SH_MUTEX_UNLOCK(mutex_sub); return; }
static void sh_utmp_setutent(void) { int error; int fd; SL_ENTER(_("sh_utmp_setutent")); ASSERT((sh_utmppath != NULL), _("sh_utmppath != NULL")); if (sh_utmppath == NULL) SL_RET0(_("sh_utmp_setutent")); if (sh_utmpfile == NULL) { SH_MUTEX_LOCK(mutex_thread_nolog); fd = (int) aud_open (FIL__, __LINE__, SL_NOPRIV, sh_utmppath, O_RDONLY, 0); SH_MUTEX_UNLOCK(mutex_thread_nolog); if (fd >= 0) { sh_utmpfile = fdopen(fd, "r"); } /* -- If (sh_utmpfile == NULL) then either the open() or the fdopen() * has failed. */ if (sh_utmpfile == NULL) { error = errno; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_ACCESS, (long) sh.real.uid, sh_utmppath); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RET0(_("sh_utmp_setutent")); } } (void) fseek (sh_utmpfile, 0L, SEEK_SET); if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR)) { sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */ (void) fseek (sh_utmpfile, 0L, SEEK_SET); } clearerr (sh_utmpfile); SL_RET0(_("sh_utmp_setutent")); }
int sh_utmp_set_logout_good (const char * c) { int retval; char tmp[32]; SL_ENTER(_("sh_utmp_set_logout_good")); tmp[0] = '='; tmp[1] = '\0'; (void) sl_strlcat (tmp, c, 32); SH_MUTEX_LOCK(mutex_thread_nolog); retval = sh_error_set_level (tmp, &ShUtmpLogout); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN(retval, _("sh_utmp_set_logout_good")); }
/************* * * module check * *************/ int sh_utmp_check () { SL_ENTER(_("sh_utmp_check")); if (ShUtmpActive == BAD) { #if defined(HAVE_PTHREAD) sh_inotify_remove(&inotify_watch); #endif SL_RETURN( (-1), _("sh_utmp_check")); } SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_check_internal (1); SL_RETURN(0, _("sh_utmp_check")); }
int sh_utmp_set_login_timer (const char * c) { long val; SL_ENTER(_("sh_utmp_set_login_timer")); val = strtol (c, (char **)NULL, 10); if (val <= 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, _("utmp timer"), c); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RETURN((-1), _("sh_utmp_set_login_timer")); } ShUtmpInterval = (time_t) val; SL_RETURN(0, _("sh_utmp_set_login_timer")); }
void sh_log_mark_check() { struct sh_mark_event * event; time_t now = time(NULL); time_t delay; /* variable 'event' might be clobbered by 'longjmp' or 'vfork' */ dummy_event = &event; DEBUG("debug: running mark check\n"); for (event = sh_log_mark_first(&delay, now); event; event = sh_log_mark_next (&delay, now)) { int severity; sh_string * alias; SH_MUTEX_LOCK(mutex_thread_nolog); severity = sh_log_lookup_severity(sh_string_str(event->queue_id)); if (severity < 0) severity = sh_mark_default_severity; DEBUG("debug: mark check: queue %s, severity %d\n", sh_string_str(event->queue_id), severity); sh_error_handle (severity, FIL__, __LINE__, 0, MSG_LOGMON_MARK, sh_string_str(event->label), (unsigned long) delay); alias = sh_log_lookup_alias(sh_string_str(event->queue_id)); if (alias) { sh_error_mail (sh_string_str(alias), severity, FIL__, __LINE__, 0, MSG_LOGMON_MARK, sh_string_str(event->label), (unsigned long) delay); } SH_MUTEX_UNLOCK(mutex_thread_nolog); } return; }
/************* * * module timer * *************/ int sh_utmp_timer (time_t tcurrent) { #if !defined(HAVE_PTHREAD) retry_msleep(1, 0); if ((time_t) (tcurrent - lastcheck) >= ShUtmpInterval) { lastcheck = tcurrent; return (-1); } return 0; #else int errnum = 0; if ( (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE) && sh.flag.checkSum != SH_CHECK_INIT ) { sh_inotify_wait_for_change(mode_path[1], &inotify_watch, &errnum, ShUtmpInterval); } lastcheck = tcurrent; if (SH_INOTIFY_ERROR(errnum)) { char ebuf[SH_ERRBUF_SIZE]; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_message(errnum, ebuf, sizeof(ebuf)); sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, errnum, MSG_E_SUBGEN, ebuf, _("sh_utmp_timer") ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } return -1; #endif }
static int sh_sub_stat_int(const char *path, struct stat *buf, char command) { int retval; volatile int sflag = 0; struct sh_sub_in inbuf; struct sh_sub_out outbuf; struct pollfd pfds; size_t len = strlen(path) + 1; if (len > SH_SUB_BUF) { if (command == SH_COM_LSTAT) { do { retval = lstat(path, buf); } while (retval < 0 && errno == EAGAIN); return retval; } else { do { retval = stat(path, buf); } while (retval < 0 && errno == EAGAIN); return retval; } } sl_strlcpy(inbuf.path, path, SH_SUB_BUF); inbuf.command = command; start: #ifdef SH_SUB_DBG debug_it("%d sh_child_pid %d\n", (int)getpid(), (int) sh_child_pid); #endif if (sh_child_pid == -1) sh_create_sub(); #ifdef SH_SUB_DBG debug_it("%d stat_sub %s (%d)\n", (int)getpid(), inbuf.path, (int) sh_child_pid); #endif SH_MUTEX_LOCK(mutex_sub_work); retval = sh_sub_write(parent2child[1], &inbuf, sizeof(inbuf)); if (retval < 0) { int error = errno; sh_kill_sub(); errno = error; sflag = 1; goto end; } #ifdef SH_SUB_DBG debug_it("%d stat_sub polling..\n", (int)getpid()); #endif pfds.fd = child2parent[0]; pfds.events = POLLIN; do { retval = poll(&pfds, 1, 300 * 1000); } while (retval < 0 && errno == EINTR); if (retval <= 0) { int error = errno; sh_kill_sub(); errno = (retval == 0) ? ETIMEDOUT : error; sflag = -1; goto end; } #ifdef SH_SUB_DBG debug_it("%d stat_sub reading..\n", (int)getpid()); #endif retval = sh_sub_read (child2parent[0], &outbuf, sizeof(outbuf)); if (retval < 0) { int error = errno; sh_kill_sub(); errno = error; sflag = 1; goto end; } end: ; /* 'label at end of compound statement' */ SH_MUTEX_UNLOCK(mutex_sub_work); if (sflag == 0) { #ifdef SH_SUB_DBG debug_it("%d stat_sub done..\n", (int)getpid()); #endif memcpy(buf, &(outbuf.sbuf), sizeof(struct stat)); errno = outbuf.errnum; return outbuf.retval; } else if (sflag == 1) { #ifdef SH_SUB_DBG debug_it("%d stat_sub error..\n", (int)getpid()); #endif /* could not read, thus subprocess may have gone */ sflag = 0; goto start; } return -1; }
static int sh_create_sub() { pid_t res; volatile int retval = 0; SH_MUTEX_LOCK(mutex_sub); #if !defined(O_NONBLOCK) #if defined(O_NDELAY) #define O_NONBLOCK O_NDELAY #else #define O_NONBLOCK 0 #endif #endif if (sh_child_pid == -1) { sigset_t signal_set_new; sigset_t signal_set_old; sigfillset ( &signal_set_new ); sigemptyset( &signal_set_old ); /* Create pipes. */ res = pipe (parent2child); if (res == 0) res = pipe (child2parent); if (res != 0) goto out; SH_SETSIGMASK(SIG_BLOCK, &signal_set_new, &signal_set_old); res = fork(); if (res == 0) { /* Child process. */ #ifdef _SC_OPEN_MAX int fdlimit = sysconf (_SC_OPEN_MAX); #else #ifdef OPEN_MAX int fdlimit = OPEN_MAX; #else int fdlimit = _POSIX_OPEN_MAX; #endif #endif int sflags, i, fd = 0; struct sigaction act; /* zero private information */ memset(skey, 0, sizeof(sh_key_t)); close (parent2child[1]); close (child2parent[0]); sflags = fcntl(parent2child[0], F_GETFL, 0); fcntl(parent2child[0], F_SETFL, sflags | O_NONBLOCK); sflags = fcntl(child2parent[1], F_GETFL, 0); fcntl(child2parent[1], F_SETFL, sflags | O_NONBLOCK); /* close inherited file descriptors */ if (fdlimit < 0) fdlimit = 20; /* POSIX lower limit */ while (fd < fdlimit) { if (fd != parent2child[0] && fd != child2parent[1]) close(fd); ++fd; } /* for (i = 0; i < 3; ++i) { if ( fcntl(i, F_GETFL, 0) == (-1)) (void) open(_("/dev/null"), O_RDWR, 0); } */ /* reset signal handling */ act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset( &act.sa_mask ); for (i = 1; i < NSIG; ++i) sigaction(i, &act, NULL); SH_SETSIGMASK(SIG_UNBLOCK, &signal_set_new, NULL); wait_for_command(); _exit(0); } else if (res > 0) { /* Parent process. */ int sflags; SH_SETSIGMASK(SIG_SETMASK, &signal_set_old, NULL); close (parent2child[0]); close (child2parent[1]); sflags = fcntl(parent2child[1], F_GETFL, 0); fcntl(parent2child[1], F_SETFL, sflags | O_NONBLOCK); sflags = fcntl(child2parent[0], F_GETFL, 0); fcntl(child2parent[0], F_SETFL, sflags | O_NONBLOCK); sh_child_pid = res; } else { /* Failure. */ SH_SETSIGMASK(SIG_SETMASK, &signal_set_old, NULL); close (parent2child[0]); close (parent2child[1]); close (child2parent[0]); close (child2parent[1]); retval = -1; } } out: ; /* 'label at end of compound statement' */ SH_MUTEX_UNLOCK(mutex_sub); return retval; }
struct sh_logrecord * sh_parse_syslog (sh_string * logline, void * fileinfo) { static const char * format0_1 = N_("%b %d %T"); static const char * format0_2 = N_("%Y-%m-%dT%T"); static char format_1[16]; static char format_2[16]; static int format_init = 0; static struct tm old_tm; static time_t old_time; const unsigned int Tpos = 10; volatile unsigned int tlen = 16; (void) fileinfo; if (!format_init) { sl_strlcpy(format_1, _(format0_1), sizeof(format_1)); sl_strlcpy(format_2, _(format0_2), sizeof(format_2)); format_init = 1; } if (flag_err_debug == SL_TRUE && sh_string_len(logline) > 0) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, logline->str, _("sh_parse_syslog")); SH_MUTEX_UNLOCK(mutex_thread_nolog); } if (logline && sh_string_len(logline) > tlen) { struct tm btime; char * ptr; int flag; size_t lengths[3]; memset(&btime, '\0', sizeof(struct tm)); btime.tm_isdst = -1; /* This is RFC 3164. */ if (logline->str[Tpos] != 'T') { logline->str[tlen-1] = '\0'; ptr = /*@i@*/strptime(logline->str, format_1, &btime); } /* RFC 3339 describes an alternative timestamp format. * Unfortunately, POSIX strptime() does not support reading * the TZ offset. */ else { ptr = strptime(logline->str, format_2, &btime); if (ptr) { tlen = 20; if (*ptr && *ptr != ' ') { do { ++ptr; ++tlen; } while (*ptr && *ptr != ' '); if (*ptr == ' ') *ptr = '\0'; } } } if (ptr && *ptr == '\0') /* no error, whole string consumed */ { unsigned int fields = 3; /* host program(\[pid\])+: message */ char ** array = split_array_ws(&(logline->str[tlen]), &fields, lengths); if (fields == 3) { struct sh_logrecord * record = SH_ALLOC(sizeof(struct sh_logrecord)); record->timestamp = conv_timestamp(&btime, &old_tm, &old_time); record->timestr = sh_string_new_from_lchar(logline->str, (tlen-1)); /* host */ record->host = sh_string_new_from_lchar(array[0], lengths[0]); /* program and pid */ if (NULL != (ptr = strchr(array[1], '['))) { *ptr = '\0'; ++ptr; record->pid = (pid_t) atoi(ptr); if (hidepid == 0 || !*ptr) { --ptr; *ptr = '['; } else { *ptr = '\0'; /* overwrite first digit */ --ptr; *ptr = ':'; /* overwrite ex-':' */ lengths[1] = strlen(array[1]); } } else { flag = 0; ptr = array[1]; if (ptr[lengths[1]] == ':') { ptr[lengths[1]] = '\0'; flag = 1; } record->pid = PID_INVALID; if (flag == 1) { ptr[lengths[1]] = ':'; } } /* message */ record->message = sh_string_new_from_lchar3(array[1], lengths[1], " ", 1, array[2], lengths[2]); SH_FREE(array); return record; } SH_FREE(array); } } /* corrupted logline */ return NULL; }
static void sh_utmp_addlogin (struct SH_UTMP_S * ut) { struct log_user * user = userlist; struct log_user * userold = userlist; #ifdef HAVE_UTTYPE struct log_user * username = userlist; #endif char ttt[TIM_MAX]; #ifdef HAVE_UTTYPE volatile int status; #endif SL_ENTER(_("sh_utmp_addlogin")); if (ut->ut_line[0] == '\0') SL_RET0(_("sh_utmp_addlogin")); /* for some stupid reason, AIX repeats the wtmp entry for logouts * with ssh */ if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0) { memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S)); SL_RET0(_("sh_utmp_addlogin")); } memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S)); /* Take the address to keep gcc from putting them into registers. * Avoids the 'clobbered by longjmp' warning. */ sh_dummy_userold = (void*) &userold; sh_dummy_user = (void*) &user; /* ------- find user -------- */ while (user != NULL) { if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) ) break; userold = user; user = user->next; } #ifdef HAVE_UTTYPE while (username != NULL) { if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) ) break; username = username->next; } #endif #ifdef HAVE_UTTYPE /* ---------- LOGIN -------------- */ if (ut->ut_type == USER_PROCESS) { if (user == NULL) { user = SH_ALLOC(sizeof(struct log_user)); user->next = userlist; userlist = (struct log_user *) user; } (void) sl_strlcpy((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE+1); (void) sl_strlcpy((char*)(user->name), ut->ut_name, UT_NAMESIZE+1); #ifdef HAVE_UTHOST (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1); #else user->ut_host[0] = '\0'; #endif #ifdef HAVE_UTADDR #ifdef HAVE_UTADDR_V6 my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF); #else my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF); #endif #endif user->time = ut->ut_time; if (username == NULL /* not yet logged in */ || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */ || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */ ) { status = sh_utmp_login_a((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG1X, #elif defined(HAVE_UTHOST) MSG_UT_LG1A, #else MSG_UT_LG1B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } else if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) { status = sh_utmp_login_a((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG2X, #elif defined(HAVE_UTHOST) MSG_UT_LG2A, #else MSG_UT_LG2B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } sh_utmp_login_morechecks(ut); goto out; } /* --------- LOGOUT ---------------- */ else if (ut->ut_name[0] == '\0' || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */ ) { if (user != NULL) { #if defined(__linux__) if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) { #endif status = sh_utmp_login_r((char*)user->name); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG3X, #elif defined(HAVE_UTHOST) MSG_UT_LG3A, #else MSG_UT_LG3B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, status ); SH_MUTEX_UNLOCK(mutex_thread_nolog); userold->next = user->next; if (user == userlist) userlist = user->next; sh_utmp_logout_morechecks((struct log_user *)user); SH_FREE((struct log_user *)user); user = NULL; #if defined(__linux__) } #endif } else { (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE); SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, MSG_UT_LG3C, terminated_line, ttt, 0 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); } goto out; } /* default */ goto out; /* #ifdef HAVE_UTTYPE */ #else if (user == NULL) /* probably a login */ { user = SH_ALLOC(sizeof(struct log_user)); sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1); sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1); #ifdef HAVE_UTHOST sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1); #endif #ifdef HAVE_UTADDR #ifdef HAVE_UTADDR_V6 my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF); #else my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF); #endif #endif user->time = ut->ut_time; user->next = userlist; userlist = user; SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (user->time, ttt, TIM_MAX); sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG1X, #elif defined(HAVE_UTHOST) MSG_UT_LG1A, #else MSG_UT_LG1B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, 1 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_login_morechecks(ut); } else /* probably a logout */ { SH_MUTEX_LOCK(mutex_thread_nolog); (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX); sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) MSG_UT_LG2X, #elif defined(HAVE_UTHOST) MSG_UT_LG2A, #else MSG_UT_LG2B, #endif user->name, user->ut_tty, #if defined(HAVE_UTHOST) && defined(HAVE_UTADDR) user->ut_host, user->ut_ship, #elif defined(HAVE_UTHOST) user->ut_host, #endif ttt, 1 ); SH_MUTEX_UNLOCK(mutex_thread_nolog); sh_utmp_logout_morechecks(user); userold->next = user->next; if (user == userlist) /* inserted Apr 4, 2004 */ userlist = user->next; SH_FREE(user); user = NULL; } #endif out: sh_dummy_user = NULL; sh_dummy_userold = NULL; SL_RET0(_("sh_utmp_addlogin")); }
static void sh_utmp_check_internal (int mode) { struct stat buf; int error; struct SH_UTMP_S * ut; unsigned long this_read; int val_retry; SL_ENTER(_("sh_utmp_check_internal")); /* error if no access */ do { val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/; } while (val_retry < 0 && errno == EINTR); if (0 != val_retry) { error = errno; SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS, (long) sh.real.uid, mode_path[mode]); SH_MUTEX_UNLOCK(mutex_thread_nolog); SL_RET0(_("sh_utmp_check_internal")); } /* modification time */ if (mode < 2) { if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/) { SL_RET0(_("sh_utmp_check_internal")); } else lastmod = buf.st_mtime; } /* file size */ if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2) { SH_MUTEX_LOCK(mutex_thread_nolog); sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT, mode_path[mode]); SH_MUTEX_UNLOCK(mutex_thread_nolog); lastread = 0; #ifndef USE_SETUTENT sh_utmp_feed_forward = 0L; #endif } if (mode < 2) lastsize = buf.st_size; if (buf.st_size == 0) SL_RET0(_("sh_utmp_check_internal")); sh_utmp_utmpname(mode_path[mode]); sh_utmp_setutent(); /* * feed forward if initializing * we need to do this here */ this_read = 0; if (mode < 2) { while (this_read < lastread) { (void) sh_utmp_getutent(); ++this_read; } } /* start reading */ this_read = 0; while (1 == 1) { ut = sh_utmp_getutent(); if (ut == NULL) break; /* modified: ut_user --> ut_name */ if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0' #ifdef HAVE_UTTYPE && ut->ut_type != DEAD_PROCESS #endif )) sh_utmp_addlogin (ut); ++this_read; } sh_utmp_endutent(); if (mode < 2) { lastread += this_read; #ifndef USE_SETUTENT sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S)); lastread = 0; #endif } SL_RET0(_("sh_utmp_check_internal")); }
/* not static to circumvent stupid gcc 4 bug */ int onlytrustedingrp(gid_t grp, uid_t *ulist, int * errval) { struct passwd *w; /* info about group member */ register uid_t *u; /* points to current ulist member */ register char **p; /* points to current group member */ struct group *g; /* pointer to group information */ register int flag = -1; /* group member found */ int status; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) struct group gr; char * buffer = NULL; struct passwd pw; char * pbuffer = NULL; #endif int retval = S_FALSE; SL_ENTER(_("onlytrustedingrp")); *errval = 0; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group writeable, group_gid: %ld\n", (UID_CAST)grp); #endif #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) buffer = calloc(1,SH_GRBUF_SIZE); status = sh_getgrgid_r(grp, &gr, buffer, SH_GRBUF_SIZE, &g); #else errno = 0; g = sh_getgrgid(grp); status = errno; #endif if (g == NULL) { if (status == ERANGE) *errval = status; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group_gid: %ld, no such group --> ERROR\n", (UID_CAST)grp); #endif retval = S_FALSE; goto end_retval; } /* empty group -> no problem if(g->gr_mem == NULL || g->gr_mem[0] == NULL ) SL_IRETURN(S_TRUE, _("onlytrustedingrp") ); */ /* check for untrusted members of the group */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) pbuffer = calloc(1,SH_PWBUF_SIZE); #endif for(p = g->gr_mem; *p != NULL; p++) { flag = -1; #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: group_member: %s\n", *p); #endif /* map user name to UID and compare */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) sh_getpwnam_r(*p, &pw, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwnam(*p); #endif if (w == NULL) /* not a valid user, ignore */ { flag = 0; } else /* check list of trusted users */ { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, checking whether it is trusted\n", (UID_CAST)(w->pw_uid)); #endif for(u = ulist; *u != tf_uid_neg; u++) { if (*u == (w->pw_uid) ) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif flag = 0; break; } else { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, no match\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif ; } } } /* not found */ if (flag == -1) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: user=%s (gid %ld), not a trusted user --> ERROR\n", *p, (UID_CAST)grp); #endif tf_baduid = w->pw_uid; retval = S_FALSE; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (pbuffer) free(pbuffer); #endif goto end_retval; } } #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (pbuffer) free(pbuffer); #endif #ifndef TEST_ONLY #ifdef HAVE_GETPWENT /* now check ALL users for their GID !!! */ SH_MUTEX_LOCK(mutex_pwent); while (NULL != (w = sh_getpwent())) { if (grp == (gid_t)(w->pw_gid)) { #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: checking group member %s, uid %ld\n", w->pw_name, (UID_CAST)w->pw_uid); #endif /* is it a trusted user ? */ flag = -1; for(u = ulist; *u != tf_uid_neg; u++) { if (*u == (uid_t)(w->pw_uid)) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)(w->pw_uid), (UID_CAST)(*u)); #endif flag = 0; break; } else { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: uid=%ld, trusted_uid=%ld, no match\n", (UID_CAST)(w->pw_uid), (UID_CAST)*u); #endif ; } } /* not found */ if (flag == -1) { #ifdef TRUST_DEBUG fprintf(stderr,"trustfile: group member %s not found in trusted users --> ERROR\n", w->pw_name); #endif tf_baduid = w->pw_uid; retval = S_FALSE; goto out; /* SL_IRETURN(S_FALSE, _("onlytrustedingrp")); */ } } } retval = S_TRUE; out: #ifdef HAVE_ENDPWENT sh_endpwent(); #endif SH_MUTEX_UNLOCK(mutex_pwent); /* TEST_ONLY */ #endif /* #ifdef HAVE_GETPWENT */ #endif #ifdef TRUST_DEBUG if (retval == S_TRUE) fprintf(stderr, "trustfile: group %ld: all members are trusted users --> OK\n", (UID_CAST)grp); #endif /* all found */ end_retval: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); #endif SL_IRETURN(retval, _("onlytrustedingrp")); }