source: trunk/src/sh_tools.c@ 526

Last change on this file since 526 was 481, checked in by katerina, 9 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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