source: trunk/src/sh_prelink.c@ 101

Last change on this file since 101 was 101, checked in by rainer, 17 years ago

Fix compile bug with --with-kcheck

File size: 7.1 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 }
[34]50
51 prelink_path = sh_util_strdup(str);
52
[1]53 SL_RETURN(0, _("sh_prelink_set_path"));
54}
55
[22]56int sh_prelink_set_hash (const char * str)
[1]57{
58 size_t len;
59 SL_ENTER(_("sh_prelink_set_hash"));
60 if (prelink_hash != NULL)
61 SH_FREE(prelink_hash);
62 len = sl_strlen (str);
63 if (len != KEY_LEN)
64 {
65 prelink_hash = NULL;
66 SL_RETURN((-1), _("sh_prelink_set_hash"));
67 }
68 prelink_hash = SH_ALLOC(len+1);
69 (void) sl_strlcpy(prelink_hash, str, len+1);
70 SL_RETURN(0, _("sh_prelink_set_hash"));
71}
72
73int sh_prelink_iself (SL_TICKET fd, off_t size, int alert_timeout)
74{
[8]75 long status;
76 char magic[4];
[101]77
78 /* 42 bytes is about the minimum an ELF binary might have
79 * (with plenty of hacks to reduce the size, such as interleaving
80 * the code with the header...)
81 */
[8]82 if (size < 42)
83 return S_FALSE;
[101]84
[8]85 status = sl_read_timeout (fd, magic, 4, alert_timeout);
86 (void) sl_rewind(fd);
87 if (status == 4)
88 {
89 /*@-usedef@*/
90 if (magic[0] == (char) 0x7f &&
91 magic[1] == 'E' &&
92 magic[2] == 'L' &&
93 magic[3] == 'F')
94 return S_TRUE;
95 /*@+usedef@*/
96 }
97 return S_FALSE;
[1]98}
99
100extern int get_the_fd (SL_TICKET ticket);
101
102static void sh_prelink_fd(sh_tas_t * task)
103{
104 SL_TICKET ticket;
105 char * tmp;
106
107 if (task->com_ti != (-1))
108 {
109 (void) sl_close(task->com_ti);
110 task->com_fd = -1;
111 task->com_ti = -1;
112 }
113 ticket = sl_open_read(task->command,
114 task->privileged == 0 ? SL_NOPRIV : SL_YESPRIV);
115 if (SL_ISERROR(ticket))
116 {
117 tmp = sh_util_safe_name (task->command);
118 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_READ, tmp);
119 SH_FREE(tmp);
120 return;
121 }
122 tiger_fd = ticket;
123 if (*(task->checksum) == '\0' ||
124 0 == sl_strcmp(task->checksum,
125 sh_tiger_hash (task->command, TIGER_FD, 0)))
126 {
127 task->com_fd = get_the_fd(ticket);
128 task->com_ti = ticket;
129 }
130 else
131 {
132 tmp = sh_util_safe_name (task->command);
133 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, ticket, MSG_E_HASH, tmp);
134 SH_FREE(tmp);
135 (void) sl_close(ticket);
136 }
137 return;
138}
139
140/* returns static storage
141 */
142int sh_prelink_run (char * path, char * file_hash, int alert_timeout)
143{
144 static int init = S_FALSE;
145 static int args_filled = 0;
146 static sh_tas_t task;
147
148 int status = 0;
149 char * p;
150 struct sigaction new_act;
151 struct sigaction old_act;
152
153 SL_ENTER(_("sh_prelink_run"));
154
155 /* reset if path == NULL
156 */
157 if (path == NULL)
158 {
159 if (init == S_FALSE)
160 {
161 SL_RETURN (0, _("sh_prelink_run"));
162 }
163 sh_ext_tas_free(&task);
164 init = S_FALSE;
165 args_filled = 0;
166 SL_RETURN (0, _("sh_prelink_run"));
167 }
168
169 /* initialize task structure
170 */
171 if (init == S_FALSE)
172 {
173 sh_ext_tas_init(&task);
174 p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid);
175 if (p)
176 {
177 (void) sh_ext_tas_add_envv (&task, _("HOME"), p);
178 }
179 (void) sh_ext_tas_add_envv (&task, _("SHELL"),
180 _("/bin/sh"));
181 (void) sh_ext_tas_add_envv (&task, _("PATH"),
182 _("/sbin:/usr/sbin:/bin:/usr/bin"));
183 if (sh.timezone != NULL)
184 {
185 (void) sh_ext_tas_add_envv(&task, "TZ", sh.timezone);
186 }
187 if (prelink_path == NULL)
188 {
189 sh_ext_tas_command(&task, _("/usr/sbin/prelink"));
190 (void) sh_ext_tas_add_argv(&task, _("/usr/sbin/prelink"));
191 }
192 else
193 {
194 sh_ext_tas_command(&task, prelink_path);
195 (void) sh_ext_tas_add_argv(&task, prelink_path);
196 }
197 args_filled = sh_ext_tas_add_argv(&task, _("--verify"));
198
199 if (prelink_hash != NULL)
200 {
201 (void) sl_strlcpy(task.checksum, prelink_hash, KEY_LEN+1);
202 }
203 task.rw = 'r';
204 task.fork_twice = S_FALSE;
205
206 sh_prelink_fd(&task);
207
208 init = S_TRUE;
209 }
210
211 /* rm filename arg if set; fill in filename
212 */
213 if (args_filled == 3)
214 args_filled = sh_ext_tas_rm_argv(&task);
215 if (args_filled == 2)
216 args_filled = sh_ext_tas_add_argv(&task, path);
217 else
218 {
219 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, args_filled, MSG_E_SUBGEN,
220 _("Bad argument count"), _("sh_prelink_run"));
221 SL_RETURN ((-1), _("sh_prelink_run"));
222 }
223
224 /* open pipe
225 */
226 status = sh_ext_popen(&task);
227 if (status != 0)
228 {
229 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
230 _("Could not open pipe"), _("sh_prelink_run"));
231 SL_RETURN ((-1), _("sh_prelink_run"));
232 }
233
234 if (SL_ISERROR(task.pipeTI))
235 {
236 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task.pipeTI, MSG_E_SUBGEN,
237 _("No valid ticket"), _("sh_prelink_run"));
238 SL_RETURN ((-1), _("sh_prelink_run"));
239 }
240
241 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
242 */
243 new_act.sa_handler = SIG_IGN;
244 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
245
246 /* read from pipe
247 */
248 tiger_fd = task.pipeTI;
[8]249
250 sl_read_timeout_prep (task.pipeTI);
251
[22]252 sl_strlcpy(file_hash,
253 sh_tiger_generic_hash (path, TIGER_FD, 0, alert_timeout),
254 KEY_LEN+1);
[1]255
256 /* restore old signal handler
257 */
258 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
259
260 /* close pipe and return exit status
261 */
262 status = sh_ext_pclose(&task);
263 SL_RETURN ((status), _("sh_prelink_run"));
264}
265/* defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
266 */
267#endif
Note: See TracBrowser for help on using the repository browser.