static char * my_inet_ntoa(SINT32 ut_addr, char * buf, size_t buflen) { struct in_addr in; buf[0] = '\0'; memcpy(&in, ut_addr, sizeof(struct in_addr)); sl_strlcpy(buf, inet_ntoa(in), buflen); return buf; }
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_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")); }
static char * my_inet_ntoa(SINT32 * ut_addr_v6, char * buf, size_t buflen) { struct in_addr in; buf[0] = '\0'; if (0 == (ut_addr_v6[1] + ut_addr_v6[2] + ut_addr_v6[3])) { memcpy(&in, ut_addr_v6, sizeof(struct in_addr)); sl_strlcpy(buf, inet_ntoa(in), buflen); } else { inet_ntop(AF_INET6, ut_addr_v6, buf, buflen); } return buf; }
static void sh_prelink_fd(sh_tas_t * task) { SL_TICKET ticket; char * tmp; char hashbuf[KEYBUF_SIZE]; if (task->com_ti != (-1)) { (void) sl_close(task->com_ti); task->com_fd = -1; task->com_ti = -1; } ticket = sl_open_read(FIL__, __LINE__, task->command, task->privileged == 0 ? SL_NOPRIV : SL_YESPRIV); if (SL_ISERROR(ticket)) { char errbuf[SH_ERRBUF_SIZE]; char errbuf2[SH_ERRBUF_SIZE]; sh_error_message(errno, errbuf2, sizeof(errbuf2)); sl_strlcpy(errbuf, sl_error_string(ticket), sizeof(errbuf)); tmp = sh_util_safe_name (task->command); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_READ, errbuf, errbuf2, tmp); SH_FREE(tmp); return; } if (*(task->checksum) == '\0' || 0 == sl_strcmp(task->checksum, sh_tiger_hash (task->command, ticket, TIGER_NOLIM, hashbuf, sizeof(hashbuf)))) { task->com_fd = get_the_fd(ticket); task->com_ti = ticket; } else { tmp = sh_util_safe_name (task->command); sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_HASH, tmp); SH_FREE(tmp); (void) sl_close(ticket); } return; }
/* add a username to the list of logged-in users */ static int sh_utmp_login_a(char * str) { struct login_ct * list = login_ct_list; while (list) { if (0 == sl_strcmp(list->name, str)) { ++(list->nlogin); return list->nlogin; } list = list->next; } list = SH_ALLOC(sizeof(struct login_ct)); (void) sl_strlcpy(list->name, str, UT_NAMESIZE+1); list->nlogin = 1; list->next = login_ct_list; login_ct_list = list; return 1; }
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")); }
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; }
/* 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")); }
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")); }
/* --- 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")); }