source: trunk/src/exepack.c@ 582

Last change on this file since 582 was 456, checked in by katerina, 10 years ago

Fix for ticket #356 (minor bug in exepack_fill.c).

File size: 5.9 KB
Line 
1#include "config.h"
2
3
4#include <stdlib.h>
5#include <stdio.h>
6
7#include <sys/types.h>
8#include <sys/wait.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <time.h>
12#include <unistd.h>
13#include <errno.h>
14
15extern char **environ;
16
17
18#include "minilzo.h"
19
20/* integer data type that is _exactly_ 32 bit
21 */
22#if defined(HAVE_INT_32)
23#define UINT32 unsigned int
24#elif defined(HAVE_LONG_32)
25#define UINT32 unsigned long
26#elif defined(HAVE_SHORT_32)
27#define UINT32 unsigned short
28#endif
29
30
31#include "exepack.data"
32
33
34static UINT32 cstate[3], astate[3];
35
36/* interval [0, 4294967296]
37 */
38static UINT32 taus_get_long (UINT32 * state)
39{
40#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
41
42 state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
43 state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4);
44 state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17);
45
46 return (state[0] ^ state[1] ^ state[2]);
47}
48
49void taus_set_from_state (UINT32 * state, UINT32 * state0)
50{
51 state[0] = state0[0] | (UINT32) 0x03;
52 state[1] = state0[1] | (UINT32) 0x09;
53 state[2] = state0[2] | (UINT32) 0x17;
54
55 /* 'warm up'
56 */
57 taus_get_long (state);
58 taus_get_long (state);
59 taus_get_long (state);
60 taus_get_long (state);
61 taus_get_long (state);
62 taus_get_long (state);
63
64 return;
65}
66
67void set2 (char * pos, char c1, char c2)
68{
69 pos[0] = c1;
70 pos[1] = c2;
71 return;
72}
73
74void set4 (char * pos, char c1, char c2, char c3, char c4)
75{
76 pos[0] = c1;
77 pos[1] = c2;
78 pos[2] = c3;
79 pos[3] = c4;
80 return;
81}
82
83int main(int argc, char *argv[])
84{
85 int file;
86 long result;
87
88 unsigned long i = argc; /* dummy use of argc to fix compiler warning */
89 unsigned long len = 0;
90
91 struct stat sbuf;
92 struct stat fbuf;
93
94 /* For compression.
95 */
96 lzo_byte * inbuf;
97 lzo_byte * outbuf;
98 int r;
99 lzo_uint in_len;
100 lzo_uint out_len;
101
102
103 char * p;
104
105 char fname[128];
106#if defined (__linux__)
107 char pname[128];
108#endif
109
110 UINT32 pid;
111
112 /* no SUID
113 */
114 if (getuid() != geteuid())
115 {
116 setuid(getuid());
117 }
118
119 /* reset umask
120 */
121 umask(0);
122
123
124 astate[0] = programkey_0[0];
125 astate[1] = programkey_0[1];
126 astate[2] = programkey_0[2];
127
128 taus_set_from_state (cstate, astate);
129
130 out_len = (unsigned long) programlen_compressed_0;
131 len = (unsigned long) programlen_0;
132 in_len = len;
133
134 outbuf = program_0;
135
136 /* Decode.
137 */
138 for (i = 0; i < out_len; ++i)
139 {
140 outbuf[i] ^= (taus_get_long (cstate) & 0xff);
141 }
142
143
144 inbuf = (lzo_byte *) malloc (sizeof(lzo_byte) * len);
145
146
147 /*
148 * Step 1: initialize the LZO library
149 */
150 if (lzo_init() != LZO_E_OK)
151 {
152 return 1;
153 }
154
155 /*
156 * Step 2: decompress again, now going from `out' to `in'
157 */
158 r = lzo1x_decompress_safe (outbuf, out_len, inbuf, &in_len, NULL);
159
160 if (r == LZO_E_OK && in_len == len)
161 {
162 /*
163 printf("decompressed %lu bytes back into %lu bytes\n",
164 (long) out_len, (long) in_len);
165 */
166 ;
167 }
168 else
169 {
170 /*
171 printf("internal error - decompression failed: %d\n",
172 r);
173 */
174 return 2;
175 }
176
177 /*
178 * Step 3: choose a filename
179 */
180
181 nameIt:
182
183 p = fname;
184
185 /* --- use /tmp if the sticky bit is set ---
186 */
187#if defined(S_ISVTX)
188
189 set4 (p, '/', 't', 'm', 'p');
190 p += 4;
191 *p = '\0';
192
193 if ( 0 != stat(fname, &sbuf))
194 {
195 if ( (sbuf.st_mode & S_ISVTX) != S_ISVTX)
196 {
197 p = fname;
198 set4 (p, '/', 'u', 's', 'r');
199 p += 4;
200 set4 (p, '/', 'b', 'i', 'n');
201 p += 4;
202 }
203 }
204
205#else
206
207 set4 (p, '/', 'u', 's', 'r');
208 p += 4;
209 set4 (p, '/', 'b', 'i', 'n');
210 p += 4;
211
212#endif
213
214 set4 (p, '/', 't', 'm', 'p');
215
216 p += 4;
217
218 cstate[0] ^= (UINT32) getpid ();
219 cstate[1] ^= (UINT32) time (NULL);
220 cstate[0] |= (UINT32) 0x03;
221 cstate[1] |= (UINT32) 0x09;
222
223 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
224
225 for (i = 0; i < 4; ++i)
226 {
227 *p = 'a' + (pid % 26);
228 pid /= 26;
229 ++p;
230 }
231
232 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
233
234 for (i = 0; i < 4; ++i)
235 {
236 *p = 'a' + (pid % 26);
237 pid /= 26;
238 ++p;
239 }
240
241 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
242
243 for (i = 0; i < 3; ++i)
244 {
245 *p = 'a' + (pid % 26);
246 pid /= 26;
247 ++p;
248 }
249 *p = '\0';
250
251 if ( (-1) != stat(fname, &sbuf) || errno != ENOENT)
252 {
253 /* because cstate[2] is not initialized, the next name will
254 * be different
255 */
256 goto nameIt;
257 }
258
259 if ((file = open (fname, O_CREAT|O_EXCL|O_WRONLY, 0700)) < 0)
260 {
261 return (4);
262 }
263
264 result = (long) write(file, inbuf, in_len);
265 if (result < 0 || in_len != (lzo_uint) result)
266 {
267 return (5);
268 }
269
270#if defined(__linux__)
271
272 if ( 0 != fstat(file, &sbuf))
273 {
274 return (6);
275 }
276
277 /* Must reopen for read only.
278 */
279 close(file);
280 file = open (fname, O_RDONLY, 0);
281
282 if ( 0 != fstat(file, &fbuf))
283 {
284 return (7);
285 }
286
287 /* check mode, inode, owner, and device, to make sure it is the same file
288 */
289 if (sbuf.st_mode != fbuf.st_mode ||
290 sbuf.st_ino != fbuf.st_ino ||
291 sbuf.st_uid != fbuf.st_uid ||
292 sbuf.st_gid != fbuf.st_gid ||
293 sbuf.st_dev != fbuf.st_dev )
294 {
295 close ( file );
296 return ( 8 );
297 }
298
299 p = pname;
300 set4(p, '/', 'p', 'r', 'o');
301 p += 4;
302
303 set2(p, 'c', '/');
304 p += 2;
305
306 set4(p, 's', 'e', 'l', 'f');
307 p += 4;
308
309 set4(p, '/', 'f', 'd', '/');
310 p += 4;
311
312 sprintf(p, "%d", file);
313
314
315 if (0 == access(pname, R_OK|X_OK))
316 {
317 unlink (fname);
318 fcntl (file, F_SETFD, FD_CLOEXEC);
319 execve (pname, argv, environ);
320 return (9);
321 }
322#endif
323
324 /* /proc not working, or not linux
325 */
326 close (file);
327
328 if ( (i = fork()) != 0)
329 {
330 wait (NULL);
331 execve (fname, argv, environ);
332 unlink (fname);
333 return (10);
334 }
335 else if (i == 0)
336 {
337 if (0 == fork())
338 {
339 sleep (3);
340 unlink (fname);
341 }
342 return (0);
343 }
344
345 /* only reached in case of error
346 */
347 unlink (fname);
348 return (-1);
349}
350
Note: See TracBrowser for help on using the repository browser.