source: trunk/src/sh_tools.c@ 371

Last change on this file since 371 was 352, checked in by katerina, 13 years ago

Fix ticket #257 (error message may contain uninitialized string).

File size: 48.4 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
[352]566 if (errsiz > 0) errmsg[0] = '\0';
567
[1]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,
[313]578 address, sl_strlen(address)) )
[1]579 {
[295]580 memcpy (&sinr, &((check_cache->saddr).sin), sizeof(struct sockaddr_in));
[1]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 {
[170]603 SH_MUTEX_LOCK(mutex_resolv);
604
[143]605 host_name = NULL;
606
[1]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
[132]617 (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
[1]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 {
[34]639 host_name = sh_util_strdup(host_entry->h_name);
[1]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
[132]653 (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
[1]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 ||
[169]663 (*errnum = sl_strcasecmp(host_name,host_entry->h_name)) != 0)
[1]664 {
665 if (*errnum)
666 sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
667 else
668 sl_strlcpy(ecall, _("strlen"), SH_MINIBUF);
[161]669 sl_strlcpy(errmsg, _("Reverse lookup failed: "),
[1]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 }
[134]681 SH_MUTEX_UNLOCK(mutex_resolv);
[143]682 if (host_name) SH_FREE(host_name);
[1]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);
[295]700
701 sh_ipvx_save(&(check_cache->saddr), AF_INET, (struct sockaddr *) &sinr);
702
[1]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;
[132]730 sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
[1]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;
[132]744 sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
[1]745 sl_strlcat(errmsg, _(", address "), errsiz);
746 sl_strlcat(errmsg, address, errsiz);
[252]747 sl_close_fd(FIL__, __LINE__, fd);
[1]748 fail = (-1);
749 }
750 }
751
752 retval = (fail < 0) ? (-1) : fd;
753 SL_RETURN(retval, _("connect_port"));
754}
[295]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;
[1]767
[295]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 {
[313]782 if ( 0 == sl_strcmp(check_cache->address, address) )
[295]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);
[313]790 cached = 1;
791 break;
[295]792 case AF_INET6:
793 sin6 = &(ss.sin6);
794 sin6->sin6_port = htons (port);
[313]795 cached = 1;
796 break;
797 default:
798 break;
[295]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 }
[313]822
823
[295]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
[313]861 hints.ai_family = AF_UNSPEC;
[295]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 {
[313]932 if ( (SOCK_STREAM == p->ai_socktype) &&
933 ((p->ai_family == AF_INET) || (p->ai_family == AF_INET6)) )
[295]934 {
[313]935
936 fd = socket(p->ai_family, SOCK_STREAM, 0);
937
938 if (fd != (-1))
[295]939 {
[313]940 if (retry_connect(FIL__, __LINE__, fd,
941 p->ai_addr, p->ai_addrlen) >= 0)
[295]942 {
[313]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 }
[295]961 else
[313]962 {
963 check_cache->next = NULL;
964 conn_cache = check_cache;
965 }
966
967 freeaddrinfo (ai);
968 goto end;
[295]969 }
[313]970 status = errno;
971 sl_close_fd(FIL__, __LINE__, fd);
[295]972 }
[313]973 else
974 {
975 status = errno;
976 }
[295]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
[1]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
[27]1036#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]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 struct sigaction new_act;
1049 struct sigaction old_act;
[132]1050 char errbuf[SH_ERRBUF_SIZE];
[1]1051
1052 SL_ENTER(_("sh_write_select"));
1053
1054 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
1055 */
1056 new_act.sa_handler = SIG_IGN;
[22]1057 sigemptyset( &new_act.sa_mask ); /* set an empty mask */
1058 new_act.sa_flags = 0; /* init sa_flags */
[1]1059 sigaction (SIGPIPE, &new_act, &old_act);
1060
1061 FD_ZERO(&fds);
1062 FD_SET(sockfd, &fds);
1063
1064 countbytes = 0;
1065 tv.tv_sec = 1;
1066 tv.tv_usec = 0;
1067 select_now = 0;
1068
1069 *w_error = 0;
1070
1071 while ( countbytes < nbytes ) {
1072
1073 FD_ZERO(&fds);
1074 FD_SET(sockfd, &fds);
1075
1076 if (type == SH_DO_WRITE)
1077 {
1078 if ( (num_sel = select (sockfd+1, NULL, &fds, NULL, &tv)) == -1)
1079 {
1080 if (sig_raised == 1)
1081 {
1082 sig_raised = 2;
1083 continue;
1084 }
[171]1085 if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
[1]1086 continue;
1087 *w_error = errno;
1088 sigaction (SIGPIPE, &old_act, NULL);
[171]1089 sh_error_message(*w_error, errbuf, sizeof(errbuf));
1090 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1091 errbuf,
1092 _("sh_write_select (ws)") );
1093 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
[1]1094 SL_RETURN( countbytes, _("sh_write_select"));
1095 }
1096 }
1097 else
1098 {
1099 if ( (num_sel = select (sockfd+1, &fds, NULL, NULL, &tv)) == -1)
1100 {
1101 if (sig_raised == 1)
1102 {
1103 sig_raised = 2;
1104 continue;
1105 }
[171]1106 if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
[1]1107 continue;
1108 *w_error = errno;
1109 sigaction (SIGPIPE, &old_act, NULL);
[171]1110 sh_error_message(*w_error, errbuf, sizeof(errbuf));
1111 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1112 errbuf,
1113 _("sh_write_select (rs)") );
1114 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
[1]1115 SL_RETURN( countbytes, _("sh_write_select"));
1116 }
1117 }
1118
1119 /* on Linux, timeout is modified to reflect the amount of
1120 * time not slept
1121 */
1122 tv.tv_sec = 1;
1123 tv.tv_usec = 0;
1124
1125
1126 /* let's not hang on forever
1127 */
1128 if (num_sel == 0)
1129 {
1130 ++select_now; /* timeout */
1131 if ( select_now > timeout ) /* 5 minutes */
1132 {
1133#ifdef ETIMEDOUT
1134 *w_error = ETIMEDOUT;
1135#else
1136 *w_error = 0;
1137#endif
1138 sigaction (SIGPIPE, &old_act, NULL);
1139 TPT(( 0, FIL__, __LINE__, _("msg=<Timeout>\n")));
1140 SL_RETURN( countbytes, _("sh_write_select"));
1141 }
1142 }
1143
1144 if ( FD_ISSET (sockfd, &fds) )
1145 {
1146 if (type == SH_DO_WRITE)
1147 count = write (sockfd, buf, nbytes-countbytes);
1148 else
1149 count = read (sockfd, buf, nbytes-countbytes);
1150
1151 if (count > 0)
1152 {
1153 countbytes += count;
1154 buf += count; /* move buffer pointer forward */
1155 if (countbytes < nbytes) FD_SET( sockfd, &fds );
1156 }
1157 else if (count < 0 && errno == EINTR)
1158 {
1159 FD_SET( sockfd, &fds );
1160 }
1161 else if (count < 0)
1162 {
1163 *w_error = errno;
1164 sigaction (SIGPIPE, &old_act, NULL);
[171]1165 sh_error_message(*w_error, errbuf, sizeof(errbuf));
1166 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
1167 errbuf,
1168 (type == SH_DO_WRITE) ?
1169 _("sh_write_select (w)") : _("sh_write_select (r)"));
[1]1170 TPT(( 0, FIL__, __LINE__, _("msg=<count < 0>\n")));
1171 SL_RETURN( countbytes, _("sh_write_select"));
1172 }
1173 else /* count == 0 */
1174 {
1175 *w_error = errno;
1176 sigaction (SIGPIPE, &old_act, NULL);
1177 TPT(( 0, FIL__, __LINE__, _("msg=<count == 0>\n")));
1178 SL_RETURN( countbytes, _("sh_write_select"));
1179 }
1180 }
1181 }
1182
1183
1184 /* restore signal handler
1185 */
1186 sigaction (SIGPIPE, &old_act, NULL);
1187
1188 *w_error = 0;
1189
1190 TPT(( 0, FIL__, __LINE__, _("msg=<count = %d>\n"), countbytes));
1191 SL_RETURN( countbytes, _("sh_write_select"));
1192}
1193#endif
1194
[27]1195#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1196unsigned long write_port (int sockfd, char *buf, unsigned long nbytes,
1197 int * w_error, int timeout)
1198{
1199 unsigned long bytes;
1200
1201 SL_ENTER(_("write_port"));
1202
1203 bytes = sh_write_select(SH_DO_WRITE, sockfd, buf, nbytes, w_error, timeout);
1204 if (*w_error != 0)
1205 {
[132]1206 char errbuf[SH_ERRBUF_SIZE];
[1]1207 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
[132]1208 sh_error_message (*w_error, errbuf, sizeof(errbuf)),
1209 (long) sockfd, _("write_port"));
[1]1210 }
1211 SL_RETURN( bytes, _("write_port"));
1212}
1213#endif
1214
[27]1215#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1216
1217unsigned long read_port (int sockfd, char *buf, unsigned long nbytes,
1218 int * w_error, int timeout)
1219{
1220 unsigned long bytes;
1221
1222 SL_ENTER(_("read_port"));
1223
1224 bytes = sh_write_select(SH_DO_READ, sockfd, buf, nbytes, w_error, timeout);
1225 if (*w_error != 0)
1226 {
[132]1227 char errbuf[SH_ERRBUF_SIZE];
[1]1228 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
[132]1229 sh_error_message (*w_error, errbuf, sizeof(errbuf)),
1230 (long) sockfd, _("read_port"));
[1]1231 }
1232 SL_RETURN( bytes, _("read_port"));
1233}
1234#endif
1235
1236#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1237
1238int check_request_nerr (char * have, char * need)
1239{
1240 SL_ENTER(_("check_request_nerr"));
1241 ASSERT_RET((have != NULL && need != NULL),
1242 _("have != NULL && need != NULL"), (-1))
1243
1244 if ( (have[0] == need[0]) && (have[1] == need[1]) &&
1245 (have[2] == need[2]) && (have[3] == need[3]))
1246 SL_RETURN(0, _("check_request_nerr"));
1247 SL_RETURN((-1), _("check_request_nerr"));
1248}
1249#endif
1250
[27]1251#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1252
1253int check_request (char * have, char * need)
1254{
1255 char first[21], second[5];
1256 int i;
1257
1258 SL_ENTER(_("check_request"));
1259 i = check_request_nerr (have, need);
1260
1261 if (i == 0)
1262 SL_RETURN(0, _("check_request"));
1263
1264 for (i = 0; i < 4; ++i)
1265 {
1266 second[i] = need[i];
1267 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
1268 '\\', (unsigned char) have[i]);
1269 }
1270
1271 first[20] = '\0'; second[4] = '\0';
1272
1273 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST,
1274 second, first);
1275 SL_RETURN((-1), _("check_request"));
1276}
1277#endif
1278
1279#if defined (SH_WITH_SERVER)
1280
1281int check_request_s (char * have, char * need, char * clt)
1282{
1283 char first[21], second[5];
1284 int i;
1285
1286 SL_ENTER(_("check_request_s"));
1287 i = check_request_nerr (have, need);
1288
1289 if (i == 0)
1290 SL_RETURN( (0), _("check_request_s"));
1291
1292 for (i = 0; i < 4; ++i)
1293 {
1294 second[i] = need[i];
1295 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
1296 '\\', (unsigned char) have[i]);
1297 }
1298 first[20] = '\0'; second[4] = '\0';
1299 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST1,
1300 second, first, clt);
1301 SL_RETURN( (-1), _("check_request_s"));
1302}
1303#endif
1304
[27]1305#if defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)
[1]1306
1307void get_header (unsigned char * head, unsigned long * bytes, char * u)
1308{
1309 SL_ENTER(_("get_header"));
1310
1311 *bytes =
1312 (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1313
1314 if (u != NULL)
1315 {
1316 u[0] = head[3];
1317 u[1] = head[4];
1318 u[2] = head[5];
1319 u[3] = head[6];
1320 u[4] = '\0';
1321 }
1322
1323 SL_RET0(_("get_header"));
1324}
1325#endif
1326
1327#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1328
1329#ifdef SH_ENCRYPT_2
1330#define TRANS_BYTES 65120
1331#else
1332#define TRANS_BYTES 65280
1333#endif
1334
1335void put_header (unsigned char * head, int protocol,
1336 unsigned long * length, char * u)
1337{
1338
1339 /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
1340 static unsigned long transfer_limit = TRANS_BYTES + 6 + KEY_LEN;
1341
1342 SL_ENTER(_("put_header"));
1343
1344 head[0] = protocol;
1345
1346 ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
1347
1348 if (*length > transfer_limit)
1349 *length = transfer_limit;
1350
1351 head[1] = (unsigned int)(*length/256);
1352 head[2] = (unsigned int)(*length-256 * head[1]);
1353 if (u == NULL)
1354 {
1355 head[3] = 0x01;
1356 head[4] = 0x01;
1357 head[5] = 0x01;
1358 head[6] = 0x01;
1359 }
1360 else
1361 {
1362 head[3] = u[0];
1363 head[4] = u[1];
1364 head[5] = u[2];
1365 head[6] = u[3];
1366 }
1367
1368 SL_RET0(_("put_header"));
1369}
1370#endif
1371
1372/* ------------------------------------------
1373 *
1374 * version 2 client/server protocol
1375 *
1376 * ------------------------------------------
1377 *
1378 * header : flag size[2]
1379 *
1380 * payload: random_pad[8] protocol[4] size[4] payload[payload_size] padding
1381 *
1382 * full_size <= 8192; payload_size <= 8176 (511*16); msg_size <= 8128 (508*16)
1383 * (msg_size = payload_size - key_len = payload_size - 48)
1384 */
[27]1385
1386/*
1387 * only SH_V2_FULLSIZE is used, and only once
1388 */
1389#if 0
[1]1390#ifdef SH_WITH_SERVER
1391#define SH_V2_FULLSIZE 240
1392#define SH_V2_PAYLOAD 224
1393#define SH_V2_MESSAGE 176
1394#else
1395#define SH_V2_FULLSIZE 1024
1396#define SH_V2_PAYLOAD 1008
1397#define SH_V2_MESSAGE 960
1398#endif
[27]1399#endif
1400#define SH_V2_FULLSIZE 1024
[1]1401
1402#ifdef SH_ENCRYPT
1403#include "rijndael-api-fst.h"
1404#endif
1405
1406void sh_tools_show_header (unsigned char * head, char sign)
1407{
1408#define SH_IS_ASCII(c) (((c) & ~0x7f) == 0)
1409
1410
1411 int msg_size = (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1412 char code[32];
1413 char * p = &code[0];
1414
1415 memset (code, ' ', 32); /* space */
1416
1417 if ((head[0] & SH_PROTO_SRP) != 0) { p[0]='S';p[1]='R';p[2]='P';}
1418 p += 4;
1419 if ((head[0] & SH_PROTO_MSG) != 0) { p[0]='M';p[1]='S';p[2]='G';}
1420 p += 4;
1421 if ((head[0] & SH_PROTO_BIG) != 0) { p[0]='B';p[1]='I';p[2]='G';}
1422 p += 4;
1423 if ((head[0] & SH_PROTO_END) != 0) { p[0]='E';p[1]='N';p[2]='D';}
1424 p += 4;
1425 if ((head[0] & SH_PROTO_ENC) != 0) { p[0]='E';p[1]='N';p[2]='C';}
1426 p += 4;
1427 if ((head[0] & SH_PROTO_EN2) != 0) { p[0]='E';p[1]='N';p[2]='2';}
1428 code[23] = '\0';
1429
1430 if (SH_IS_ASCII(head[3]) && isalpha(head[3]) &&
1431 SH_IS_ASCII(head[4]) && isalpha(head[4]) &&
1432 SH_IS_ASCII(head[5]) && isalpha(head[5]) &&
1433 SH_IS_ASCII(head[6]) && isalpha(head[6])) {
1434 fprintf(stderr, "%c %3o %s %5d %c %c %c %c\n", sign,
1435 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1436 } else {
1437 fprintf(stderr, "%c %3o %s %5d %2X %2X %2X %2X\n", sign,
1438 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1439 }
1440 return;
1441}
1442
1443#ifdef SH_ENCRYPT
1444/*
1445 * #define DEBUG_EN2
1446 *
1447 * ingest version 1 7-byte header and payload, return version2 header/payload
1448 * last 4 bytes of outgoing header are set to dummy value
1449 */
1450char * sh_tools_makePack (unsigned char * header,
[34]1451 char * payload, unsigned long payload_size,
[1]1452 keyInstance * keyInstE)
1453{
1454 UINT32 rpad[3];
1455 unsigned char head[16];
1456 double epad;
[34]1457 unsigned long i_epad = 0;
1458 unsigned long i_blk = payload_size / 16;
1459 unsigned long i_blkmax = SH_V2_FULLSIZE / 16;
1460 unsigned long pads = 0;
1461 size_t full_size;
[1]1462 char * full_ret;
1463
1464 char * p;
1465 RIJ_BYTE inBlock[B_SIZ];
1466 RIJ_BYTE outBlock[B_SIZ];
1467 int j;
1468 cipherInstance cipherInst;
1469 int err_num;
1470 int blkfac;
[34]1471 int oflow = 0;
[1]1472
1473 /*
1474 SL_REQUIRE (i_blk*16 == payload_size, _("payload_size % 16 != 0"));
1475 */
1476 if ((i_blk * 16) != payload_size) ++i_blk;
1477#ifdef DEBUG_EN2
1478 fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
1479#endif
1480 /* random_pad
1481 */
[137]1482 rpad[1] = taus_get ();
[1]1483 memcpy (head, &rpad[1], 4);
[137]1484 rpad[0] = taus_get ();
[1]1485 memcpy (&head[4], &rpad[0], 4);
[137]1486 rpad[2] = taus_get ();
[1]1487 memcpy (&head[8], &rpad[2], 4);
1488
1489 /* protocol
1490 */
1491 /* memcpy (&head[8], &header[3], 4); */
1492
1493 /* size (payload)
1494 */
1495 head[12] = header[1];
1496 head[13] = header[2];
1497 head[14] = '\0';
1498 head[15] = '\0';
1499
1500 if (i_blk < i_blkmax)
1501 {
1502 pads = i_blkmax - i_blk;
1503 /* memcpy((char *) &rpad[2], &head[12], 4); */
1504 epad = taus_get_double (&rpad);
1505#ifdef DEBUG_EN2
1506 fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
1507#endif
[34]1508 i_epad = (unsigned long) (pads * epad);
[1]1509#ifdef DEBUG_EN2
1510 fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
1511#endif
1512 }
1513
[34]1514 full_size = 16; /* head */
1515 if (sl_ok_muls(i_blk, 16) && sl_ok_adds(full_size, (i_blk*16)))
1516 full_size = full_size + (i_blk*16); /* payload */
1517 else
1518 oflow = 1;
1519 if (sl_ok_adds(full_size, (i_epad*16)))
1520 full_size = full_size + (i_epad*16); /* pad */
1521 else
1522 i_epad = 0;
[1]1523
[34]1524 if (oflow)
1525 {
1526 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1527 _("integer overflow"),
1528 _("sh_tools_makePack"));
1529 }
1530
[1]1531 full_ret = SH_ALLOC(full_size);
1532 memcpy(full_ret, head, 16);
[34]1533 if (payload != NULL && !oflow)
[1]1534 {
1535 memcpy(&full_ret[16], payload, payload_size);
1536 }
[34]1537 if ((i_blk*16) > payload_size && !oflow)
[1]1538 {
1539#ifdef DEBUG_EN2
1540 fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
1541#endif
1542 memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
1543 payload_size = i_blk * 16;
1544 }
1545 memset(&full_ret[16+payload_size], '\0', i_epad*16);
1546#ifdef DEBUG_EN2
1547 fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
1548#endif
1549
1550 /* rewrite header
1551 */
1552 header[1] = (unsigned int)(full_size/256);
1553 header[2] = (unsigned int)(full_size - (256 * header[1]));
1554 /* don't erase protocol from header
1555 memset(&header[3], '\0', 4);
1556 */
1557 p = full_ret; blkfac = full_size / 16;
1558
1559 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1560
1561 if (err_num < 0)
1562 {
[132]1563 char expbuf[SH_ERRBUF_SIZE];
[1]1564 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1565 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1566 _("sh_tools_makePack: cipherInit"));
1567 }
1568 for (j = 0; j < blkfac; ++j)
1569 {
1570 memcpy(inBlock, p, B_SIZ);
1571 err_num = blockEncrypt(&cipherInst, keyInstE,
1572 inBlock, 128 * BNUM, outBlock);
1573 if (err_num < 0)
1574 {
[132]1575 char expbuf[SH_ERRBUF_SIZE];
[1]1576 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1577 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1578 _("sh_tools_makePack: blockEncrypt"));
1579 }
1580 memcpy(p, outBlock, B_SIZ);
1581 p += B_SIZ;
1582 }
1583
1584 return full_ret;
1585}
1586
1587/* write a 7-byte header and return payload as expected by version 1
1588 * last 4 bytes of incoming header are dummy
1589 */
1590char * sh_tools_revertPack (unsigned char * header, char * message,
1591 keyInstance * keyInstD,
1592 unsigned long message_size)
1593{
1594 unsigned long msg_size;
1595 char * msg_ret;
1596
1597 char * p;
1598 RIJ_BYTE inBlock[B_SIZ];
1599 RIJ_BYTE outBlock[B_SIZ];
1600 int j;
1601 cipherInstance cipherInst;
1602 int err_num;
1603 int blkfac;
[132]1604 char expbuf[SH_ERRBUF_SIZE];
[1]1605
1606 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1607#ifdef DEBUG_EN2
1608 fprintf(stderr, "RECV <%lu>\n", msg_size);
1609#endif
1610 if (msg_size > message_size) {
1611 msg_size = message_size;
1612#ifdef DEBUG_EN2
1613 fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
1614#endif
1615 }
1616
1617 p = message; blkfac = msg_size / 16;
1618
1619 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1620
1621 if (err_num < 0)
1622 {
1623 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1624 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1625 _("sh_tools_revertPack: cipherInit"));
1626 }
1627 for (j = 0; j < blkfac; ++j)
1628 {
1629 memcpy(inBlock, p, B_SIZ);
1630 err_num = blockDecrypt(&cipherInst, keyInstD,
1631 inBlock, 128 * BNUM, outBlock);
1632 if (err_num < 0)
1633 {
1634 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1635 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1636 _("sh_tools_revertPack: blockDecrypt"));
1637 }
1638 memcpy(p, outBlock, B_SIZ);
1639 p += B_SIZ;
1640 }
1641
1642 /* rewrite size in header
1643 */
1644 header[1] = message[12];
1645 header[2] = message[13];
1646 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1647
1648 if (msg_size > (message_size-16))
1649 {
1650 msg_size = message_size-16;
1651 header[1] = (unsigned int)(msg_size/256);
1652 header[2] = (unsigned int)(msg_size - (256 * header[1]));
1653#ifdef DEBUG_EN2
1654 fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
1655#endif
1656 }
1657#ifdef DEBUG_EN2
1658 fprintf(stderr, "REC2 <%lu>\n", msg_size);
1659#endif
1660 /* protocol
1661 */
1662 /* memcpy(&header[3], &message[8], 4); */
1663
1664 /* payload
1665 */
1666 msg_ret = SH_ALLOC(msg_size+1);
1667 if (msg_size > 0)
1668 {
1669 memcpy(msg_ret, &message[16], msg_size);
1670 }
1671 msg_ret[msg_size] = '\0';
1672#ifdef DEBUG_EN2
1673 fprintf(stderr, "REC3 <%lu>\n", msg_size);
1674#endif
1675 SH_FREE(message);
1676
1677 return msg_ret;
1678}
1679#endif
1680
1681int sh_tools_hash_add(char * key, char * buf, int buflen)
1682{
1683 char * theSig;
[133]1684 char sigbuf[KEYBUF_SIZE];
[1]1685
1686 SL_ENTER(_("sh_tools_hash_add"));
1687
[133]1688 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1689 sl_strlcat(buf, theSig, buflen + KEY_LEN + 1);
1690
1691 SL_RETURN((0), _("sh_tools_hash_add"));
1692}
1693
1694
1695/* return 0 (== FALSE) if no match, else 1 (== TRUE)
1696 */
1697int sh_tools_hash_vfy(char * key, char * buf, int buflen)
1698{
1699 char hash[KEY_LEN+1];
1700 register int i;
1701 char * theSig;
[133]1702 char sigbuf[KEYBUF_SIZE];
[1]1703
1704 SL_ENTER(_("sh_tools_hash_vfy"));
1705
[133]1706 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1707 sl_strlcpy(hash, theSig, KEY_LEN+1);
1708
1709 for (i = 0; i < KEY_LEN; ++i)
1710 {
1711 if (buf[buflen + i] != hash[i])
1712 SL_RETURN((0), _("sh_tools_hash_vfy"));
1713 }
1714
1715 SL_RETURN((1), _("sh_tools_hash_vfy"));
1716}
1717
1718/* ------------------------------------------ */
1719
1720#if defined (SH_WITH_SERVER)
1721
1722/* add a checksum to a buffer; put checksum in front
1723 */
1724char * hash_me (char * key, char * buf, int buflen)
1725{
1726 char hash[KEY_LEN+1];
[34]1727 char * temp = NULL;
[1]1728 register int i;
1729 int total = 0;
1730 char * theSig;
[133]1731 char sigbuf[KEYBUF_SIZE];
[1]1732
1733
1734 SL_ENTER(_("hash_me"));
1735
1736#ifdef DEBUG_EN2
1737 fprintf(stderr, "hash_me <%s> <%d>\n",
1738 (key == NULL) ? "NULL" : key, buflen);
1739#endif
1740 /* key = H(NSRV,NCLT,SK)
1741 */
1742 ASSERT_RET((key != NULL), _("key != NULL"), (NULL));
1743 ASSERT_RET((buflen >= 0), _("buflen >= 0"), (NULL));
1744
[133]1745 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1746 sl_strlcpy(hash, theSig, KEY_LEN+1);
1747
[34]1748 if (sl_ok_adds(buflen, KEY_LEN))
1749 {
1750 total = KEY_LEN + buflen;
1751 temp = SH_ALLOC (total);
[1]1752
[34]1753 for (i = 0; i < KEY_LEN; ++i)
1754 temp[i] = hash[i];
[1]1755
[34]1756 for (i = 0; i < buflen; ++i)
1757 temp[i+KEY_LEN] = buf[i];
1758 }
1759 else
1760 {
1761 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1762 _("integer overflow"),
1763 _("hash_me"));
1764 temp = sh_util_strdup(buf);
1765 }
[1]1766 SL_RETURN(temp, _("hash_me"));
1767}
1768#endif
1769
[27]1770#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1771
1772/* verify the checksum of a buffer; checksum comes first
1773 */
1774int hash_check(char * key,
1775 char * buf, int buflen)
1776{
1777 char hash[KEY_LEN+1];
1778 register int i;
1779 char * theSig;
[133]1780 char sigbuf[KEYBUF_SIZE];
[1]1781
1782 SL_ENTER(_("hash_check"));
1783
1784#ifdef DEBUG_EN2
1785 fprintf(stderr, "hash_check <%s> <%d>\n",
1786 (key == NULL) ? "NULL" : key, buflen);
1787#endif
[133]1788 theSig = sh_util_siggen (key, &buf[KEY_LEN], buflen-KEY_LEN,
1789 sigbuf, sizeof(sigbuf));
[1]1790 sl_strlcpy(hash, theSig, KEY_LEN+1);
1791
1792 for (i = 0; i < KEY_LEN; ++i)
1793 {
1794 if (buf[i] != hash[i])
1795 SL_RETURN((-1), _("hash_check"));
1796 }
1797 SL_RETURN((0), _("hash_check"));
1798}
1799
1800#endif
1801
1802#if defined (SH_WITH_SERVER)
1803
1804char * get_client_conf_file (char * peer, unsigned long * length)
1805{
1806 char * ret;
[34]1807 int status;
[1]1808 struct stat buf;
1809 char * base;
[34]1810 size_t size;
[1]1811
1812 SL_ENTER(_("get_client_conf_file"));
1813
[34]1814 base = sh_util_strdup(DEFAULT_DATAROOT);
[1]1815
[34]1816 size = sl_strlen(base);
1817 if (sl_ok_adds(size, sl_strlen(peer)))
1818 size += sl_strlen(peer);
1819 if (sl_ok_adds(size, 6))
1820 size += 6;
[1]1821
1822 ret = SH_ALLOC(size);
1823 sl_strlcpy(ret, base, size);
1824 sl_strlcat(ret, _("/rc."), size);
1825 sl_strlcat(ret, peer, size);
1826
1827 status = retry_stat (FIL__, __LINE__, ret, &buf);
1828
1829 if (status == 0)
1830 goto lab_end;
1831 else
1832 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1833 (long) sh.effective.uid, ret);
1834
1835 sl_strlcpy(ret, base, size);
1836 sl_strlcat(ret, "/rc", size);
1837
1838 status = retry_stat (FIL__, __LINE__, ret, &buf);
1839
1840 if (status == 0)
1841 goto lab_end;
1842 else
1843 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
1844 (long) sh.effective.uid, ret);
1845
1846 SH_FREE(base);
[34]1847 SH_FREE(ret);
[1]1848 *length=0;
1849 SL_RETURN(NULL, _("get_client_conf_file"));
1850
1851 lab_end:
1852 if (buf.st_size > 0x7fffffff)
1853 {
1854 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1855 _("File too large"), _("get_client_conf_file"));
1856 SH_FREE(base);
1857 SL_RETURN(NULL, _("get_client_conf_file"));
1858 }
1859 *length = (unsigned long) buf.st_size;
1860 SH_FREE(base);
1861 SL_RETURN(ret, _("get_client_conf_file"));
1862}
1863
1864char * get_client_data_file (char * peer, unsigned long * length)
1865{
1866 char * ret;
[34]1867 int status;
[1]1868 struct stat buf;
1869
1870 char * base;
[34]1871 size_t size;
[1]1872
1873 SL_ENTER(_("get_client_data_file"));
1874
[34]1875 base = sh_util_strdup(DEFAULT_DATAROOT);
[1]1876
[34]1877 size = sl_strlen(base);
1878 if (sl_ok_adds(size, sl_strlen(peer)))
1879 size += sl_strlen(peer);
1880 if (sl_ok_adds(size, 8))
1881 size += 8;
[1]1882
1883 ret = SH_ALLOC(size);
1884 sl_strlcpy(ret, base, size);
1885 sl_strlcat(ret, _("/file."), size);
1886 sl_strlcat(ret, peer, size);
1887
1888 status = retry_stat (FIL__, __LINE__, ret, &buf);
1889
1890 if (status == 0)
1891 goto lab1_end;
1892 else
1893 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1894 (long) sh.effective.uid, ret);
1895
1896
1897 sl_strlcpy(ret, base, size);
1898 sl_strlcat(ret, _("/file"), size);
1899
1900 status = retry_stat (FIL__, __LINE__, ret, &buf);
1901
1902 if (status == 0)
1903 goto lab1_end;
1904 else
1905 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1906 (long) sh.effective.uid, ret);
1907
1908
1909 *length = 0;
1910 SH_FREE(base);
[34]1911 SH_FREE(ret);
[1]1912 SL_RETURN(NULL, _("get_client_data_file"));
1913
1914 lab1_end:
1915 if (buf.st_size > 0x7fffffff)
1916 {
1917 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1918 _("File too large"), _("get_client_data_file"));
1919 SH_FREE(base);
1920 SL_RETURN(NULL, _("get_client_data_file"));
1921 }
1922 *length = (unsigned long) buf.st_size;
1923 SH_FREE(base);
1924 SL_RETURN(ret, _("get_client_data_file"));
1925
1926}
1927#endif
1928
[27]1929#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
[1]1930
1931/* --------- secure temporary file ------------ */
1932
1933SL_TICKET open_tmp ()
1934{
1935 SL_TICKET fd;
1936 UINT32 ticks;
1937 char * file;
1938 struct stat buf;
1939 int error;
1940 int status = BAD;
1941 char * my_tmp_dir;
[133]1942 char hashbuf[KEYBUF_SIZE];
[1]1943
1944 SL_ENTER(_("open_tmp"));
1945
1946#if defined(SH_TMPDIR)
[34]1947 my_tmp_dir = sh_util_strdup(SH_TMPDIR);
[1]1948#else
1949#if defined(SH_WITH_SERVER)
[34]1950 my_tmp_dir = sh_util_strdup(DEFAULT_LOGDIR);
[1]1951#else
[34]1952 my_tmp_dir = sh_util_strdup(sh.effective.home);
[1]1953#endif
1954#endif
1955
1956 if (0 != tf_trust_check (my_tmp_dir, SL_YESPRIV))
1957 {
1958 dlog(1, FIL__, __LINE__,
1959 _("The directory for temporary files: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"),
1960 my_tmp_dir);
1961 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST,
1962 (long) sh.effective.uid,
1963 my_tmp_dir);
1964 SH_FREE(my_tmp_dir);
1965 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1966 }
1967
1968 do {
1969
1970 /* create random filename in effective users home directory
1971 */
[137]1972 ticks = taus_get ();
[1]1973 if (my_tmp_dir[0] == '/' && my_tmp_dir[1] == '\0')
1974 file = sh_util_strconcat (my_tmp_dir,
[133]1975 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1976 hashbuf, sizeof(hashbuf)),
[1]1977 NULL);
1978 else
1979 file = sh_util_strconcat (my_tmp_dir,
1980 "/",
[133]1981 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1982 hashbuf, sizeof(hashbuf)),
[1]1983 NULL);
1984
1985 /* check whether it already exists (paranoia)
1986 */
1987 errno = 0;
1988 status = retry_lstat(FIL__, __LINE__, file, &buf);
1989 error = errno;
1990
1991 if ( (status < 0) && (error == ENOENT) ) /* file does not exist */
1992 status = GOOD;
1993 else if (status < 0) /* unexpected error condition */
1994 {
1995 SH_FREE (file);
1996 SH_FREE(my_tmp_dir);
[169]1997 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
1998 _("Error (lstat) while opening temporary file"), _("open_tmp"));
[1]1999 TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
2000 SL_RETURN((-1), _("open_tmp"));
2001 }
2002 else /* file exists */
2003 {
2004 status = BAD;
2005 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file exists already>\n")));
2006 }
2007
2008 if (status == GOOD)
2009 {
2010 if (0 == tf_trust_check (file, SL_YESPRIV))
2011 status = GOOD;
2012 else
2013 {
2014 status = BAD;
2015 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file untrusted>\n")));
2016 }
2017 }
2018
2019 if (status == BAD)
2020 SH_FREE (file);
2021
2022 } while (status == BAD);
2023
[248]2024 fd = sl_open_safe_rdwr (FIL__, __LINE__, file, SL_YESPRIV);
[1]2025 if (SL_ISERROR(fd))
2026 {
2027 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN,
2028 _("Error opening temporary file"), _("open_tmp"));
2029 TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"),
2030 fd, file));
2031 }
2032
2033
2034 SH_FREE (file);
2035 SH_FREE(my_tmp_dir);
2036
2037 if (!SL_ISERROR(fd)) {
2038 sl_unlink(fd);
2039 }
2040
2041 if (!SL_ISERROR(fd))
2042 SL_RETURN((fd), _("open_tmp"));
2043 else
2044 SL_RETURN((-1), _("open_tmp"));
2045}
2046
2047
2048int close_tmp (SL_TICKET fd)
2049{
2050 SL_ENTER(_("close_tmp"));
2051
2052 if (SL_ISERROR(sl_close (fd)))
2053 SL_RETURN((-1), _("close_tmp"));
2054 SL_RETURN((0), _("close_tmp"));
2055}
2056
2057int rewind_tmp (SL_TICKET fd)
2058{
2059 SL_ENTER(_("rewind_tmp"));
2060
2061 if (SL_ISERROR(sl_rewind (fd)))
2062 SL_RETURN((-1), _("rewind_tmp"));
2063 SL_RETURN((0), _("rewind_tmp"));
2064}
2065#endif
Note: See TracBrowser for help on using the repository browser.