static struct SH_UTMP_S * sh_utmp_getutent(void) { size_t in; static struct SH_UTMP_S out; SL_ENTER(_("sh_utmp_getutent")); ASSERT_RET((sh_utmpfile != NULL), _("sh_utmpfile != NULL"), (NULL)) in = fread (&out, sizeof(struct SH_UTMP_S), 1, sh_utmpfile); if (in != 1) { if (ferror (sh_utmpfile) != 0) { clearerr (sh_utmpfile); SL_RETURN(NULL, _("sh_utmp_getutent")); } else { SL_RETURN(NULL, _("sh_utmp_getutent")); } } SL_RETURN(&out, _("sh_utmp_getutent")); }
int sh_readconf_setTime (const char * str, ShTimerItem what) { unsigned long i = atoi (str); SL_ENTER( _("sh_readconf_setTime")); if (i < LONG_MAX) { if (what == SET_MAILTIME) { TPT((0, FIL__, __LINE__, _("msg=<Set mail timer to %ld>\n"), i)); sh.mailTime.alarm_interval = i; } else if (what == SET_FILETIME) { TPT((0, FIL__, __LINE__, _("msg=<Set filecheck timer to %ld>\n"),i)); sh.fileCheck.alarm_interval = i; } SL_RETURN( 0, _("sh_readconf_setTime")); } else { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALL, _("set timer"), (long) i); SL_RETURN( (-1), _("sh_readconf_setTime")); } }
static int isin(uid_t n, uid_t *list) { SL_ENTER(_("isin")); if (list == NULL) SL_IRETURN(S_FALSE, _("isin")); while(*list != tf_uid_neg && *list != n) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, trusted uid=%ld, no match\n", (UID_CAST) n, (UID_CAST) *list); #endif list++; } if (*list == tf_uid_neg) { #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, no match with any trusted user --> ERROR\n", (UID_CAST) n); #endif SL_IRETURN(S_FALSE, _("isin")); } #ifdef TRUST_DEBUG fprintf (stderr, "trustfile: owner_uid=%ld, trusted_uid=%ld, match found --> OK\n", (UID_CAST)n, (UID_CAST)*list); #endif SL_IRETURN(S_TRUE, _("isin")); }
int sh_utmp_end () { struct log_user * user = userlist; struct log_user * userold; SL_ENTER(_("sh_utmp_end")); while (user) { userold = user; user = user->next; SH_FREE(userold); } userlist = NULL; #ifdef HAVE_UTTYPE (void) sh_utmp_login_clean(); #endif /* Reset the flag, such that the module * can be re-enabled. */ set_defaults(); init_done = 0; #if defined(HAVE_PTHREAD) sh_inotify_remove(&inotify_watch); #endif SL_RETURN( (0), _("sh_utmp_end")); }
int sh_utmp_set_login_activate (const char * c) { int i; SL_ENTER(_("sh_utmp_set_login_activate")); i = sh_util_flagval(c, &ShUtmpActive); SL_RETURN(i, _("sh_utmp_set_login_activate")); }
static void sh_utmp_endutent(void) { SL_ENTER(_("sh_utmp_endutent")); if (NULL != sh_utmpfile) (void) sl_fclose(FIL__, __LINE__, sh_utmpfile); sh_utmpfile = NULL; SL_RET0(_("sh_utmp_endutent")); }
int sh_readconf_setCaps(const char * c) { int i; SL_ENTER(_("sh_readconf_setCaps")); i = sh_util_flagval(c, &sl_useCaps); SL_RETURN((i), _("sh_readconf_setCaps")); }
static void sh_utmp_utmpname(const char * str) { SL_ENTER(_("sh_utmp_utmpname")); if (sh_utmpfile != NULL) { (void) sl_fclose (FIL__, __LINE__, sh_utmpfile); sh_utmpfile = NULL; } (void) sl_strlcpy (sh_utmppath, str, 80); SL_RET0(_("sh_utmp_utmpname")); }
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")); }
/* not static to circumvent stupid gcc 4 bug */ int getfname(const char *fname, char *rbuf, int rsz) { #ifndef TRUST_MAIN register int status; #endif SL_ENTER(_("getfname")); /* * do the initial checking * NULL pointer */ if (fname == NULL || rbuf == NULL) SL_IRETURN(SL_ENULL, _("getfname")); if (rsz <= 0) SL_IRETURN(SL_ERANGE, _("getfname")); /* already a full path name */ if (*fname == '/') rbuf[0] = '\0'; else { if (CURDIR(rbuf, rsz) == NULL) { #ifdef TRUST_DEBUG fprintf(stderr, "trustfile: getcwd failed\n"); #endif SL_IRETURN(SL_EBADNAME, _("getfname")); } } /* * append the file name and reduce */ if (fname != NULL && *fname != '\0') { #ifndef TRUST_MAIN status = sl_strlcat(rbuf, "/", rsz); if (status == SL_ENONE) status = sl_strlcat(rbuf, fname, rsz); if (status != SL_ENONE) SL_IRETURN(status, _("getfname")); #else strncat(rbuf, "/", rsz-strlen(rbuf)-1); rbuf[rsz-1] = '\0'; strncat(rbuf, fname, rsz-strlen(rbuf)-1); rbuf[rsz-1] = '\0'; #endif } SL_IRETURN(dirz(rbuf), _("getfname")); }
static int sh_fInotify_watches(const char *s) { int retval = -1; char * foo; unsigned long value; SL_ENTER(_("sh_fInotify_watches")); value = strtoul(s, &foo, 0); if (*foo == '\0') { ShfInotifyWatches = (value > 2147483647) ? 2147483647 /* MAX_INT_32 */: value; retval = 0; } SL_RETURN((retval), _("sh_fInotify_watches")); }
int sh_prelink_set_hash (const char * str) { size_t len; SL_ENTER(_("sh_prelink_set_hash")); if (prelink_hash != NULL) SH_FREE(prelink_hash); len = sl_strlen (str); if (len != KEY_LEN) { prelink_hash = NULL; SL_RETURN((-1), _("sh_prelink_set_hash")); } prelink_hash = SH_ALLOC(len+1); (void) sl_strlcpy(prelink_hash, str, len+1); SL_RETURN(0, _("sh_prelink_set_hash")); }
/************* * * 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")); }
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_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")); }
int sh_readconf_set_nice (const char * c) { long val; SL_ENTER(_("sh_readconf_set_nice")); val = strtol (c, (char **)NULL, 10); if (val < -20 || val > 20) { SL_RETURN((-1), _("sh_readconf_set_nice")); } val = (val < -19 ? -19 : val); val = (val > 19 ? 19 : val); sh.flag.nice = val; SL_RETURN((0), _("sh_readconf_set_nice")); }
int sh_prelink_set_path (const char * str) { SL_ENTER(_("sh_prelink_set_path")); if (prelink_path != NULL) SH_FREE(prelink_path); if (str[0] != '/') { prelink_path = NULL; SL_RETURN((-1), _("sh_prelink_set_path")); } #ifdef SH_EVAL_SHELL prelink_path = sh_util_strdup(str); SL_RETURN(0, _("sh_prelink_set_path")); #else prelink_path = NULL; SL_RETURN((-1), _("sh_prelink_set_path")); #endif }
static int sh_fInotify_active(const char *s) { int value; SL_ENTER(_("sh_fInotify_active")); value = sh_util_flagval(s, &ShfInotifyActive); if (value == 0 && ShfInotifyActive != S_FALSE) { sh.flag.inotify |= SH_INOTIFY_USE; sh.flag.inotify |= SH_INOTIFY_DOSCAN; sh.flag.inotify |= SH_INOTIFY_NEEDINIT; } if (value == 0 && ShfInotifyActive == S_FALSE) { sh.flag.inotify = 0; } SL_RETURN((value), _("sh_fInotify_active")); }
static int sh_utmp_init_internal (void) { SL_ENTER(_("sh_utmp_init")); if (ShUtmpActive == BAD) SL_RETURN( (-1), _("sh_utmp_init")); /* do not re-initialize after a re-configuration */ if (init_done == 1) { SL_RETURN( (0), _("sh_utmp_init")); } lastcheck = time (NULL); userlist = NULL; memset (&save_utmp, 0, sizeof(struct SH_UTMP_S)); sh_utmp_check_internal (2); /* current logins */ sh_utmp_check_internal (0); init_done = 1; SL_RETURN( (0), _("sh_utmp_init")); }
int sh_readconf_set_path (char * which, const char * what) { int len; SL_ENTER( _("sh_readconf_set_path")); if (which == NULL || what == NULL) { TPT((0, FIL__, __LINE__ , _("msg=<Input error>\n"))); SL_RETURN( -1, _("sh_readconf_set_path")); } if (0 == sl_strcmp(what, _("AUTO"))) { len = sl_strlen(which); if ( (len + sl_strlen(sh.host.name) + 2) > SH_PATHBUF) { TPT((0, FIL__, __LINE__ , _("msg=<Path too large: %s:%s>\n"), which, sh.host.name)); SL_RETURN( -1, _("sh_readconf_set_path")); } else { which[len] = ':'; which[len+1] = '\0'; sl_strlcat(which, sh.host.name, SH_PATHBUF); } } else /* not auto */ { if (sl_strlen(what) > (SH_PATHBUF-1)) { TPT((0, FIL__, __LINE__ , _("msg=<Path too large: %s>\n"), what)); SL_RETURN( -1, _("sh_readconf_set_path")); } else { sl_strlcpy(which, what, SH_PATHBUF); } } SL_RETURN( 0, _("sh_readconf_set_path")); }
/* returns static storage */ int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask) { static int init = S_FALSE; static int args_filled = 0; static sh_tas_t task; int status = 0; char * p; SL_ENTER(_("sh_prelink_run")); /* reset if path == NULL */ if (path == NULL) { if (init == S_FALSE) { SL_RETURN (0, _("sh_prelink_run")); } sh_ext_tas_free(&task); init = S_FALSE; args_filled = 0; SL_RETURN (0, _("sh_prelink_run")); } /* initialize task structure */ if (init == S_FALSE) { char dir[SH_PATHBUF]; sh_ext_tas_init(&task); p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir)); if (p) { (void) sh_ext_tas_add_envv (&task, _("HOME"), p); } (void) sh_ext_tas_add_envv (&task, _("SHELL"), _("/bin/sh")); (void) sh_ext_tas_add_envv (&task, _("PATH"), _("/sbin:/usr/sbin:/bin:/usr/bin")); if (sh.timezone != NULL) { (void) sh_ext_tas_add_envv(&task, "TZ", sh.timezone); } if (prelink_path == NULL) { sh_ext_tas_command(&task, _("/usr/sbin/prelink")); (void) sh_ext_tas_add_argv(&task, _("/usr/sbin/prelink")); } else { sh_ext_tas_command(&task, prelink_path); (void) sh_ext_tas_add_argv(&task, prelink_path); } args_filled = sh_ext_tas_add_argv(&task, _("--verify")); if (prelink_hash != NULL) { (void) sl_strlcpy(task.checksum, prelink_hash, KEY_LEN+1); } task.rw = 'r'; task.fork_twice = S_FALSE; sh_prelink_fd(&task); init = S_TRUE; } /* rm filename arg if set; fill in filename */ if (args_filled == 3) args_filled = sh_ext_tas_rm_argv(&task); if (args_filled == 2) args_filled = sh_ext_tas_add_argv(&task, path); else { sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, args_filled, MSG_E_SUBGEN, _("Bad argument count"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } /* open pipe */ status = sh_ext_popen(&task); if (status != 0) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, _("Could not open pipe"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } if (SL_ISERROR(task.pipeTI)) { sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task.pipeTI, MSG_E_SUBGEN, _("No valid ticket"), _("sh_prelink_run")); SL_RETURN ((-1), _("sh_prelink_run")); } /* read from pipe */ sl_read_timeout_prep (task.pipeTI); { char hashbuf[KEYBUF_SIZE]; UINT64 length_nolim = TIGER_NOLIM; if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask); sl_strlcpy(file_hash, sh_tiger_generic_hash (path, task.pipeTI, &length_nolim, alert_timeout, hashbuf, sizeof(hashbuf)), KEY_LEN+1); } /* close pipe and return exit status */ status = sh_ext_pclose(&task); SL_RETURN ((status), _("sh_prelink_run")); }
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 int dirz(char *path) { register char *p = path;/* points to rest of path to clean up */ register char *q; /* temp pointer for skipping over stuff */ static char swp[MAXFILENAME]; SL_ENTER(_("dirz")); /* * standard error checking */ if (path == NULL) SL_IRETURN(SL_ENULL, _("dirz")); if (path[0] == '.') SL_IRETURN(SL_EINTERNAL, _("dirz")); /* * loop over the path name until everything is checked */ while(*p) { /* skip */ if (*p != '/') { p++; continue; } /* "/./" or "/." */ if (p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { /* yes -- delete "/." */ (void) strcpy(swp, &p[2]); /* known to fit */ (void) strcpy(p, swp); /* known to fit */ /* special case "/." as full path name */ if (p == path && *p == '\0') { *p++ = '/'; *p = '\0'; } } /* "//" */ else if (p[1] == '/') { /* yes -- skip */ for(q = &p[2]; *q == '/'; q++) ; (void) strcpy(swp, q); /* known to fit */ (void) strcpy(&p[1], swp); /* known to fit */ } /* "/../" or "/.." */ else if (p[1] == '.' && p[2] == '.' && (p[3] == '/' || p[3] == '\0')) { /* yes -- if it's root, delete .. only */ if (p == path) { (void) strcpy(swp, &p[3]); /* known to fit */ (void) strcpy(p, swp); /* known to fit */ } else { /* back up over previous component */ q = p - 1; while(q != path && *q != '/') q--; /* now wipe it out */ (void) strcpy(swp, &p[3]); /* known to fit */ (void) strcpy(q, swp); /* known to fit */ p = q; } } else p++; } SL_IRETURN(SL_ENONE, _("dirz")); }
/* not static to circumvent stupid gcc 4 bug */ int isingrp(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 */ int status; #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) struct group gr; char * buffer = NULL; struct passwd pwd; char * pbuffer = NULL; #endif SL_ENTER(_("isingrp")); *errval = 0; #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; goto end_false; } /* this will return at the first match */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) pbuffer = calloc(1,SH_PWBUF_SIZE); #endif for(p = g->gr_mem; *p != NULL; p++) { for(u = ulist; *u != tf_uid_neg; u++) { /* map user name to UID and compare */ #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) sh_getpwnam_r(*p, &pwd, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwnam(*p); #endif #ifdef TRUST_MAIN if (w != NULL && *u == (uid_t)(w->pw_uid) ) goto end_true; #else if (w != NULL && *u == (uid_t)(w->pw_uid) ) { goto end_true; } #endif } } /* added by R. Wichmann Fri Mar 30 08:16:14 CEST 2001: * a user can have a GID but no entry in /etc/group */ for(u = ulist; *u != tf_uid_neg; u++) { #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) sh_getpwuid_r(*u, &pwd, pbuffer, SH_PWBUF_SIZE, &w); #else w = sh_getpwuid(*u); #endif #ifdef TRUST_MAIN if (w != NULL && grp == (gid_t)(w->pw_gid) ) goto end_true; #else if (w != NULL && grp == (gid_t)(w->pw_gid) ) { goto end_true; } #endif } end_false: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); if (pbuffer) free(pbuffer); #endif SL_IRETURN(S_FALSE, _("isingrp")); end_true: #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) if (buffer) free(buffer); if (pbuffer) free(pbuffer); #endif SL_IRETURN(S_TRUE, _("isingrp")); }
/* 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")); }
int sl_trustfile(const char *fname, uid_t *okusers, uid_t *badusers) { char * fexp = NULL; /* file name fully expanded */ register char *p; /* used to hold name to be checked */ struct stat stbuf; /* used to check file permissions */ char c; /* used to hold temp char */ int errgrp = 0; SL_ENTER(_("sl_trustfile")); if (fname == NULL) SL_IRETURN(SL_EBADFILE, _("sl_trustfile")); fexp = calloc(1, MAXFILENAME ); if (!fexp) SL_IRETURN(SL_EMEM, _("sl_trustfile")); p = fexp; /* * next expand to the full file name * getfname sets sl_errno as appropriate */ #ifdef TRUST_MAIN sl_errno = getfname(fname, fexp, MAXFILENAME); if (sl_errno != 0) { free(fexp); return sl_errno; } #else if (SL_ISERROR(getfname(fname, fexp, MAXFILENAME))) { free(fexp); SL_IRETURN(sl_errno, _("sl_trustfile")); } #endif if (okusers == NULL && badusers == NULL) { okusers = rootonly; rootonly[EUIDSLOT] = tf_euid; } /* * now loop through the path a component at a time * note we have to special-case root */ while(*p) { /* * get next component */ while(*p && *p != '/') p++; /* save where you are */ if (p == fexp) { /* keep the / if it's the root dir */ c = p[1]; p[1] = '\0'; } else { /* clobber the / if it isn't the root dir */ c = *p; *p = '\0'; } /* * now get the information */ if (retry_lstat(FIL__, __LINE__, fexp, &stbuf) < 0) { (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ESTAT: stat(%s) failed,\n", fexp); fprintf(stderr, "maybe the file does not exist\n"); fprintf(stderr, "---------------------------------------------\n"); #endif free(fexp); SL_IRETURN(SL_ESTAT, _("sl_trustfile")); } #ifdef S_IFLNK /* * if it's a symbolic link, recurse */ if ((stbuf.st_mode & S_IFLNK) == S_IFLNK) { /* * this is tricky * if the symlink is to an absolute path * name, just call trustfile on it; but * if it's a relative path name, it's * interpreted WRT the current working * directory AND NOT THE FILE NAME!!!!! * so, we simply put /../ at the end of * the file name, then append the symlink * contents; trustfile will canonicalize * this, and the /../ we added "undoes" * the name of the symlink to put us in * the current working directory, at * which point the symlink contents (appended * to the CWD) are interpreted correctly. * got it? */ char * csym; /* contents of symlink file */ char * full; /* "full" name of symlink */ char *b; /* used to copy stuff around */ const char *t; /* used to copy stuff around */ int lsym; /* num chars in symlink ref */ int i; /* trustworthy or not? */ const char * t_const; char *end; /* * get what the symbolic link points to * * The original code does not check the return code of readlink(), * and has an off-by-one error * (MAXFILENAME instead of MAXFILENAME-1) * R.W. Tue May 29 22:05:16 CEST 2001 */ csym = calloc(1, MAXFILENAME ); if (!csym) { free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } lsym = readlink(fexp, csym, MAXFILENAME-1); if (lsym >= 0) csym[lsym] = '\0'; else { #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADNAME: readlink(%s) failed\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(csym); free(fexp); SL_IRETURN(SL_EBADNAME, _("sl_trustfile")); } full = calloc(1, MAXFILENAME ); if (!full) { free(csym); free(fexp); SL_IRETURN(SL_EMEM, _("sl_trustfile")); } /* * relative or absolute referent? */ if (csym[0] != '/') { /* pointer to one above last element */ end = &full[MAXFILENAME-1]; ++end; /* initialize pointers */ b = full; /* copy in base path */ t = fexp; while(*t && b < end) *b++ = *t++; /* smack on the /../ */ t_const = "/../"; t = (const char *)t_const; while(*t && b < end) *b++ = *t++; /* append the symlink referent */ t = csym; while(*t && b < end) *b++ = *t++; /* see if we're too big */ if (*t || b == end) { /* yes -- error */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; #ifdef TRUST_MAIN fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: ETRUNC: normalized path too long (%s)\n", fexp); fprintf(stderr, "---------------------------------------------\n"); #endif free(full); free(csym); free(fexp); SL_IRETURN(SL_ETRUNC, _("sl_trustfile")); } *b = '\0'; } else { /* absolute -- just copy */ /* overflow can't occur as the arrays */ /* are the same size */ (void) strcpy(full, csym); /* known to fit */ } /* * now check out this file and its ancestors */ if ((i = sl_trustfile(full, okusers, badusers)) != SL_ENONE) { free(full); free(csym); free(fexp); SL_IRETURN(i, _("sl_trustfile")); } /* * okay, this part is valid ... let's check the rest * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } free(full); free(csym); continue; } #endif #ifdef TRUST_DEBUG fprintf(stderr, "\ntrustfile: checking path=%s\n", fexp); #endif /* * if the owner is not trusted then -- as the owner can * change protection modes -- he/she can write to the * file regardless of permissions, so bomb */ if (((okusers != NULL && S_FALSE == isin((uid_t)stbuf.st_uid,okusers))|| (badusers != NULL && S_TRUE == isin((uid_t)stbuf.st_uid,badusers)))) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADUID %s (owner not trusted)\n", fexp); fprintf(stderr, "The owner of this file/directory is not in samhains\n"); fprintf(stderr, "list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_baduid = (uid_t) stbuf.st_uid; free(fexp); SL_IRETURN(SL_EBADUID, _("sl_trustfile")); } /* * if a group member can write but the * member is not trusted, bomb; but if * sticky bit semantics are honored, it's * okay */ /* Thu Mar 29 21:10:28 CEST 2001 Rainer Wichmann * replace !isingrp() with onlytrustedingrp(), as isingrp() * will return at the first trusted user, even if there are additional * (untrusted) users in the group */ if (((stbuf.st_mode & S_IWGRP) == S_IWGRP) && ((okusers != NULL && !onlytrustedingrp((gid_t)stbuf.st_gid,okusers,&errgrp))|| (badusers != NULL && isingrp((gid_t)stbuf.st_gid, badusers,&errgrp))) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADGID %ld %s (group member not trusted)\n", (UID_CAST)stbuf.st_gid, fexp); fprintf(stderr, "This file/directory is group writeable, and one of the group members\n"); fprintf(stderr, "is not in samhains list of trusted users.\n"); fprintf(stderr, "Please run ./configure again with the option\n"); fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; tf_badgid = (gid_t) stbuf.st_gid; free(fexp); SL_IRETURN((errgrp == ERANGE) ? SL_ERANGE : SL_EBADGID, _("sl_trustfile")); } /* * if other can write, bomb; but if the sticky * bit semantics are honored, it's okay */ if (((stbuf.st_mode & S_IWOTH) == S_IWOTH) #ifdef STICKY && ((stbuf.st_mode&S_IFDIR) != S_IFDIR || (stbuf.st_mode&S_ISVTX) != S_ISVTX) #endif ) { #ifdef TRUST_DEBUG fprintf(stderr, "---------------------------------------------\n"); fprintf(stderr, "trustfile: EBADOTH (world writeable): %s\n", fexp); fprintf(stderr, "This file/directory is world writeable.\n"); fprintf(stderr, "---------------------------------------------\n"); #endif (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_EBADOTH, _("sl_trustfile")); } /* * put the / back */ if (p == fexp) { /* special case for root */ p[1] = c; p++; } else { /* ordinary case for everything else */ *p = c; if (*p) p++; } } /* * yes, it can be trusted */ (void) strncpy(tf_path, fexp, sizeof(tf_path)); tf_path[sizeof(tf_path)-1] = '\0'; free(fexp); SL_IRETURN(SL_ENONE, _("sl_trustfile")); }
/* --- Read the configuration file. --- */ int sh_readconf_read (void) { #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) /* This is for modules. */ int modnum; #endif int i; SL_TICKET fd = -1; #if defined(SH_STEALTH) && !defined(SH_STEALTH_MICRO) SL_TICKET fdTmp = -1; #endif #if defined(WITH_GPG) || defined(WITH_PGP) SL_TICKET fdGpg = -1; #endif char * tmp; #define SH_LINE_IN 16384 char * line_in; char * line; /* This is for nested conditionals. */ int cond_depth = 0; int cond_excl = 0; int local_file = 1; char local_flag = 'R'; #if defined(WITH_GPG) || defined(WITH_PGP) int signed_content = S_FALSE; int true_content = S_FALSE; #endif #if defined(SH_STEALTH) && !defined(SH_STEALTH_MICRO) int hidden_count = 0; #endif uid_t euid; char hashbuf[KEYBUF_SIZE]; SL_ENTER(_("sh_readconf_read")); /* --- Open config file, exit on failure. --- */ #if defined(SH_WITH_CLIENT) if (0 == sl_strcmp(file_path('C', 'R'), _("REQ_FROM_SERVER"))) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_START); fd = sh_forward_req_file(_("CONF")); if (!SL_ISERROR(fd)) { local_file = 0; } else if (sh.flag.checkSum != SH_CHECK_INIT) { aud_exit (FIL__, __LINE__, EXIT_FAILURE); } else { sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_D_FAIL); local_file = 1; local_flag = 'I'; } } #endif /* Use a local configuration file. */ if (local_file == 1) { if (0 != tf_trust_check (file_path('C', local_flag), SL_YESPRIV)) { sl_get_euid(&euid); dlog(1, FIL__, __LINE__, _("The configuration file: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"), ( (NULL == file_path('C', local_flag)) ? _("(null)") : file_path('C', local_flag) )); sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST, (long) euid, ( (NULL == file_path('C', local_flag)) ? _("(null)") : file_path('C', local_flag) ) ); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } if (SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, file_path('C',local_flag),SL_YESPRIV))) { sl_get_euid(&euid); dlog(1, FIL__, __LINE__, _("Could not open the local configuration file for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"), sl_get_errmsg(), fd, (int) euid); sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_NOACCESS, (long) euid, ( (NULL == file_path('C', local_flag)) ? _("(null)") : file_path('C', local_flag) ) ); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } } /* Compute the checksum of the open file. */ sl_strlcpy(sh.conf.hash, sh_tiger_hash(file_path('C',local_flag), fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), KEY_LEN+1); sl_rewind (fd); line_in = SH_ALLOC(SH_LINE_IN); #if defined(SH_STEALTH) && !defined(SH_STEALTH_MICRO) /* extract the data and copy to temporary file */ fdTmp = open_tmp(); sh_unix_getline_stealth (0, NULL, 0); /* initialize */ while ( sh_unix_getline_stealth (fd, line_in, SH_LINE_IN-2) > 0) { hidden_count++; if (line_in[0] == '\n') { sl_write(fdTmp, line_in, 1); } else { sl_write_line(fdTmp, line_in, sl_strlen(line_in)); } #if defined(WITH_GPG) || defined(WITH_PGP) if (0 == sl_strncmp(line_in, _("-----END PGP SIGNATURE-----"), 25)) break; #else if (0 == sl_strncmp(line_in, _("[EOF]"), 5)) break; #endif if (hidden_count > 1048576) /* arbitrary safeguard, 1024*1024 */ break; } sl_close(fd); fd = fdTmp; sl_rewind (fd); #endif #if defined(WITH_GPG) || defined(WITH_PGP) /* extract the data and copy to temporary file */ fdGpg = sh_gpg_extract_signed(fd); sl_close(fd); fd = fdGpg; /* Validate signature of open file. */ if (0 != sh_gpg_check_sign (fd, 0, 1)) { SH_FREE(line_in); aud_exit (FIL__, __LINE__, EXIT_FAILURE); } sl_rewind (fd); #endif /* --- Start reading lines. --- */ conf_line = 0; while ( sh_unix_getline (fd, line_in, SH_LINE_IN-2) > 0) { ++conf_line; line = &(line_in[0]); /* fprintf(stderr, "<%s>\n", line); */ /* Sun May 27 18:40:05 CEST 2001 */ #if defined(WITH_GPG) || defined(WITH_PGP) if (signed_content == S_FALSE) { if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----"))) signed_content = S_TRUE; else continue; } else if (true_content == S_FALSE) { if (line[0] == '\n') true_content = S_TRUE; else continue; } else if (signed_content == S_TRUE) { if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNATURE-----"))) break; else if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----"))) { sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, _("second signed message in file"), _("sh_readconf_read")); dlog(1, FIL__, __LINE__, _("There seems to be more than one signed message in the configuration\nfile. Please make sure there is only one signed message.\n")); sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name); SH_FREE(line_in); aud_exit (FIL__, __LINE__,EXIT_FAILURE); } } #endif /* Skip leading white space. */ while (isspace((int)*line)) ++line; /* Skip header etc. */ if (line[0] == '#' || line[0] == '\0' || line[0] == ';' || (line[0] == '/' && line[1] == '/')) continue; /* Clip off trailing white space. */ tmp = line + sl_strlen( line ); --tmp; while( isspace((int) *tmp ) && tmp >= line ) *tmp-- = '\0'; /* --- an @host/@if/$system directive -------------- */ if (line[0] == '@' || (line[0] == '!' && line[1] == '@') || line[0] == '$' || (line[0] == '!' && line[1] == '$')) { if (sh_readconf_is_end(line)) { if (0 == cond_depth) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALD, _("config file"), (long) conf_line); } else { if (cond_excl == cond_depth) cond_excl = 0; --cond_depth; } } else if (sh_readconf_is_else(line)) { if (0 == cond_depth) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALD, _("config file"), (long) conf_line); } else if (cond_excl == cond_depth) { cond_excl = 0; } else if (cond_excl == 0) { cond_excl = cond_depth; } } else { if (sh_readconf_cond_match(line, conf_line)) { ++cond_depth; } else { ++cond_depth; if (cond_excl == 0) cond_excl = cond_depth; } } continue; } /**************************************************** * * Only carry on if this section is intended for us * ****************************************************/ if (cond_excl != 0) { continue; } /* ------- starts a section ------------ */ else if (line[0] == '[') { read_mode = SH_SECTION_NONE; if (0 == sl_strncasecmp (line, _("[EOF]"), 5)) { goto nopel; } i = 0; while (tab_ListSections[i].name != 0) { if (sl_strncasecmp (line, _(tab_ListSections[i].name), sl_strlen(tab_ListSections[i].name)) == 0) { read_mode = tab_ListSections[i].type; break; } ++i; } #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if (read_mode == SH_SECTION_NONE) { for (modnum = 0; modList[modnum].name != NULL; ++modnum) { if (0 == sl_strncasecmp (line, _(modList[modnum].conf_section), sl_strlen(modList[modnum].conf_section)) ) read_mode = SH_SECTION_OTHER; } } #endif if (read_mode == SH_SECTION_NONE) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALHEAD, (long) conf_line); } } /* --- an %schedule directive ------------ */ else if (line[0] == '%' || (line[0] == '!' && line[1] == '%')) { #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if (line[0] == '!' && 0 == sl_strcasecmp(&(line[2]), _("SCHEDULE_TWO"))) set_dirList(1); else if (0 == sl_strcasecmp(&(line[1]), _("SCHEDULE_TWO"))) set_dirList(2); #else ; #endif } /* ------ no new section -------------- */ else if (read_mode != SH_SECTION_NONE) { if (0 != sh_readconfig_line (line)) { sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALCONF, (long) conf_line); } } } /* while getline() */ nopel: if (0 != cond_depth) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALDD, _("config file"), (long) conf_line); sl_close (fd); sh_error_fixup(); read_mode = SH_SECTION_NONE; /* reset b/o sighup reload */ SH_FREE(line_in); SL_RETURN( 0, _("sh_readconf_read")); }
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")); }
static int sh_readconfig_line (char * line) { char * key; const char * value; char * tmp; int i; int good_opt = -1; #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) int modnum, modkey; #endif static const char *dummy = N_("dummy"); static const char *closing[] = { N_("closecommand"), N_("closeaddress"), N_("logmonendgroup"), N_("logmonendhost"), NULL }; static const char *ident[] = { N_("severityreadonly"), N_("severitylogfiles"), N_("severitygrowinglogs"), N_("severityignorenone"), N_("severityignoreall"), N_("severityattributes"), N_("severitydirs"), N_("severityfiles"), N_("severitynames"), N_("severityuser0"), N_("severityuser1"), N_("severityuser2"), N_("severityuser3"), N_("severityuser4"), N_("severityprelink"), NULL }; static int identnum[] = { SH_ERR_T_RO, SH_ERR_T_LOGS, SH_ERR_T_GLOG, SH_ERR_T_NOIG, SH_ERR_T_ALLIG, SH_ERR_T_ATTR, SH_ERR_T_DIR, SH_ERR_T_FILE, SH_ERR_T_NAME, SH_ERR_T_USER0, SH_ERR_T_USER1, SH_ERR_T_USER2, SH_ERR_T_USER3, SH_ERR_T_USER4, SH_ERR_T_PRELINK, }; SL_ENTER(_("sh_readconf_line")); /* convert to lowercase */ tmp = line; while (*tmp != '=' && *tmp != '\0') { *tmp = tolower( (int) *tmp); ++tmp; } key = line; /* interpret line */ value = strchr(line, '='); if (value == NULL || (*value) == '\0') { if (key != NULL) { i = 0; while (closing[i] != NULL) { if (sl_strncmp(key,_(closing[i]),sl_strlen(closing[i])-1) == 0) { value = dummy; goto ok_novalue; } ++i; } TPT(( 0, FIL__, __LINE__, _("msg=<ConfigFile: not key=value: %s>\n"), line)); } SL_RETURN(good_opt, _("sh_readconf_line")); } else ++value; /* skip leading whitespace */ while ((*value) == ' ' || (*value) == '\t') ++value; if ((*value) == '\0') /* no value */ { if (key != NULL) { TPT(( 0, FIL__, __LINE__, _("msg=<ConfigFile: not key=value: %s>\n"), line)); } SL_RETURN(good_opt, _("sh_readconf_line")); } ok_novalue: if (!sl_is_suid()) { TPT(( 0, FIL__, __LINE__, _("msg=<ConfigFile: %s>\n"), line)); } /* Expand shell expressions. This return allocated memory which we must free. * If !defined(SH_EVAL_SHELL), this will reduce to a strdup. */ value = sh_readconf_expand_value(value); if (!value || (*value) == '\0') { TPT(( 0, FIL__, __LINE__, _("msg=<ConfigFile: empty after shell expansion: %s>\n"), line)); SL_RETURN(good_opt, _("sh_readconf_line")); } #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) if (read_mode == SH_SECTION_OTHER) { for (modnum = 0; modList[modnum].name != NULL; ++modnum) { for (modkey = 0; modList[modnum].conf_table[modkey].the_opt != NULL; ++modkey) { if (sl_strncmp (key, _(modList[modnum].conf_table[modkey].the_opt), sl_strlen(modList[modnum].conf_table[modkey].the_opt) ) == 0) { good_opt = 0; if (0 != modList[modnum].conf_table[modkey].func(value)) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALS, _(modList[modnum].conf_table[modkey].the_opt), value); if (!sl_is_suid()) { TPT(( 0, FIL__, __LINE__, _("msg=<line = %s, option = %s>\n"), line, _(modList[modnum].conf_table[modkey].the_opt))); } goto outburst; } } } } outburst: #endif if (read_mode == SH_SECTION_THRESHOLD) { i = 0; while (ident[i] != NULL) { if (sl_strncmp (key, _(ident[i]), sl_strlen(ident[i])) == 0) { good_opt = 0; sh_error_set_iv (identnum[i], value); break; } ++i; } } else { i = 0; while (ext_table[i].optname != NULL) { if ((ext_table[i].section == read_mode || ext_table[i].alt_section == read_mode) && sl_strncmp (key, _(ext_table[i].optname), sl_strlen(ext_table[i].optname)) == 0) { good_opt = 0; if (0 != ext_table[i].func (value)) sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EINVALS, _(ext_table[i].optname), value); break; } ++i; } } SH_FREE((char*)value); SL_RETURN(good_opt, _("sh_readconf_line")); }