source: trunk/src/sh_tools.c@ 15

Last change on this file since 15 was 12, checked in by rainer, 19 years ago

More optimisation

File size: 38.9 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 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
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27
28/* Must be early on FreeBSD
29 */
30#include <sys/types.h>
31
32#ifdef HAVE_MEMORY_H
33#include <memory.h>
34#endif
35
36#ifdef HAVE_SYS_SELECT_H
37#include <sys/select.h>
38#endif
39
40#ifdef HAVE_UNISTD_H
41#include <errno.h>
42#include <signal.h>
43#include <setjmp.h>
44#include <pwd.h>
45#include <grp.h>
46#include <sys/stat.h>
47#include <sys/resource.h>
48#include <fcntl.h>
49#include <sys/wait.h>
50#include <unistd.h>
51#endif
52
53#include <sys/socket.h>
54
55#ifdef HOST_IS_HPUX
56#define _XOPEN_SOURCE_EXTENDED
57#endif
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#include <netdb.h>
61
62#ifndef FD_SET
63#define NFDBITS 32
64#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
65#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
66#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
67#endif /* !FD_SET */
68#ifndef FD_SETSIZE
69#define FD_SETSIZE 32
70#endif
71#ifndef FD_ZERO
72#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
73#endif
74
75
76#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
77#include <sys/mman.h>
78#endif
79
80#define SH_REAL_SET
81
82#include "samhain.h"
83#include "sh_mem.h"
84#include "sh_error.h"
85#include "sh_tools.h"
86#include "sh_utils.h"
87#include "sh_tiger.h"
88#define SH_NEED_GETHOSTBYXXX
89#include "sh_static.h"
90
91#undef FIL__
92#define FIL__ _("sh_tools.c")
93
94#ifdef SH_ENCRYPT
95#include "rijndael-api-fst.h"
96char * errorExplain (int err_num)
97{
98 if (err_num == BAD_KEY_DIR)
99 return (_("Key direction is invalid"));
100 else if (err_num == BAD_KEY_MAT)
101 return (_("Key material not of correct length"));
102 else if (err_num == BAD_KEY_INSTANCE)
103 return (_("Key passed is not valid"));
104 else if (err_num == BAD_CIPHER_MODE)
105 return (_("Params struct passed to cipherInit invalid"));
106 else if (err_num == BAD_CIPHER_STATE)
107 return (_("Cipher in wrong state"));
108 else if (err_num == BAD_BLOCK_LENGTH)
109 return (_("Bad block length"));
110 else if (err_num == BAD_CIPHER_INSTANCE)
111 return (_("Bad cipher instance"));
112 else if (err_num == BAD_DATA)
113 return (_("Data contents are invalid"));
114 else
115 return (_("Unknown error"));
116}
117
118#endif
119
120/* --- recode all \blah escapes to '=XX' format, and also code all
121 * remaining unprintable chars ---
122 */
123#define SH_PUT_4(p, a, b, c) (p)[0] = (a); (p)[1] = (b); (p)[2] = (c);
124
125char * sh_tools_safe_name (const char * instr, int flag)
126{
127 unsigned char c;
128 const char * p;
129 char *q;
130 char tmp[4];
131 char * outstr;
132 int len = 1;
133 int i = 0;
134 unsigned char val_octal = '\0';
135
136 SL_ENTER(_("sh_tools_safe_name"));
137
138 if (instr)
139 len = (3 * strlen(instr)) + 4;
140
141 outstr = SH_ALLOC(len);
142
143 outstr[0] = '\0';
144 tmp[3] = '\0';
145
146 p = instr;
147 q = outstr;
148
149#if !defined(SH_USE_XML)
150 (void) flag; /* fix compiler warning */
151#endif
152
153 if (!p)
154 goto end;
155
156 while (*p)
157 {
158 c = *p;
159
160 if (*p == '\n')
161 {
162 outstr[i] = ' '; ++i; ++p;
163 continue;
164 }
165
166#ifdef SH_USE_XML
167 if (flag == 1)
168 {
169 if ((*p) == '"')
170 {
171 SH_PUT_4(&outstr[i], '=', '2', '2');
172 i+=3; ++p;
173 continue;
174 }
175 else if ((*p) == '&')
176 {
177 SH_PUT_4(&outstr[i], '=', '2', '6');
178 i+=3; ++p;
179 continue;
180 }
181 else if ((*p) == '<')
182 { /* left angle */
183 SH_PUT_4(&outstr[i], '=', '3', 'c');
184 i+=3; ++p;
185 continue;
186 }
187 else if ((*p) == '>')
188 { /* right angle */
189 SH_PUT_4(&outstr[i], '=', '3', 'e');
190 i+=3; ++p;
191 continue;
192 }
193 }
194#endif
195
196 if ( (*p) != '\\' && (*p) != '&' && (*p) != '=' && (*p) != '\'')
197 {
198 outstr[i] = *p; ++i;
199 ++p;
200
201 if (c < 31 || c > 126)
202 {
203 --i;
204 sprintf(&outstr[i], "=%02x", c); /* known to fit */
205 }
206
207 continue;
208 }
209 else if ((*p) == '\'')
210 {
211 SH_PUT_4(&outstr[i], '=', '2', '7');
212 i+=3; ++p;
213 }
214 else if (*p == '=')
215 {
216 if (p[1] != '"' && p[1] != '<')
217 {
218 SH_PUT_4(&outstr[i], '=', '3', 'd');
219 i+=3; ++p;
220 }
221 else
222 { outstr[i] = *p; ++i; ++p; }
223 }
224 else if (*p == '\\')
225 {
226 ++p;
227 if (!p)
228 break;
229 if (!(*p))
230 break;
231
232 c = *p;
233
234 switch (*p) {
235 case '\\':
236 SH_PUT_4(&outstr[i], '=', '5', 'c');
237 i+=3; ++p;
238 break;
239 case 'n':
240 SH_PUT_4(&outstr[i], '=', '0', 'a');
241 i+=3; ++p;
242 break;
243 case 'b':
244 SH_PUT_4(&outstr[i], '=', '0', '8');
245 i+=3; ++p;
246 break;
247 case 'r':
248 SH_PUT_4(&outstr[i], '=', '0', 'd');
249 i+=3; ++p;
250 break;
251 case 't':
252 SH_PUT_4(&outstr[i], '=', '0', '9');
253 i+=3; ++p;
254 break;
255 case 'v':
256 SH_PUT_4(&outstr[i], '=', '0', 'b');
257 i+=3; ++p;
258 break;
259 case 'f':
260 SH_PUT_4(&outstr[i], '=', '0', 'c');
261 i+=3; ++p;
262 break;
263 case '\'':
264 SH_PUT_4(&outstr[i], '=', '2', '7');
265 i+=3; ++p;
266 break;
267 case '"': /* also encode quoted '"' */
268 SH_PUT_4(&outstr[i], '=', '2', '2');
269 i+=3; ++p;
270 break;
271 case ' ':
272 SH_PUT_4(&outstr[i], '=', '2', '0');
273 i+=3; ++p;
274 break;
275 default:
276 if (strlen(p) < 3)
277 {
278 p += strlen(p);
279 }
280 else
281 {
282 tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2];
283 val_octal = (unsigned char) strtoul(tmp, (char **)NULL, 8);
284 if (val_octal != '\0') {
285 c = val_octal;
286 sprintf(&outstr[i], "=%02x", c); /* known to fit */
287 i+=3;
288 }
289 p += 3;
290 }
291 }
292 }
293 else if (*p == '&')
294 {
295 ++p;
296 if (!p || !(*p))
297 break;
298
299 if (p[0] == 'a' && p[1] == 'm' && p[2] == 'p' && p[3] == ';')
300 {
301 SH_PUT_4(&outstr[i], '=', '2', '6');
302 i+=3; p += 4;
303 }
304 else if (p[0] == 'q' && p[1] == 'u' && p[2] == 'o' && p[3] == 't' &&
305 p[4] == ';')
306 {
307 SH_PUT_4(&outstr[i], '=', '2', '2');
308 i+=3; p += 5;
309 }
310 else if (p[0] == 'l' && p[1] == 't' && p[2] == ';')
311 {
312 SH_PUT_4(&outstr[i], '=', '3', 'c');
313 i+=3; p += 3;
314 }
315 else if (p[0] == 'g' && p[1] == 't' && p[2] == ';')
316 {
317 SH_PUT_4(&outstr[i], '=', '3', 'e');
318 i+=3; p += 3;
319 }
320 else /* conserve the '&' */
321 {
322 outstr[i] = '&'; ++i;
323 }
324 }
325 else
326 {
327 outstr[i] = *p; ++i;
328 ++p;
329 }
330 } /* while (p && *p) */
331
332 end:
333
334 outstr[i] = '\0';
335 SL_RETURN( outstr, _("sh_tools_safe_name"));
336}
337
338
339/* extern int h_errno; */
340
341char * sh_tools_errmessage (int tellme)
342{
343
344#ifdef HOST_NOT_FOUND
345 if (tellme == HOST_NOT_FOUND)
346 return _("The specified host is unknown: ");
347#endif
348#ifdef NO_ADDRESS
349 if (tellme == NO_ADDRESS)
350 return _("The requested name is valid but does not have an IP address: ");
351#endif
352#ifdef NO_RECOVERY
353 if (tellme == NO_RECOVERY)
354 return _("A non-recoverable name server error occurred: ");
355#endif
356#ifdef TRY_AGAIN
357 if (tellme == TRY_AGAIN)
358 return _("A temporary error occurred on an authoritative name server. The specified host is unknown: ");
359#endif
360 return _("Unknown error");
361}
362
363int is_numeric (const char * address)
364{
365 int j;
366 int len = sl_strlen(address);
367
368 for (j = 0; j < len; ++j)
369 if ( (address[j] < '0' || address[j] > '9') && address[j] != '.')
370 return (1 == 0);
371 return (1 == 1);
372}
373
374#if defined (SH_WITH_SERVER)
375
376int get_open_max ()
377{
378 int value;
379
380#ifdef _SC_OPEN_MAX
381 value = sysconf (_SC_OPEN_MAX);
382#else
383#ifdef OPEN_MAX
384 value = OPEN_MAX;
385#else
386 value = _POSIX_OPEN_MAX;
387#endif
388#endif
389
390 if (value < 0)
391 value = 8; /* POSIX lower limit */
392
393 if (value > 4096)
394 value = 4096;
395
396 return value;
397}
398
399#endif
400
401typedef struct _sin_cache {
402 char * address;
403 struct sockaddr_in sin;
404 struct _sin_cache * next;
405} sin_cache;
406
407static sin_cache * conn_cache = NULL;
408static int cached_addr = 0;
409
410void delete_cache()
411{
412 sin_cache * check_cache = conn_cache;
413 sin_cache * old_entry = conn_cache;
414
415 SL_ENTER(_("delete_cache"));
416
417 while (check_cache != NULL)
418 {
419 old_entry = check_cache;
420 check_cache = check_cache->next;
421 SH_FREE(old_entry->address);
422 SH_FREE(old_entry);
423 }
424
425 cached_addr = 0;
426
427 conn_cache = NULL;
428 SL_RET0(_("delete_cache"));
429}
430
431int DoReverseLookup = S_TRUE;
432
433int set_reverse_lookup (char * c)
434{
435 return sh_util_flagval(c, &DoReverseLookup);
436}
437
438int connect_port (char * address, int port,
439 char * ecall, int * errnum, char * errmsg, int errsiz)
440{
441 struct in_addr haddr; /* host address from numeric */
442 /* host details returned by the DNS */
443 struct hostent *host_entry = NULL;
444 struct sockaddr_in sinr; /* socket to the remote host */
445
446 char * host_name;
447
448 int fd = (-1);
449 int status;
450 int fail = 0;
451 int cached = 0;
452
453 int retval;
454
455 sin_cache * check_cache = conn_cache;
456
457 SL_ENTER(_("connect_port"));
458
459 /* paranoia -- should not happen
460 */
461 if (cached_addr > 128)
462 delete_cache();
463
464 if (check_cache != NULL)
465 {
466 while (check_cache && check_cache->address)
467 {
468 if ( 0 == sl_strncmp(check_cache->address,
469 address, sl_strlen(address)))
470 {
471 memcpy (&sinr, &(check_cache->sin), sizeof(struct sockaddr_in));
472 sinr.sin_family = AF_INET;
473 sinr.sin_port = htons (port);
474 cached = 1;
475 break;
476 }
477 if (check_cache->next)
478 check_cache = check_cache->next;
479 else
480 check_cache = NULL;
481 }
482 }
483
484 /* only use gethostbyname() if neccessary
485 */
486 if (cached == 0)
487 {
488#ifdef HAVE_INET_ATON
489 if (0 == inet_aton(address, &haddr))
490#else
491 if ((unsigned long)-1 == (haddr.s_addr = inet_addr(address)))
492#endif
493 {
494
495 host_entry = sh_gethostbyname(address);
496
497 if (host_entry == NULL || host_entry->h_addr == NULL)
498 {
499 sl_strlcpy(ecall, _("gethostbyname"), SH_MINIBUF);
500#ifndef NO_H_ERRNO
501 *errnum = h_errno;
502#else
503 *errnum = 666;
504#endif
505 sl_strlcpy(errmsg, sh_tools_errmessage (*errnum), errsiz);
506 sl_strlcat(errmsg, address, errsiz);
507 fail = (-1);
508 }
509 else
510 {
511 sinr.sin_family = AF_INET;
512 sinr.sin_port = htons (port);
513 sinr.sin_addr = *(struct in_addr *) host_entry->h_addr;
514
515
516 /* reverse DNS lookup
517 */
518 if (DoReverseLookup == S_TRUE)
519 {
520 if (host_entry->h_name == NULL)
521 {
522 host_name = SH_ALLOC(1);
523 host_name[0] = '\0';
524 }
525 else
526 {
527 host_name = SH_ALLOC(sl_strlen(host_entry->h_name) + 1);
528 if (sl_strlen(host_entry->h_name) > 0)
529 strcpy(host_name, /* known to fit */
530 host_entry->h_name);
531 else
532 host_name[0] = '\0';
533 }
534
535 host_entry = sh_gethostbyaddr ((char *) &sinr.sin_addr,
536 sizeof(struct in_addr),
537 AF_INET);
538 if (host_entry == NULL || host_entry->h_name == NULL)
539 {
540 sl_strlcpy(ecall, _("gethostbyaddr"), SH_MINIBUF);
541#ifndef NO_H_ERRNO
542 *errnum = h_errno;
543#else
544 *errnum = 666;
545#endif
546 sl_strlcpy(errmsg,
547 sh_tools_errmessage (*errnum), errsiz);
548 sl_strlcat(errmsg,
549 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
550 errsiz);
551 fail = (-1);
552 }
553 else
554 {
555 *errnum = 0;
556 if (sl_strlen(host_entry->h_name) == 0 ||
557 (*errnum = sl_strcmp(host_name,host_entry->h_name)) != 0)
558 {
559 if (*errnum)
560 sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
561 else
562 sl_strlcpy(ecall, _("strlen"), SH_MINIBUF);
563 sl_strlcpy(errmsg, _("Reverse lookup failed."),
564 errsiz);
565 sl_strlcat(errmsg, address, errsiz);
566 sl_strlcat(errmsg, _(" vs "), errsiz);
567 sl_strlcat(errmsg,
568 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
569 errsiz);
570 fail = -1;
571 }
572 }
573
574 SH_FREE(host_name);
575 }
576 }
577 }
578
579 else /* address was numeric */
580 {
581 sinr.sin_family = AF_INET;
582 sinr.sin_port = htons (port);
583 sinr.sin_addr = haddr;
584 }
585
586
587 if (fail != -1)
588 {
589 /* put it into the cache
590 */
591 check_cache = SH_ALLOC(sizeof(sin_cache));
592 check_cache->address = SH_ALLOC(sl_strlen(address) + 1);
593 sl_strlcpy (check_cache->address, address, sl_strlen(address) + 1);
594 memcpy(&(check_cache->sin), &sinr, sizeof(struct sockaddr_in));
595 ++cached_addr;
596
597 if (conn_cache)
598 {
599 if (conn_cache->next)
600 check_cache->next = conn_cache->next;
601 else
602 check_cache->next = NULL;
603 conn_cache->next = check_cache;
604 }
605 else
606 {
607 check_cache->next = NULL;
608 conn_cache = check_cache;
609 }
610 }
611 }
612
613
614 if (fail != (-1))
615 {
616 fd = socket(AF_INET, SOCK_STREAM, 0);
617 if (fd < 0) {
618 fail = (-1);
619 status = errno;
620 sl_strlcpy(ecall, _("socket"), SH_MINIBUF);
621 *errnum = status;
622 sl_strlcpy(errmsg, sh_error_message (status), errsiz);
623 sl_strlcat(errmsg, _(", address "), errsiz);
624 sl_strlcat(errmsg, address, errsiz);
625 }
626 }
627
628 if (fail != (-1)) {
629
630 if ( retry_connect(FIL__, __LINE__, fd,
631 (struct sockaddr *) &sinr, sizeof(sinr)) < 0)
632 {
633 status = errno;
634 sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
635 *errnum = status;
636 sl_strlcpy(errmsg, sh_error_message (status), errsiz);
637 sl_strlcat(errmsg, _(", address "), errsiz);
638 sl_strlcat(errmsg, address, errsiz);
639 close(fd);
640 fail = (-1);
641 }
642 }
643
644 retval = (fail < 0) ? (-1) : fd;
645 SL_RETURN(retval, _("connect_port"));
646}
647
648int connect_port_2 (char * address1, char * address2, int port,
649 char * ecall, int * errnum, char * errmsg, int errsiz)
650{
651 int retval = (-1);
652
653 SL_ENTER(_("connect_port_2"));
654
655 errmsg[0] = '\0';
656 *errnum = 0;
657
658 if (address1 != NULL && address1[0] != '\0')
659 retval = connect_port (address1, port,
660 ecall, errnum,
661 errmsg, errsiz);
662
663 if (retval < 0 && address2 != NULL && address2[0] != '\0')
664 {
665 /* can't use sh_error_handle here, as this would cause an infinite
666 * loop if called from sh_unix_time
667 */
668 TPT(( 0, FIL__, __LINE__, _("msg=<Using alternative server %s.>\n"),
669 address2));
670 retval = connect_port (address2, port,
671 ecall, errnum,
672 errmsg, errsiz);
673 }
674
675 if ((retval < 0) &&
676 (address1 == NULL || address1[0] == '\0') &&
677 (address1 == NULL || address1[0] == '\0'))
678 {
679 sl_strlcpy(ecall, _("connect_port_2"), SH_MINIBUF);
680 sl_strlcpy(errmsg, _("No server address known"), errsiz);
681 }
682 SL_RETURN(retval, _("connect_port_2"));
683 /* return retval; */
684}
685
686#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT)
687static
688int sh_write_select(int type, int sockfd,
689 char *buf, int nbytes,
690 int * w_error, int timeout)
691{
692 int countbytes, count;
693 fd_set fds;
694 struct timeval tv;
695 int select_now;
696 int num_sel;
697
698 struct sigaction new_act;
699 struct sigaction old_act;
700
701 SL_ENTER(_("sh_write_select"));
702
703 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
704 */
705 new_act.sa_handler = SIG_IGN;
706 sigaction (SIGPIPE, &new_act, &old_act);
707
708 FD_ZERO(&fds);
709 FD_SET(sockfd, &fds);
710
711 countbytes = 0;
712 tv.tv_sec = 1;
713 tv.tv_usec = 0;
714 select_now = 0;
715
716 *w_error = 0;
717
718 while ( countbytes < nbytes ) {
719
720 FD_ZERO(&fds);
721 FD_SET(sockfd, &fds);
722
723 if (type == SH_DO_WRITE)
724 {
725 if ( (num_sel = select (sockfd+1, NULL, &fds, NULL, &tv)) == -1)
726 {
727 if (sig_raised == 1)
728 {
729 sig_raised = 2;
730 continue;
731 }
732 if ( errno == EINTR) /* try again */
733 continue;
734 *w_error = errno;
735 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"),
736 sh_error_message(*w_error)));
737 sigaction (SIGPIPE, &old_act, NULL);
738 SL_RETURN( countbytes, _("sh_write_select"));
739 }
740 }
741 else
742 {
743 if ( (num_sel = select (sockfd+1, &fds, NULL, NULL, &tv)) == -1)
744 {
745 if (sig_raised == 1)
746 {
747 sig_raised = 2;
748 continue;
749 }
750 if ( errno == EINTR ) /* try again */
751 continue;
752 *w_error = errno;
753 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"),
754 sh_error_message(*w_error)));
755 sigaction (SIGPIPE, &old_act, NULL);
756 SL_RETURN( countbytes, _("sh_write_select"));
757 }
758 }
759
760 /* on Linux, timeout is modified to reflect the amount of
761 * time not slept
762 */
763 tv.tv_sec = 1;
764 tv.tv_usec = 0;
765
766
767 /* let's not hang on forever
768 */
769 if (num_sel == 0)
770 {
771 ++select_now; /* timeout */
772 if ( select_now > timeout ) /* 5 minutes */
773 {
774#ifdef ETIMEDOUT
775 *w_error = ETIMEDOUT;
776#else
777 *w_error = 0;
778#endif
779 sigaction (SIGPIPE, &old_act, NULL);
780 TPT(( 0, FIL__, __LINE__, _("msg=<Timeout>\n")));
781 SL_RETURN( countbytes, _("sh_write_select"));
782 }
783 }
784
785 if ( FD_ISSET (sockfd, &fds) )
786 {
787 if (type == SH_DO_WRITE)
788 count = write (sockfd, buf, nbytes-countbytes);
789 else
790 count = read (sockfd, buf, nbytes-countbytes);
791
792 if (count > 0)
793 {
794 countbytes += count;
795 buf += count; /* move buffer pointer forward */
796 if (countbytes < nbytes) FD_SET( sockfd, &fds );
797 }
798 else if (count < 0 && errno == EINTR)
799 {
800 FD_SET( sockfd, &fds );
801 }
802 else if (count < 0)
803 {
804 *w_error = errno;
805 sigaction (SIGPIPE, &old_act, NULL);
806 TPT(( 0, FIL__, __LINE__, _("msg=<count < 0>\n")));
807 SL_RETURN( countbytes, _("sh_write_select"));
808 }
809 else /* count == 0 */
810 {
811 *w_error = errno;
812 sigaction (SIGPIPE, &old_act, NULL);
813 TPT(( 0, FIL__, __LINE__, _("msg=<count == 0>\n")));
814 SL_RETURN( countbytes, _("sh_write_select"));
815 }
816 }
817 }
818
819
820 /* restore signal handler
821 */
822 sigaction (SIGPIPE, &old_act, NULL);
823
824 *w_error = 0;
825
826 TPT(( 0, FIL__, __LINE__, _("msg=<count = %d>\n"), countbytes));
827 SL_RETURN( countbytes, _("sh_write_select"));
828}
829#endif
830
831#if defined (SH_WITH_CLIENT)
832unsigned long write_port (int sockfd, char *buf, unsigned long nbytes,
833 int * w_error, int timeout)
834{
835 unsigned long bytes;
836 char errmsg[256];
837
838 SL_ENTER(_("write_port"));
839
840 bytes = sh_write_select(SH_DO_WRITE, sockfd, buf, nbytes, w_error, timeout);
841 if (*w_error != 0)
842 {
843 sl_strlcpy(errmsg, sh_error_message (*w_error), sizeof(errmsg));
844 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
845 errmsg, (long) sockfd, _("write_port"));
846 }
847 SL_RETURN( bytes, _("write_port"));
848}
849#endif
850
851#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT)
852
853unsigned long read_port (int sockfd, char *buf, unsigned long nbytes,
854 int * w_error, int timeout)
855{
856 unsigned long bytes;
857 char errmsg[256];
858
859 SL_ENTER(_("read_port"));
860
861 bytes = sh_write_select(SH_DO_READ, sockfd, buf, nbytes, w_error, timeout);
862 if (*w_error != 0)
863 {
864 sl_strlcpy(errmsg, sh_error_message (*w_error), sizeof(errmsg));
865 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
866 errmsg, (long) sockfd, _("read_port"));
867 }
868 SL_RETURN( bytes, _("read_port"));
869}
870#endif
871
872#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
873
874int check_request_nerr (char * have, char * need)
875{
876 SL_ENTER(_("check_request_nerr"));
877 ASSERT_RET((have != NULL && need != NULL),
878 _("have != NULL && need != NULL"), (-1))
879
880 if ( (have[0] == need[0]) && (have[1] == need[1]) &&
881 (have[2] == need[2]) && (have[3] == need[3]))
882 SL_RETURN(0, _("check_request_nerr"));
883 SL_RETURN((-1), _("check_request_nerr"));
884}
885#endif
886
887#if defined (SH_WITH_CLIENT)
888
889int check_request (char * have, char * need)
890{
891 char first[21], second[5];
892 int i;
893
894 SL_ENTER(_("check_request"));
895 i = check_request_nerr (have, need);
896
897 if (i == 0)
898 SL_RETURN(0, _("check_request"));
899
900 for (i = 0; i < 4; ++i)
901 {
902 second[i] = need[i];
903 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
904 '\\', (unsigned char) have[i]);
905 }
906
907 first[20] = '\0'; second[4] = '\0';
908
909 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST,
910 second, first);
911 SL_RETURN((-1), _("check_request"));
912}
913#endif
914
915#if defined (SH_WITH_SERVER)
916
917int check_request_s (char * have, char * need, char * clt)
918{
919 char first[21], second[5];
920 int i;
921
922 SL_ENTER(_("check_request_s"));
923 i = check_request_nerr (have, need);
924
925 if (i == 0)
926 SL_RETURN( (0), _("check_request_s"));
927
928 for (i = 0; i < 4; ++i)
929 {
930 second[i] = need[i];
931 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
932 '\\', (unsigned char) have[i]);
933 }
934 first[20] = '\0'; second[4] = '\0';
935 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST1,
936 second, first, clt);
937 SL_RETURN( (-1), _("check_request_s"));
938}
939#endif
940
941#if defined (SH_WITH_CLIENT)
942
943void get_header (unsigned char * head, unsigned long * bytes, char * u)
944{
945 SL_ENTER(_("get_header"));
946
947 *bytes =
948 (256 * (unsigned int)head[1] + (unsigned int)head[2]);
949
950 if (u != NULL)
951 {
952 u[0] = head[3];
953 u[1] = head[4];
954 u[2] = head[5];
955 u[3] = head[6];
956 u[4] = '\0';
957 }
958
959 SL_RET0(_("get_header"));
960}
961#endif
962
963#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
964
965#ifdef SH_ENCRYPT_2
966#define TRANS_BYTES 65120
967#else
968#define TRANS_BYTES 65280
969#endif
970
971void put_header (unsigned char * head, int protocol,
972 unsigned long * length, char * u)
973{
974
975 /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
976 static unsigned long transfer_limit = TRANS_BYTES + 6 + KEY_LEN;
977
978 SL_ENTER(_("put_header"));
979
980 head[0] = protocol;
981
982 ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
983
984 if (*length > transfer_limit)
985 *length = transfer_limit;
986
987 head[1] = (unsigned int)(*length/256);
988 head[2] = (unsigned int)(*length-256 * head[1]);
989 if (u == NULL)
990 {
991 head[3] = 0x01;
992 head[4] = 0x01;
993 head[5] = 0x01;
994 head[6] = 0x01;
995 }
996 else
997 {
998 head[3] = u[0];
999 head[4] = u[1];
1000 head[5] = u[2];
1001 head[6] = u[3];
1002 }
1003
1004 SL_RET0(_("put_header"));
1005}
1006#endif
1007
1008/* ------------------------------------------
1009 *
1010 * version 2 client/server protocol
1011 *
1012 * ------------------------------------------
1013 *
1014 * header : flag size[2]
1015 *
1016 * payload: random_pad[8] protocol[4] size[4] payload[payload_size] padding
1017 *
1018 * full_size <= 8192; payload_size <= 8176 (511*16); msg_size <= 8128 (508*16)
1019 * (msg_size = payload_size - key_len = payload_size - 48)
1020 */
1021#ifdef SH_WITH_SERVER
1022#define SH_V2_FULLSIZE 240
1023#define SH_V2_PAYLOAD 224
1024#define SH_V2_MESSAGE 176
1025#else
1026#define SH_V2_FULLSIZE 1024
1027#define SH_V2_PAYLOAD 1008
1028#define SH_V2_MESSAGE 960
1029#endif
1030
1031#ifdef SH_ENCRYPT
1032#include "rijndael-api-fst.h"
1033#endif
1034
1035void sh_tools_show_header (unsigned char * head, char sign)
1036{
1037#define SH_IS_ASCII(c) (((c) & ~0x7f) == 0)
1038
1039
1040 int msg_size = (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1041 char code[32];
1042 char * p = &code[0];
1043
1044 memset (code, ' ', 32); /* space */
1045
1046 if ((head[0] & SH_PROTO_SRP) != 0) { p[0]='S';p[1]='R';p[2]='P';}
1047 p += 4;
1048 if ((head[0] & SH_PROTO_MSG) != 0) { p[0]='M';p[1]='S';p[2]='G';}
1049 p += 4;
1050 if ((head[0] & SH_PROTO_BIG) != 0) { p[0]='B';p[1]='I';p[2]='G';}
1051 p += 4;
1052 if ((head[0] & SH_PROTO_END) != 0) { p[0]='E';p[1]='N';p[2]='D';}
1053 p += 4;
1054 if ((head[0] & SH_PROTO_ENC) != 0) { p[0]='E';p[1]='N';p[2]='C';}
1055 p += 4;
1056 if ((head[0] & SH_PROTO_EN2) != 0) { p[0]='E';p[1]='N';p[2]='2';}
1057 code[23] = '\0';
1058
1059 if (SH_IS_ASCII(head[3]) && isalpha(head[3]) &&
1060 SH_IS_ASCII(head[4]) && isalpha(head[4]) &&
1061 SH_IS_ASCII(head[5]) && isalpha(head[5]) &&
1062 SH_IS_ASCII(head[6]) && isalpha(head[6])) {
1063 fprintf(stderr, "%c %3o %s %5d %c %c %c %c\n", sign,
1064 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1065 } else {
1066 fprintf(stderr, "%c %3o %s %5d %2X %2X %2X %2X\n", sign,
1067 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1068 }
1069 return;
1070}
1071
1072#ifdef SH_ENCRYPT
1073/*
1074 * #define DEBUG_EN2
1075 *
1076 * ingest version 1 7-byte header and payload, return version2 header/payload
1077 * last 4 bytes of outgoing header are set to dummy value
1078 */
1079char * sh_tools_makePack (unsigned char * header,
1080 char * payload, int payload_size,
1081 keyInstance * keyInstE)
1082{
1083 UINT32 rpad[3];
1084 unsigned char head[16];
1085 double epad;
1086 int i_epad = 0;
1087 int i_blk = payload_size / 16;
1088 int i_blkmax = SH_V2_FULLSIZE / 16;
1089 int pads = 0;
1090 int full_size;
1091 char * full_ret;
1092
1093 char * p;
1094 RIJ_BYTE inBlock[B_SIZ];
1095 RIJ_BYTE outBlock[B_SIZ];
1096 int j;
1097 cipherInstance cipherInst;
1098 int err_num;
1099 int blkfac;
1100
1101 /*
1102 SL_REQUIRE (i_blk*16 == payload_size, _("payload_size % 16 != 0"));
1103 */
1104 if ((i_blk * 16) != payload_size) ++i_blk;
1105#ifdef DEBUG_EN2
1106 fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
1107#endif
1108 /* random_pad
1109 */
1110 rpad[1] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1111 memcpy (head, &rpad[1], 4);
1112 rpad[0] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1113 memcpy (&head[4], &rpad[0], 4);
1114 rpad[2] = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1115 memcpy (&head[8], &rpad[2], 4);
1116
1117 /* protocol
1118 */
1119 /* memcpy (&head[8], &header[3], 4); */
1120
1121 /* size (payload)
1122 */
1123 head[12] = header[1];
1124 head[13] = header[2];
1125 head[14] = '\0';
1126 head[15] = '\0';
1127
1128 if (i_blk < i_blkmax)
1129 {
1130 pads = i_blkmax - i_blk;
1131 /* memcpy((char *) &rpad[2], &head[12], 4); */
1132 epad = taus_get_double (&rpad);
1133#ifdef DEBUG_EN2
1134 fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
1135#endif
1136 i_epad = (int) (pads * epad);
1137#ifdef DEBUG_EN2
1138 fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
1139#endif
1140 }
1141
1142 full_size =
1143 /* head */ 16 +
1144 /* payload */ (i_blk*16) + /* payload_size + */
1145 /* pad */ (i_epad * 16);
1146
1147 full_ret = SH_ALLOC(full_size);
1148 memcpy(full_ret, head, 16);
1149 if (payload != NULL)
1150 {
1151 memcpy(&full_ret[16], payload, payload_size);
1152 }
1153 if ((i_blk*16) > payload_size)
1154 {
1155#ifdef DEBUG_EN2
1156 fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
1157#endif
1158 memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
1159 payload_size = i_blk * 16;
1160 }
1161 memset(&full_ret[16+payload_size], '\0', i_epad*16);
1162#ifdef DEBUG_EN2
1163 fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
1164#endif
1165
1166 /* rewrite header
1167 */
1168 header[1] = (unsigned int)(full_size/256);
1169 header[2] = (unsigned int)(full_size - (256 * header[1]));
1170 /* don't erase protocol from header
1171 memset(&header[3], '\0', 4);
1172 */
1173 p = full_ret; blkfac = full_size / 16;
1174
1175 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1176
1177 if (err_num < 0)
1178 {
1179 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1180 errorExplain(err_num),
1181 _("sh_tools_makePack: cipherInit"));
1182 }
1183 for (j = 0; j < blkfac; ++j)
1184 {
1185 memcpy(inBlock, p, B_SIZ);
1186 err_num = blockEncrypt(&cipherInst, keyInstE,
1187 inBlock, 128 * BNUM, outBlock);
1188 if (err_num < 0)
1189 {
1190 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1191 errorExplain(err_num),
1192 _("sh_tools_makePack: blockEncrypt"));
1193 }
1194 memcpy(p, outBlock, B_SIZ);
1195 p += B_SIZ;
1196 }
1197
1198 return full_ret;
1199}
1200
1201/* write a 7-byte header and return payload as expected by version 1
1202 * last 4 bytes of incoming header are dummy
1203 */
1204char * sh_tools_revertPack (unsigned char * header, char * message,
1205 keyInstance * keyInstD,
1206 unsigned long message_size)
1207{
1208 unsigned long msg_size;
1209 char * msg_ret;
1210
1211 char * p;
1212 RIJ_BYTE inBlock[B_SIZ];
1213 RIJ_BYTE outBlock[B_SIZ];
1214 int j;
1215 cipherInstance cipherInst;
1216 int err_num;
1217 int blkfac;
1218
1219 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1220#ifdef DEBUG_EN2
1221 fprintf(stderr, "RECV <%lu>\n", msg_size);
1222#endif
1223 if (msg_size > message_size) {
1224 msg_size = message_size;
1225#ifdef DEBUG_EN2
1226 fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
1227#endif
1228 }
1229
1230 p = message; blkfac = msg_size / 16;
1231
1232 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1233
1234 if (err_num < 0)
1235 {
1236 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1237 errorExplain(err_num),
1238 _("sh_tools_revertPack: cipherInit"));
1239 }
1240 for (j = 0; j < blkfac; ++j)
1241 {
1242 memcpy(inBlock, p, B_SIZ);
1243 err_num = blockDecrypt(&cipherInst, keyInstD,
1244 inBlock, 128 * BNUM, outBlock);
1245 if (err_num < 0)
1246 {
1247 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1248 errorExplain(err_num),
1249 _("sh_tools_revertPack: blockDecrypt"));
1250 }
1251 memcpy(p, outBlock, B_SIZ);
1252 p += B_SIZ;
1253 }
1254
1255 /* rewrite size in header
1256 */
1257 header[1] = message[12];
1258 header[2] = message[13];
1259 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1260
1261 if (msg_size > (message_size-16))
1262 {
1263 msg_size = message_size-16;
1264 header[1] = (unsigned int)(msg_size/256);
1265 header[2] = (unsigned int)(msg_size - (256 * header[1]));
1266#ifdef DEBUG_EN2
1267 fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
1268#endif
1269 }
1270#ifdef DEBUG_EN2
1271 fprintf(stderr, "REC2 <%lu>\n", msg_size);
1272#endif
1273 /* protocol
1274 */
1275 /* memcpy(&header[3], &message[8], 4); */
1276
1277 /* payload
1278 */
1279 msg_ret = SH_ALLOC(msg_size+1);
1280 if (msg_size > 0)
1281 {
1282 memcpy(msg_ret, &message[16], msg_size);
1283 }
1284 msg_ret[msg_size] = '\0';
1285#ifdef DEBUG_EN2
1286 fprintf(stderr, "REC3 <%lu>\n", msg_size);
1287#endif
1288 SH_FREE(message);
1289
1290 return msg_ret;
1291}
1292#endif
1293
1294int sh_tools_hash_add(char * key, char * buf, int buflen)
1295{
1296 char * theSig;
1297
1298 SL_ENTER(_("sh_tools_hash_add"));
1299
1300 theSig = sh_util_siggen (key, buf, buflen);
1301 sl_strlcat(buf, theSig, buflen + KEY_LEN + 1);
1302
1303 SL_RETURN((0), _("sh_tools_hash_add"));
1304}
1305
1306
1307/* return 0 (== FALSE) if no match, else 1 (== TRUE)
1308 */
1309int sh_tools_hash_vfy(char * key, char * buf, int buflen)
1310{
1311 char hash[KEY_LEN+1];
1312 register int i;
1313 char * theSig;
1314
1315 SL_ENTER(_("sh_tools_hash_vfy"));
1316
1317 theSig = sh_util_siggen (key, buf, buflen);
1318 sl_strlcpy(hash, theSig, KEY_LEN+1);
1319
1320 for (i = 0; i < KEY_LEN; ++i)
1321 {
1322 if (buf[buflen + i] != hash[i])
1323 SL_RETURN((0), _("sh_tools_hash_vfy"));
1324 }
1325
1326 SL_RETURN((1), _("sh_tools_hash_vfy"));
1327}
1328
1329/* ------------------------------------------ */
1330
1331#if defined (SH_WITH_SERVER)
1332
1333/* add a checksum to a buffer; put checksum in front
1334 */
1335char * hash_me (char * key, char * buf, int buflen)
1336{
1337 char hash[KEY_LEN+1];
1338 char * temp;
1339 register int i;
1340 int total = 0;
1341 char * theSig;
1342
1343
1344 SL_ENTER(_("hash_me"));
1345
1346#ifdef DEBUG_EN2
1347 fprintf(stderr, "hash_me <%s> <%d>\n",
1348 (key == NULL) ? "NULL" : key, buflen);
1349#endif
1350 /* key = H(NSRV,NCLT,SK)
1351 */
1352 ASSERT_RET((key != NULL), _("key != NULL"), (NULL));
1353 ASSERT_RET((buflen >= 0), _("buflen >= 0"), (NULL));
1354
1355 theSig = sh_util_siggen (key, buf, buflen);
1356 sl_strlcpy(hash, theSig, KEY_LEN+1);
1357
1358
1359 total = KEY_LEN + buflen;
1360 temp = SH_ALLOC (total);
1361
1362 for (i = 0; i < KEY_LEN; ++i)
1363 temp[i] = hash[i];
1364
1365 for (i = 0; i < buflen; ++i)
1366 temp[i+KEY_LEN] = buf[i];
1367
1368 SL_RETURN(temp, _("hash_me"));
1369}
1370#endif
1371
1372#if defined (SH_WITH_CLIENT)
1373
1374/* verify the checksum of a buffer; checksum comes first
1375 */
1376int hash_check(char * key,
1377 char * buf, int buflen)
1378{
1379 char hash[KEY_LEN+1];
1380 register int i;
1381 char * theSig;
1382
1383 SL_ENTER(_("hash_check"));
1384
1385#ifdef DEBUG_EN2
1386 fprintf(stderr, "hash_check <%s> <%d>\n",
1387 (key == NULL) ? "NULL" : key, buflen);
1388#endif
1389 theSig = sh_util_siggen (key, &buf[KEY_LEN], buflen-KEY_LEN);
1390 sl_strlcpy(hash, theSig, KEY_LEN+1);
1391
1392 for (i = 0; i < KEY_LEN; ++i)
1393 {
1394 if (buf[i] != hash[i])
1395 SL_RETURN((-1), _("hash_check"));
1396 }
1397 SL_RETURN((0), _("hash_check"));
1398}
1399
1400#endif
1401
1402#if defined (SH_WITH_SERVER)
1403
1404char * get_client_conf_file (char * peer, unsigned long * length)
1405{
1406 char * ret;
1407 int size, status;
1408 struct stat buf;
1409 char * base;
1410
1411 SL_ENTER(_("get_client_conf_file"));
1412
1413 size = sl_strlen(DEFAULT_DATAROOT);
1414 base = SH_ALLOC(size + 1);
1415 sl_strlcpy(base, DEFAULT_DATAROOT, size + 1);
1416
1417 size = sl_strlen(base) + sl_strlen(peer) + 5;
1418 ++size;
1419
1420 ret = SH_ALLOC(size);
1421 sl_strlcpy(ret, base, size);
1422 sl_strlcat(ret, _("/rc."), size);
1423 sl_strlcat(ret, peer, size);
1424
1425 status = retry_stat (FIL__, __LINE__, ret, &buf);
1426
1427 if (status == 0)
1428 goto lab_end;
1429 else
1430 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1431 (long) sh.effective.uid, ret);
1432
1433 sl_strlcpy(ret, base, size);
1434 sl_strlcat(ret, "/rc", size);
1435
1436 status = retry_stat (FIL__, __LINE__, ret, &buf);
1437
1438 if (status == 0)
1439 goto lab_end;
1440 else
1441 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
1442 (long) sh.effective.uid, ret);
1443
1444 SH_FREE(base);
1445 *length=0;
1446 SL_RETURN(NULL, _("get_client_conf_file"));
1447
1448 lab_end:
1449 if (buf.st_size > 0x7fffffff)
1450 {
1451 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1452 _("File too large"), _("get_client_conf_file"));
1453 SH_FREE(base);
1454 SL_RETURN(NULL, _("get_client_conf_file"));
1455 }
1456 *length = (unsigned long) buf.st_size;
1457 SH_FREE(base);
1458 SL_RETURN(ret, _("get_client_conf_file"));
1459}
1460
1461char * get_client_data_file (char * peer, unsigned long * length)
1462{
1463 char * ret;
1464 int size, status;
1465 struct stat buf;
1466
1467 char * base;
1468
1469 SL_ENTER(_("get_client_data_file"));
1470
1471 size = sl_strlen(DEFAULT_DATAROOT);
1472 base = SH_ALLOC(size + 1);
1473 sl_strlcpy(base, DEFAULT_DATAROOT, size + 1);
1474
1475 size = sl_strlen(base) + sl_strlen(peer) + 7;
1476
1477 ++size;
1478
1479 ret = SH_ALLOC(size);
1480 sl_strlcpy(ret, base, size);
1481 sl_strlcat(ret, _("/file."), size);
1482 sl_strlcat(ret, peer, size);
1483
1484 status = retry_stat (FIL__, __LINE__, ret, &buf);
1485
1486 if (status == 0)
1487 goto lab1_end;
1488 else
1489 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1490 (long) sh.effective.uid, ret);
1491
1492
1493 sl_strlcpy(ret, base, size);
1494 sl_strlcat(ret, _("/file"), size);
1495
1496 status = retry_stat (FIL__, __LINE__, ret, &buf);
1497
1498 if (status == 0)
1499 goto lab1_end;
1500 else
1501 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1502 (long) sh.effective.uid, ret);
1503
1504
1505 *length = 0;
1506 SH_FREE(base);
1507 SL_RETURN(NULL, _("get_client_data_file"));
1508
1509 lab1_end:
1510 if (buf.st_size > 0x7fffffff)
1511 {
1512 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1513 _("File too large"), _("get_client_data_file"));
1514 SH_FREE(base);
1515 SL_RETURN(NULL, _("get_client_data_file"));
1516 }
1517 *length = (unsigned long) buf.st_size;
1518 SH_FREE(base);
1519 SL_RETURN(ret, _("get_client_data_file"));
1520
1521}
1522#endif
1523
1524#if defined(SH_WITH_CLIENT) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
1525
1526/* --------- secure temporary file ------------ */
1527
1528SL_TICKET open_tmp ()
1529{
1530 SL_TICKET fd;
1531 UINT32 ticks;
1532 char * file;
1533 struct stat buf;
1534 int error;
1535 int status = BAD;
1536 char * my_tmp_dir;
1537 int len;
1538
1539 SL_ENTER(_("open_tmp"));
1540
1541#if defined(SH_TMPDIR)
1542 len = sl_strlen(SH_TMPDIR) + 1;
1543 my_tmp_dir = SH_ALLOC(len);
1544 sl_strlcpy(my_tmp_dir, SH_TMPDIR, len);
1545#else
1546#if defined(SH_WITH_SERVER)
1547 len = sl_strlen(DEFAULT_LOGDIR) + 1;
1548 my_tmp_dir = SH_ALLOC(len);
1549 sl_strlcpy(my_tmp_dir, DEFAULT_LOGDIR, len);
1550#else
1551 len = sl_strlen(sh.effective.home) + 1;
1552 my_tmp_dir = SH_ALLOC(len);
1553 sl_strlcpy(my_tmp_dir, sh.effective.home, len);
1554#endif
1555#endif
1556
1557 if (0 != tf_trust_check (my_tmp_dir, SL_YESPRIV))
1558 {
1559 dlog(1, FIL__, __LINE__,
1560 _("The directory for temporary files: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"),
1561 my_tmp_dir);
1562 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST,
1563 (long) sh.effective.uid,
1564 my_tmp_dir);
1565 SH_FREE(my_tmp_dir);
1566 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1567 }
1568
1569 do {
1570
1571 /* create random filename in effective users home directory
1572 */
1573 ticks = taus_get (&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1574 if (my_tmp_dir[0] == '/' && my_tmp_dir[1] == '\0')
1575 file = sh_util_strconcat (my_tmp_dir,
1576 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4),
1577 NULL);
1578 else
1579 file = sh_util_strconcat (my_tmp_dir,
1580 "/",
1581 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4),
1582 NULL);
1583
1584 /* check whether it already exists (paranoia)
1585 */
1586 errno = 0;
1587 status = retry_lstat(FIL__, __LINE__, file, &buf);
1588 error = errno;
1589
1590 if ( (status < 0) && (error == ENOENT) ) /* file does not exist */
1591 status = GOOD;
1592 else if (status < 0) /* unexpected error condition */
1593 {
1594 SH_FREE (file);
1595 SH_FREE(my_tmp_dir);
1596 TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
1597 SL_RETURN((-1), _("open_tmp"));
1598 }
1599 else /* file exists */
1600 {
1601 status = BAD;
1602 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file exists already>\n")));
1603 }
1604
1605 if (status == GOOD)
1606 {
1607 if (0 == tf_trust_check (file, SL_YESPRIV))
1608 status = GOOD;
1609 else
1610 {
1611 status = BAD;
1612 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file untrusted>\n")));
1613 }
1614 }
1615
1616 if (status == BAD)
1617 SH_FREE (file);
1618
1619 } while (status == BAD);
1620
1621 fd = sl_open_safe_rdwr (file, SL_YESPRIV);
1622 if (SL_ISERROR(fd))
1623 {
1624 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN,
1625 _("Error opening temporary file"), _("open_tmp"));
1626 TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"),
1627 fd, file));
1628 }
1629
1630
1631 SH_FREE (file);
1632 SH_FREE(my_tmp_dir);
1633
1634 if (!SL_ISERROR(fd)) {
1635 sl_unlink(fd);
1636 }
1637
1638 if (!SL_ISERROR(fd))
1639 SL_RETURN((fd), _("open_tmp"));
1640 else
1641 SL_RETURN((-1), _("open_tmp"));
1642}
1643
1644
1645int close_tmp (SL_TICKET fd)
1646{
1647 SL_ENTER(_("close_tmp"));
1648
1649 if (SL_ISERROR(sl_close (fd)))
1650 SL_RETURN((-1), _("close_tmp"));
1651 SL_RETURN((0), _("close_tmp"));
1652}
1653
1654int rewind_tmp (SL_TICKET fd)
1655{
1656 SL_ENTER(_("rewind_tmp"));
1657
1658 if (SL_ISERROR(sl_rewind (fd)))
1659 SL_RETURN((-1), _("rewind_tmp"));
1660 SL_RETURN((0), _("rewind_tmp"));
1661}
1662#endif
Note: See TracBrowser for help on using the repository browser.