source: trunk/src/sh_tools.c@ 343

Last change on this file since 343 was 313, checked in by katerina, 14 years ago

Fix for ticker #234 (spurious warnings about unsupported address family)

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