source: trunk/src/sh_tools.c@ 20

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

Optimized version of tiger algorithm, and basic ingredients for unit testing (part 2)

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