source: trunk/src/sh_prelink.c@ 538

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

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

File size: 7.6 KB
Line 
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
40int sh_prelink_set_path (const char * str)
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 }
50#ifdef SH_EVAL_SHELL
51 prelink_path = sh_util_strdup(str);
52 SL_RETURN(0, _("sh_prelink_set_path"));
53#else
54 prelink_path = NULL;
55 SL_RETURN((-1), _("sh_prelink_set_path"));
56#endif
57}
58
59int sh_prelink_set_hash (const char * str)
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
76int sh_prelink_iself (SL_TICKET fd, off_t size, int alert_timeout, char * path)
77{
78 long status;
79 char magic[4];
80 char * tmp;
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 */
86 if (size < 42)
87 return S_FALSE;
88
89 status = sl_read_timeout (fd, magic, 4, alert_timeout, S_FALSE);
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 }
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 }
108 return S_FALSE;
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;
117 char hashbuf[KEYBUF_SIZE];
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 }
125 ticket = sl_open_read(FIL__, __LINE__, task->command,
126 task->privileged == 0 ? SL_NOPRIV : SL_YESPRIV);
127 if (SL_ISERROR(ticket))
128 {
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));
133 tmp = sh_util_safe_name (task->command);
134 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_READ, errbuf, errbuf2, tmp);
135 SH_FREE(tmp);
136 return;
137 }
138
139 if (*(task->checksum) == '\0' ||
140 0 == sl_strcmp(task->checksum,
141 sh_tiger_hash (task->command, ticket, TIGER_NOLIM, hashbuf, sizeof(hashbuf))))
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 */
158int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask)
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 {
187 char dir[SH_PATHBUF];
188
189 sh_ext_tas_init(&task);
190 p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir));
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 */
259 sl_read_timeout_prep (task.pipeTI);
260
261 {
262 char hashbuf[KEYBUF_SIZE];
263 UINT64 length_nolim = TIGER_NOLIM;
264 if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
265 sl_strlcpy(file_hash,
266 sh_tiger_generic_hash (path, task.pipeTI, &length_nolim, alert_timeout,
267 hashbuf, sizeof(hashbuf)),
268 KEY_LEN+1);
269 }
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.