source: trunk/src/sh_tools.c@ 27

Last change on this file since 27 was 27, checked in by rainer, 18 years ago

Support for server-to-server relay and more user policies

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