source: trunk/src/sh_prelink.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 7.6 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2004 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22#include <string.h>
23#include <sys/types.h>
24#include <signal.h>
25
26#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
27
28#include "samhain.h"
29#include "sh_tiger.h"
30#include "sh_extern.h"
31#include "sh_utils.h"
32#include "sh_unix.h"
33
34#undef  FIL__
35#define FIL__  _("sh_prelink.c")
36
37static char * prelink_path = NULL;
38static char * prelink_hash = NULL;
39
[22]40int sh_prelink_set_path (const char * str)
[1]41{
42  SL_ENTER(_("sh_prelink_set_path"));
43  if (prelink_path != NULL)
44    SH_FREE(prelink_path);
45  if (str[0] != '/')
46    {
47      prelink_path = NULL;
48      SL_RETURN((-1), _("sh_prelink_set_path")); 
49    }
[374]50#ifdef SH_EVAL_SHELL
[34]51  prelink_path = sh_util_strdup(str);
[1]52  SL_RETURN(0, _("sh_prelink_set_path")); 
[374]53#else
54  prelink_path = NULL;
55  SL_RETURN((-1), _("sh_prelink_set_path"));
56#endif
[1]57}
58
[22]59int sh_prelink_set_hash (const char * str)
[1]60{
61  size_t len;
62  SL_ENTER(_("sh_prelink_set_hash"));
63  if (prelink_hash != NULL)
64    SH_FREE(prelink_hash);
65  len = sl_strlen (str);
66  if (len != KEY_LEN)
67    {
68      prelink_hash = NULL;
69      SL_RETURN((-1), _("sh_prelink_set_hash")); 
70    }
71  prelink_hash = SH_ALLOC(len+1);
72  (void) sl_strlcpy(prelink_hash, str, len+1);
73  SL_RETURN(0, _("sh_prelink_set_hash")); 
74}
75
[102]76int sh_prelink_iself (SL_TICKET fd, off_t size, int alert_timeout, char * path)
[1]77{
[102]78  long   status;
79  char   magic[4];
80  char * tmp;
[101]81
82  /* 42 bytes is about the minimum an ELF binary might have
83   * (with plenty of hacks to reduce the size, such as interleaving
84   * the code with the header...)
85   */
[8]86  if (size < 42)
87    return S_FALSE;
[101]88
[481]89  status = sl_read_timeout (fd, magic, 4, alert_timeout, S_FALSE);
[8]90  (void) sl_rewind(fd);
91  if (status == 4)
92    {
93      /*@-usedef@*/
94      if (magic[0] == (char) 0x7f &&
95          magic[1] == 'E'  &&
96          magic[2] == 'L'  &&
97          magic[3] == 'F')
98        return S_TRUE;
99      /*@+usedef@*/
100    }
[102]101  else
102    {
103      tmp = sh_util_safe_name (path);
104      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGPATH, 
105                      _("Error reading file"), _("sh_prelink_iself"), tmp);
106      SH_FREE(path);
107    }
[8]108  return S_FALSE;
[1]109}
110
111extern int get_the_fd (SL_TICKET ticket);
112
113static void sh_prelink_fd(sh_tas_t * task)
114{
115  SL_TICKET ticket;
116  char * tmp;
[133]117  char hashbuf[KEYBUF_SIZE];
[1]118
119  if (task->com_ti != (-1))
120    {
121      (void) sl_close(task->com_ti);
122      task->com_fd = -1;
123      task->com_ti = -1;
124    }
[248]125  ticket = sl_open_read(FIL__, __LINE__, task->command, 
[1]126                        task->privileged == 0 ? SL_NOPRIV : SL_YESPRIV);
127  if (SL_ISERROR(ticket))
128    {
[192]129      char errbuf[SH_ERRBUF_SIZE];
130      char errbuf2[SH_ERRBUF_SIZE];
131      sh_error_message(errno, errbuf2, sizeof(errbuf2));
132      sl_strlcpy(errbuf, sl_error_string(ticket), sizeof(errbuf));
[1]133      tmp = sh_util_safe_name (task->command);
[192]134      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_READ, errbuf, errbuf2, tmp);
[1]135      SH_FREE(tmp);
136      return;
137    }
[133]138
[1]139  if (*(task->checksum) == '\0' ||
140      0 == sl_strcmp(task->checksum, 
[160]141                     sh_tiger_hash (task->command, ticket, TIGER_NOLIM, hashbuf, sizeof(hashbuf))))
[1]142    {
143      task->com_fd = get_the_fd(ticket);
144      task->com_ti = ticket;
145    }
146  else
147    {
148      tmp = sh_util_safe_name (task->command);
149      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_HASH, tmp);
150      SH_FREE(tmp);
151      (void) sl_close(ticket);
152    }
153  return;
154}
155
156/* returns static storage
157 */
[481]158int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask)
[1]159{
160  static int      init = S_FALSE;
161  static int      args_filled = 0;
162  static sh_tas_t task;
163
164  int    status = 0;
165  char * p;
166
167  SL_ENTER(_("sh_prelink_run"));
168
169  /* reset if path == NULL
170   */
171  if (path == NULL)
172    {
173      if (init == S_FALSE)
174        {
175           SL_RETURN (0, _("sh_prelink_run"));
176        }
177      sh_ext_tas_free(&task);
178      init = S_FALSE;
179      args_filled = 0;
180      SL_RETURN (0, _("sh_prelink_run"));
181    }
182
183  /* initialize task structure
184   */
185  if (init == S_FALSE)
186    {
[132]187      char dir[SH_PATHBUF];
188
[1]189      sh_ext_tas_init(&task);
[132]190      p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir));
[1]191      if (p)
192        {
193          (void) sh_ext_tas_add_envv (&task, _("HOME"), p);
194        }
195      (void) sh_ext_tas_add_envv (&task, _("SHELL"), 
196                                  _("/bin/sh")); 
197      (void) sh_ext_tas_add_envv (&task, _("PATH"), 
198                                  _("/sbin:/usr/sbin:/bin:/usr/bin")); 
199      if (sh.timezone != NULL)
200        {
201          (void) sh_ext_tas_add_envv(&task,  "TZ", sh.timezone);
202        }
203      if (prelink_path == NULL)
204        {
205          sh_ext_tas_command(&task,  _("/usr/sbin/prelink"));
206          (void) sh_ext_tas_add_argv(&task,  _("/usr/sbin/prelink"));
207        }
208      else
209        {
210          sh_ext_tas_command(&task,  prelink_path);
211          (void) sh_ext_tas_add_argv(&task,  prelink_path);
212        }
213      args_filled = sh_ext_tas_add_argv(&task,  _("--verify"));
214
215      if (prelink_hash != NULL)
216        {
217          (void) sl_strlcpy(task.checksum, prelink_hash, KEY_LEN+1);
218        }
219      task.rw = 'r';
220      task.fork_twice = S_FALSE;
221
222      sh_prelink_fd(&task);
223
224      init = S_TRUE;
225    }
226
227  /* rm filename arg if set; fill in filename
228   */
229  if (args_filled == 3)
230    args_filled = sh_ext_tas_rm_argv(&task);
231  if (args_filled == 2)
232    args_filled = sh_ext_tas_add_argv(&task, path);
233  else
234    {
235      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, args_filled, MSG_E_SUBGEN, 
236                      _("Bad argument count"), _("sh_prelink_run"));
237      SL_RETURN ((-1), _("sh_prelink_run"));
238    }
239
240  /* open pipe
241   */
242  status = sh_ext_popen(&task);
243  if (status != 0)
244    {
245      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
246                      _("Could not open pipe"), _("sh_prelink_run"));
247      SL_RETURN ((-1), _("sh_prelink_run"));
248    }
249
250  if (SL_ISERROR(task.pipeTI))
251    {
252      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task.pipeTI, MSG_E_SUBGEN, 
253                      _("No valid ticket"), _("sh_prelink_run"));
254      SL_RETURN ((-1), _("sh_prelink_run"));
255    }
256
257  /* read from pipe
258   */
[8]259  sl_read_timeout_prep (task.pipeTI);
260
[133]261  {
262    char hashbuf[KEYBUF_SIZE];
[151]263    UINT64 length_nolim = TIGER_NOLIM;
[481]264    if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
[133]265    sl_strlcpy(file_hash,
[151]266               sh_tiger_generic_hash (path, task.pipeTI, &length_nolim, alert_timeout,
[133]267                                      hashbuf, sizeof(hashbuf)),
268               KEY_LEN+1);
269  }
[1]270
271  /* close pipe and return exit status
272   */
273  status = sh_ext_pclose(&task);
274  SL_RETURN ((status), _("sh_prelink_run"));
275}
276/* defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
277 */
278#endif
Note: See TracBrowser for help on using the repository browser.