source: trunk/src/sh_tools.c@ 580

Last change on this file since 580 was 562, checked in by katerina, 3 years ago

Fix for ticket #450 (compiler warnings) and fixes for tests.

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