source: trunk/src/sh_tools.c@ 203

Last change on this file since 203 was 197, checked in by katerina, 16 years ago

Rewrite of code for conditionals in configuration file, supports more tests now (ticket #129).

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