source: trunk/src/sh_tools.c@ 470

Last change on this file since 470 was 425, checked in by katerina, 12 years ago

Fix for tickets #329, #330, #331, #332

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