tutil.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tutil.c (15615B)
---
1 /* Mixmaster version 3.0 -- (C) 1999 - 2006 Anonymizer Inc. and others.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Utility functions
9 $Id: util.c 934 2006-06-24 13:40:39Z rabbi $ */
10
11 #include "mix3.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <fcntl.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #ifdef POSIX
19 #include <signal.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <sys/file.h>
23 #include <termios.h>
24 #else /* end of POSIX */
25 #include <io.h>
26 #endif /* else if not POSIX */
27 #ifdef HAVE_GETKEY
28 #include <pc.h>
29 #endif /* HAVE_GETKEY */
30 #include <assert.h>
31
32 /** string comparison functions. return 1 on match, 0 otherwise ********/
33
34 int strileft(const char *string, const char *keyword)
35 {
36 register unsigned int i;
37
38 for (i = 0; keyword[i] != '\0'; i++)
39 if (tolower(string[i]) != tolower(keyword[i]))
40 return 0;
41 return 1;
42 }
43
44 int striright(const char *string, const char *keyword)
45 {
46 int l;
47 l = strlen(string) - strlen(keyword);
48 return (l >= 0 ? strieq(string + l, keyword) : -1);
49 }
50
51 int strleft(const char *string, const char *keyword)
52 {
53 register unsigned int i;
54
55 for (i = 0; keyword[i] != '\0'; i++)
56 if (string[i] != keyword[i])
57 return 0;
58 return 1;
59 }
60
61 int strifind(const char *string, const char *keyword)
62 {
63 register unsigned int i, j;
64 char k;
65
66 k = tolower(keyword[0]);
67 for (i = 0; string[i] != '\0'; i++) {
68 if (tolower(string[i]) == k) {
69 for (j = 1; keyword[j] != '\0'; j++)
70 if (tolower(string[i + j]) != tolower(keyword[j]))
71 goto next;
72 return 1;
73 }
74 next:
75 ;
76 }
77 return 0;
78 }
79
80 int strieq(const char *s1, const char *s2)
81 {
82 register unsigned int i = 0;
83
84 do
85 if (tolower(s1[i]) != tolower(s2[i]))
86 return 0;
87 while (s1[i++] != '\0') ;
88 return 1;
89 }
90
91 int streq(const char *a, const char *b)
92 {
93 return (strcmp(a, b) == 0);
94 }
95
96 int strfind(const char *a, const char *keyword)
97 {
98 return (strstr(a, keyword) != NULL);
99 }
100
101 void strcatn(char *dest, const char *src, int n)
102 {
103 int l;
104 l = strlen(dest);
105 if (l < n)
106 strncpy(dest + l, src, n - l - 1);
107 dest[n-1] = '\0';
108 }
109
110 /** files **************************************************************/
111
112 int mixfile(char *path, const char *name)
113 {
114 char *h;
115 assert(path != NULL && name != NULL);
116
117 #ifdef POSIX
118 if (name[0] == '~' && name[1] == DIRSEP && (h = getenv("HOME")) != NULL) {
119 strncpy(path, h, PATHMAX);
120 path[PATHMAX-1] = '\0';
121 strcatn(path, name + 1, PATHMAX);
122 } else
123 #endif /* POSIX */
124 if (name[0] == DIRSEP || (isalpha(name[0]) && name[1] == ':') || MIXDIR == NULL) {
125 strncpy(path, name, PATHMAX);
126 path[PATHMAX-1] = '\0';
127 } else {
128 strncpy(path, MIXDIR, PATHMAX);
129 path[PATHMAX-1] = '\0';
130 strcatn(path, name, PATHMAX);
131 }
132 return (0);
133 }
134
135 FILE *mix_openfile(const char *name, const char *a)
136 {
137 char path[PATHMAX];
138
139 mixfile(path, name);
140 return (fopen(path, a));
141 }
142
143 FILE *openpipe(const char *prog)
144 {
145 FILE *p = NULL;
146
147 #ifdef POSIX
148 p = popen(prog, "w");
149 #endif /* POSIX */
150 #ifdef _MSC
151 p = _popen(prog, "w");
152 #endif /* _MSC */
153
154 if (p == NULL)
155 errlog(ERRORMSG, "Unable to open pipe to %s\n", prog);
156 return p;
157 }
158
159 int
160 file_to_out(const char *filename)
161 {
162 int len;
163 FILE *fp;
164 char chunk[1024];
165
166 if ((fp = mix_openfile(filename, "r")) == NULL)
167 return -1;
168 while ((len = fread(chunk, 1, sizeof(chunk), fp)) > 0)
169 {
170 fwrite(chunk, 1, len, stdout);
171 }
172 fclose (fp);
173 return (len == 0 ? 0 : (-1));
174 }
175
176 int closepipe(FILE *p)
177 {
178 #ifdef POSIX
179 return (pclose(p));
180 #elif defined(_MSC) /* end of POSIX */
181 return (_pclose(p));
182 #else /* end of defined(_MSC) */
183 return -1;
184 #endif /* else if not defined(_MSC), POSIX */
185 }
186
187 /** Base 64 encoding ****************************************************/
188
189 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
190 static byte asctobin[] =
191 {
192 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
193 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
194 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
195 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
196 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
197 0x80, 0x80, 0x80, 0076, 0x80, 0x80, 0x80, 0077,
198 0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073,
199 0074, 0075, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
200 0x80, 0000, 0001, 0002, 0003, 0004, 0005, 0006,
201 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016,
202 0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026,
203 0027, 0030, 0031, 0x80, 0x80, 0x80, 0x80, 0x80,
204 0x80, 0032, 0033, 0034, 0035, 0036, 0037, 0040,
205 0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050,
206 0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060,
207 0061, 0062, 0063, 0x80, 0x80, 0x80, 0x80, 0x80,
208
209 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
210 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
211 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
212 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
213 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
214 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
215 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
216 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
217 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
218 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
219 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
220 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
221 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
222 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
223 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
224 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
225 };
226
227 void id_encode(byte id[], byte *s)
228 {
229 sprintf
230 (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
231 id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9],
232 id[10], id[11], id[12], id[13], id[14], id[15]);
233 }
234
235 void id_decode(byte *s, byte id[])
236 {
237 int i, x[16];
238
239 sscanf
240 (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
241 x, x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7, x + 8,
242 x + 9, x + 10, x + 11, x + 12, x + 13, x + 14, x + 15);
243 for (i = 0; i < 16; i++)
244 id[i] = x[i];
245 }
246
247 int encode(BUFFER *in, int linelen)
248 {
249 byte *b, *e;
250 int i, l, m;
251 unsigned long u;
252 BUFFER *out;
253
254 out = buf_new();
255
256 l = in->length;
257 if (l % 3 != 0)
258 l += 2;
259 l = l / 3 * 4;
260
261 if (linelen) {
262 l += l / linelen + (l % linelen > 0 ? 1 : 0);
263 }
264 linelen /= 4; /* blocks of 4 characters */
265
266 buf_prepare(out, l);
267
268 b = in->data;
269 e = out->data;
270 m = in->length - 2;
271 for (i = 0, l = 0; i < m; i += 3) {
272 u = ((unsigned long) b[i] << 16) | ((unsigned long) b[i + 1] << 8) |
273 b[i + 2];
274 *e++ = bintoasc[(u >> 18) & 0x3f];
275 *e++ = bintoasc[(u >> 12) & 0x3f];
276 *e++ = bintoasc[(u >> 6) & 0x3f];
277 *e++ = bintoasc[u & 0x3f];
278 if (linelen && ++l >= linelen) {
279 l = 0;
280 *e++ = '\n';
281 }
282 }
283 if (i < in->length) {
284 *e++ = bintoasc[b[i] >> 2];
285 *e++ = bintoasc[((b[i] << 4) & 0x30) | ((b[i + 1] >> 4) & 0x0f)];
286 if (i + 1 == in->length)
287 *e++ = '=';
288 else
289 *e++ = bintoasc[((b[i + 1] << 2) & 0x3c) | ((b[i + 2] >> 6) & 0x03)];
290 *e++ = '=';
291 ++l;
292 }
293 if (linelen && l != 0)
294 *e++ = '\n';
295 *e = '\0';
296
297 assert(out->data + out->length == e);
298 buf_move(in, out);
299 buf_free(out);
300 return (0);
301 }
302
303 int decode(BUFFER *in, BUFFER *out)
304 {
305 int err = 0;
306 register byte c0 = 0, c1 = 0, c2 = 0, c3 = 0;
307 register byte *a, *d, *end;
308 int tempbuf = 0;
309 int i;
310
311 if (in == out) {
312 out = buf_new();
313 tempbuf = 1;
314 }
315 buf_prepare(out, 3 * (in->length - in->ptr) / 4);
316
317 a = in->data + in->ptr;
318 end = in->data + in->length - 3;
319 d = out->data;
320 i = 0;
321
322 while (a < end) {
323 if ((c0 = asctobin[a[0]]) & 0x80 ||
324 (c1 = asctobin[a[1]]) & 0x80 ||
325 (c2 = asctobin[a[2]]) & 0x80 ||
326 (c3 = asctobin[a[3]]) & 0x80) {
327 if (a[0] == '\n') { /* ignore newline */
328 a++;
329 continue;
330 } else if (a[0] == '\r' && a[1] == '\n') { /* ignore crlf */
331 a += 2;
332 continue;
333 } else if (a[0] == '=' && a[1] == '4' && a[2] == '6' && !(asctobin[a[5]] & 0x80) ) {
334 a += 2; /* '=46' at the left of a line really is 'F' */
335 *a = 'F'; /* fix in memory ... */
336 continue;
337 } else if (a[2] == '=' || a[3] == '=') {
338 if (a[0] & 0x80 || (c0 = asctobin[a[0]]) & 0x80 ||
339 a[1] & 0x80 || (c1 = asctobin[a[1]]) & 0x80)
340 err = -1;
341 else if (a[2] == '=')
342 c2 = 0, i += 1;
343 else if (a[2] & 0x80 || (c2 = asctobin[a[2]]) & 0x80)
344 err = -1;
345 else
346 i += 2;
347 if (err == 0) {
348 /* read the correct final block */
349 *d++ = (byte) ((c0 << 2) | (c1 >> 4));
350 *d++ = (byte) ((c1 << 4) | (c2 >> 2));
351 if (a[3] != '=')
352 *d++ = (byte) ((c2 << 6));
353 #if 1
354 if (a + 4 < in->data + in->length) {
355 a += 4;
356 continue; /* support Mixmaster 2.0.3 encoding */
357 }
358 #endif /* 1 */
359 break;
360 }
361 }
362 err = -1;
363 break;
364 }
365 a += 4;
366
367 *d++ = (byte) ((c0 << 2) | (c1 >> 4));
368 *d++ = (byte) ((c1 << 4) | (c2 >> 2));
369 *d++ = (byte) ((c2 << 6) | c3);
370 i += 3;
371 }
372
373 in->ptr = a - in->data;
374
375 assert(i <= out->length);
376 out->length = i;
377
378 if (tempbuf) {
379 buf_move(in, out);
380 buf_free(out);
381 }
382 return (err);
383 }
384
385 LOCK *lockfile(char *filename)
386 {
387 LOCK *l;
388 char name[LINELEN];
389
390 strcpy(name, "lck");
391 if (strchr(filename, DIRSEP))
392 strcatn(name, strrchr(filename, DIRSEP), LINELEN);
393 else
394 strcatn(name, filename, LINELEN);
395 l = malloc(sizeof(LOCK));
396
397 l->name = malloc(PATHMAX);
398 mixfile(l->name, name);
399 l->f = mix_openfile(l->name, "w+");
400 if (l->f)
401 lock(l->f);
402 return (l);
403 }
404
405 int unlockfile(LOCK *l)
406 {
407 if (l->f) {
408 unlock(l->f);
409 fclose(l->f);
410 }
411 unlink(l->name);
412 free(l->name);
413 free(l);
414 return (0);
415 }
416
417 int lock(FILE *f)
418 {
419 #ifndef WIN32
420 struct flock lockstruct;
421
422 lockstruct.l_type = F_WRLCK;
423 lockstruct.l_whence = 0;
424 lockstruct.l_start = 0;
425 lockstruct.l_len = 0;
426 return (fcntl(fileno(f), F_SETLKW, &lockstruct));
427 #else /* end of WIN32 */
428 return (0);
429 #endif /* else if not WIN32 */
430 }
431
432 int unlock(FILE *f)
433 {
434 #ifndef WIN32
435
436 struct flock lockstruct;
437
438 lockstruct.l_type = F_UNLCK;
439 lockstruct.l_whence = 0;
440 lockstruct.l_start = 0;
441 lockstruct.l_len = 0;
442 return (fcntl(fileno(f), F_SETLKW, &lockstruct));
443 #else /* end of not WIN32 */
444 return (0);
445 #endif /* else if WIN32 */
446 }
447
448 /* get passphrase ******************************************************/
449
450 static int getuserpass(BUFFER *b, int mode)
451 {
452 char p[LINELEN];
453 int fd;
454 int n;
455
456 #ifdef HAVE_TERMIOS
457 struct termios attr;
458
459 #endif /* HAVE_TERMIOS */
460
461 if (mode == 0)
462 fprintf(stderr, "enter passphrase: ");
463 else
464 fprintf(stderr, "re-enter passphrase: ");
465 fflush(stderr);
466 #ifndef UNIX
467 #ifdef HAVE_GETKEY
468 for (n = 0; p[n] != '\n' && n < LINELEN; n++) {
469 p[n] = getkey();
470 }
471 p[n] = 0;
472 #else /* end of HAVE_GETKEY */
473 scanf("%127s", p);
474 #endif /* else if not HAVE_GETKEY */
475 #else /* end of not UNIX */
476 fd = open("/dev/tty", O_RDONLY);
477 if (tcgetattr(fd, &attr) != 0)
478 return (-1);
479 attr.c_lflag &= ~ECHO;
480 attr.c_lflag |= ICANON;
481 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
482 return (-1);
483
484 n = read(fd, p, LINELEN);
485
486 attr.c_lflag |= ECHO;
487 if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
488 return (-1);
489
490 close(fd);
491 fprintf(stderr, "\n");
492 p[n - 1] = 0;
493 #endif /* else if UNIX */
494 if (mode == 0)
495 buf_appends(b, p);
496 else
497 return (bufeq(b, p));
498 return (0);
499 }
500
501 static BUFFER *userpass = NULL;
502
503 int user_pass(BUFFER *key)
504 {
505 if (userpass == NULL) {
506 userpass = buf_new();
507 userpass->sensitive = 1;
508 if (getenv("MIXPASS"))
509 buf_sets(userpass, getenv("MIXPASS"));
510 else if (menu_getuserpass(userpass, 0) == -1)
511 getuserpass(userpass, 0);
512 }
513 buf_set(key, userpass);
514 key->sensitive = 1;
515 return (0);
516 }
517
518 int user_confirmpass(BUFFER *key)
519 {
520 int ok;
521
522 ok = menu_getuserpass(key, 1);
523 if (ok == -1)
524 ok = getuserpass(key, 1);
525 return (ok);
526 }
527
528 void user_delpass(void)
529 {
530 if (userpass)
531 buf_free(userpass);
532 userpass = NULL;
533 }
534
535 int write_pidfile(char *pidfile)
536 {
537 int err = 0;
538 #ifdef POSIX
539 FILE *f;
540 char host[LINELEN], myhostname[LINELEN];
541 int pid, mypid;
542 int assigned;
543
544 mypid = getpid();
545 gethostname(myhostname, LINELEN);
546 myhostname[LINELEN-1] = '\0';
547
548 f = mix_openfile(pidfile, "r+");
549 if (f != NULL) {
550 assert(LINELEN > 71);
551 assigned = fscanf(f, "%d %70s", &pid, host);
552 if (assigned == 2) {
553 if (strcmp(host, myhostname) == 0) {
554 if (kill (pid, 0) == -1) {
555 if (errno == ESRCH) {
556 fprintf(stderr, "Rewriting stale pid file.\n");
557 rewind(f);
558 ftruncate(fileno(f), 0);
559 fprintf(f, "%d %s\n", mypid, myhostname);
560 } else {
561 fprintf(stderr, "Pid file exists and process still running.\n");
562 err = -1;
563 }
564 } else {
565 fprintf(stderr, "Pid file exists and process still running.\n");
566 err = -1;
567 }
568 } else {
569 /* Pid file was written on another host, fail */
570 fprintf(stderr, "Pid file exists and was created on another host (%s).\n", host);
571 err = -1;
572 }
573 } else {
574 fprintf(stderr, "Pid file exists and and could not be parsed.\n");
575 err = -1;
576 }
577 } else {
578 if (errno == ENOENT) {
579 f = mix_openfile(pidfile, "w+");
580 if (f != NULL) {
581 fprintf(f, "%d %s\n", mypid, myhostname);
582 } else {
583 fprintf(stderr, "Could not open pidfile for writing: %s\n", strerror(errno));
584 err = -1;
585 }
586 } else {
587 fprintf(stderr, "Could not open pidfile for readwrite: %s\n", strerror(errno));
588 err = -1;
589 };
590 }
591 if(f)
592 fclose(f);
593 #endif /* POSIX */
594 return (err);
595 }
596
597 int clear_pidfile(char *pidfile)
598 {
599 #ifdef POSIX
600 char path[PATHMAX];
601
602 mixfile(path, pidfile);
603 return (unlink(path));
604 #else /* end of POSIX */
605 return (0);
606 #endif /* else if not POSIX */
607 }
608
609 time_t parse_yearmonthday(char* str)
610 {
611 time_t date;
612 int day, month, year;
613
614 if (sscanf( str, "%d-%d-%d", &year, &month, &day) == 3 ) {
615 struct tm timestruct;
616 char *tz;
617
618 tz = getenv("TZ");
619 #ifdef HAVE_SETENV
620 setenv("TZ", "GMT", 1);
621 #else /* end of HAVE_SETENV */
622 putenv("TZ=GMT");
623 #endif /* else if not HAVE_SETENV */
624 tzset();
625 memset(×truct, 0, sizeof(timestruct));
626 timestruct.tm_mday = day;
627 timestruct.tm_mon = month - 1;
628 timestruct.tm_year = year - 1900;
629 date = mktime(×truct);
630 #ifdef HAVE_SETENV
631 if (tz)
632 setenv("TZ", tz, 1);
633 else
634 unsetenv("TZ");
635 #else /* end of HAVE_SETENV */
636 if (tz) {
637 char envstr[LINELEN];
638 snprintf(envstr, LINELEN, "TZ=%s", tz);
639 putenv(envstr);
640 } else
641 putenv("TZ=");
642 #endif /* else if not HAVE_SETENV */
643 tzset();
644 return date;
645 } else
646 return -1;
647 }
648
649 /* functions missing on some systems *************************************/
650
651 #ifdef __RSXNT__
652 int fileno(FILE *f)
653 {
654 return (f->_handle);
655 }
656
657 #endif /* __RSXNT__ */
658
659 #ifdef _MSC /* Visual C lacks dirent */
660
661 DIR *opendir(const char *name)
662 {
663 DIR *dir;
664 WIN32_FIND_DATA d;
665 char path[PATHMAX];
666
667 dir = malloc(sizeof(HANDLE));
668
669 sprintf(path, "%s%c*", name, DIRSEP);
670 *dir = FindFirstFile(path, &d);
671 /* first file found is "." -- can be safely ignored here */
672
673 if (*dir == INVALID_HANDLE_VALUE) {
674 free(dir);
675 return (NULL);
676 } else
677 return (dir);
678 }
679
680 struct dirent e;
681 struct dirent *readdir(DIR *dir)
682 {
683 WIN32_FIND_DATA d;
684 int ok;
685
686 ok = FindNextFile(*dir, &d);
687 if (ok) {
688 strncpy(e.d_name, d.cFileName, PATHMAX);
689 return (&e);
690 } else
691 return (NULL);
692 }
693
694 int closedir(DIR *dir)
695 {
696 if (dir) {
697 FindClose(*dir);
698 free(dir);
699 return (0);
700 }
701 return (-1);
702 }
703
704 #endif /* _MSC */