source: trunk/src/sh_tools.c@ 11

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

Minor optimisations for server

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