source: trunk/src/sh_prelink.c@ 14

Last change on this file since 14 was 8, checked in by rainer, 19 years ago

minor optimisations for speed

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