source: trunk/src/sh_tools.c@ 259

Last change on this file since 259 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

File size: 42.3 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27
28/* Must be early on FreeBSD
29 */
30#include <sys/types.h>
31
32#ifdef HAVE_MEMORY_H
33#include <memory.h>
34#endif
35
36#ifdef HAVE_SYS_SELECT_H
37#include <sys/select.h>
38#endif
39
40#ifdef HAVE_UNISTD_H
41#include <errno.h>
42#include <signal.h>
43#include <setjmp.h>
44#include <pwd.h>
45#include <grp.h>
46#include <sys/stat.h>
47#include <sys/resource.h>
48#include <fcntl.h>
49#include <sys/wait.h>
50#include <unistd.h>
51#endif
52
53#include <sys/socket.h>
54
55#ifdef HOST_IS_HPUX
56#define _XOPEN_SOURCE_EXTENDED
57#endif
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#include <netdb.h>
61
62#ifndef FD_SET
63#define NFDBITS 32
64#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
65#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
66#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
67#endif /* !FD_SET */
68#ifndef FD_SETSIZE
69#define FD_SETSIZE 32
70#endif
71#ifndef FD_ZERO
72#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
73#endif
74
75
76#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
77#include <sys/mman.h>
78#endif
79
[11]80#define SH_REAL_SET
81
[1]82#include "samhain.h"
83#include "sh_mem.h"
84#include "sh_error.h"
85#include "sh_tools.h"
86#include "sh_utils.h"
87#include "sh_tiger.h"
88#define SH_NEED_GETHOSTBYXXX
89#include "sh_static.h"
[137]90#include "sh_pthread.h"
[1]91
92#undef FIL__
93#define FIL__ _("sh_tools.c")
94
95#ifdef SH_ENCRYPT
96#include "rijndael-api-fst.h"
[132]97char * errorExplain (int err_num, char * buffer, size_t len)
[1]98{
[132]99 char * p;
100
[1]101 if (err_num == BAD_KEY_DIR)
[132]102 p = (_("Key direction is invalid"));
[1]103 else if (err_num == BAD_KEY_MAT)
[132]104 p = (_("Key material not of correct length"));
[1]105 else if (err_num == BAD_KEY_INSTANCE)
[132]106 p = (_("Key passed is not valid"));
[1]107 else if (err_num == BAD_CIPHER_MODE)
[132]108 p = (_("Params struct passed to cipherInit invalid"));
[1]109 else if (err_num == BAD_CIPHER_STATE)
[132]110 p = (_("Cipher in wrong state"));
[1]111 else if (err_num == BAD_BLOCK_LENGTH)
[132]112 p = (_("Bad block length"));
[1]113 else if (err_num == BAD_CIPHER_INSTANCE)
[132]114 p = (_("Bad cipher instance"));
[1]115 else if (err_num == BAD_DATA)
[132]116 p = (_("Data contents are invalid"));
[1]117 else
[132]118 p = (_("Unknown error"));
119 sl_strlcpy (buffer, p, len);
120 return buffer;
[1]121}
122
123#endif
124
[197]125/* --- check for an interface ---
126 */
127int sh_tools_iface_is_present(char *str)
128{
129 struct sockaddr_in sin;
130 int sd;
131
132 memset(&sin, '\0', sizeof(sin));
133 sin.sin_family = AF_INET;
134 if (inet_aton(str, &(sin.sin_addr)))
135 {
136 sin.sin_port = htons(2543);
137
138 if (-1 == (sd = socket(AF_INET, SOCK_STREAM, 0)))
139 {
140 return 0;
141 }
142
143 if (-1 == bind(sd, (struct sockaddr *)&sin, sizeof(sin)))
144 {
145 int retval = 0;
146
147 /* bind() fails for access reasons, iface exists
148 */
149 if (errno == EACCES || errno == EADDRINUSE)
150 retval = 1;
[252]151 sl_close_fd (FIL__, __LINE__, sd);
[197]152 return retval;
153 }
154
155 /* bind() succeeds, iface exists
156 */
[252]157 sl_close_fd(FIL__, __LINE__, sd);
[197]158 return 1;
159 }
160 return 0;
161}
162
[1]163/* --- recode all \blah escapes to '=XX' format, and also code all
164 * remaining unprintable chars ---
165 */
[12]166#define SH_PUT_4(p, a, b, c) (p)[0] = (a); (p)[1] = (b); (p)[2] = (c);
167
[1]168char * sh_tools_safe_name (const char * instr, int flag)
169{
[18]170 unsigned char c, d;
[1]171 const char * p;
172 char tmp[4];
173 char * outstr;
[34]174 size_t len = 1;
[1]175 int i = 0;
176 unsigned char val_octal = '\0';
[18]177 static char ctable[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
178 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
[1]179
180 SL_ENTER(_("sh_tools_safe_name"));
181
182 if (instr)
[34]183 {
184 len = strlen(instr);
185 if (sl_ok_muls (3, len) && sl_ok_adds ((3*len), 4))
186 {
187 len = (3 * len) + 4;
188 p = instr;
189 }
190 else
191 {
192 len = 1;
193 p = NULL;
194 }
195 }
196 else
197 {
198 p = NULL;
199 }
[1]200
201 outstr = SH_ALLOC(len);
202
203 outstr[0] = '\0';
204 tmp[3] = '\0';
205
[11]206#if !defined(SH_USE_XML)
207 (void) flag; /* fix compiler warning */
208#endif
209
210 if (!p)
211 goto end;
212
213 while (*p)
[1]214 {
215 c = *p;
216
217 if (*p == '\n')
218 {
219 outstr[i] = ' '; ++i; ++p;
220 continue;
221 }
222
223#ifdef SH_USE_XML
[11]224 if (flag == 1)
225 {
226 if ((*p) == '"')
227 {
[12]228 SH_PUT_4(&outstr[i], '=', '2', '2');
229 i+=3; ++p;
[11]230 continue;
231 }
232 else if ((*p) == '&')
233 {
[12]234 SH_PUT_4(&outstr[i], '=', '2', '6');
235 i+=3; ++p;
[11]236 continue;
237 }
238 else if ((*p) == '<')
239 { /* left angle */
[12]240 SH_PUT_4(&outstr[i], '=', '3', 'c');
241 i+=3; ++p;
[11]242 continue;
243 }
244 else if ((*p) == '>')
245 { /* right angle */
[12]246 SH_PUT_4(&outstr[i], '=', '3', 'e');
247 i+=3; ++p;
[11]248 continue;
249 }
[1]250 }
251#endif
252
[12]253 if ( (*p) != '\\' && (*p) != '&' && (*p) != '=' && (*p) != '\'')
[1]254 {
[11]255 outstr[i] = *p; ++i;
256 ++p;
257
[81]258 if (c < 32 || c > 126)
[1]259 {
[11]260 --i;
[18]261 d = c % 16; c = c / 16;
262 outstr[i] = '='; ++i;
263 outstr[i] = ctable[c]; ++i;
264 outstr[i] = ctable[d]; ++i;
[1]265 }
[11]266
[1]267 continue;
268 }
269 else if ((*p) == '\'')
270 {
[12]271 SH_PUT_4(&outstr[i], '=', '2', '7');
272 i+=3; ++p;
[1]273 }
274 else if (*p == '=')
275 {
276 if (p[1] != '"' && p[1] != '<')
277 {
[12]278 SH_PUT_4(&outstr[i], '=', '3', 'd');
279 i+=3; ++p;
[1]280 }
281 else
282 { outstr[i] = *p; ++i; ++p; }
283 }
284 else if (*p == '\\')
285 {
286 ++p;
287 if (!p)
288 break;
289 if (!(*p))
290 break;
291
292 c = *p;
293
294 switch (*p) {
295 case '\\':
[12]296 SH_PUT_4(&outstr[i], '=', '5', 'c');
297 i+=3; ++p;
[1]298 break;
299 case 'n':
[12]300 SH_PUT_4(&outstr[i], '=', '0', 'a');
[1]301 i+=3; ++p;
302 break;
303 case 'b':
[12]304 SH_PUT_4(&outstr[i], '=', '0', '8');
[1]305 i+=3; ++p;
306 break;
307 case 'r':
[12]308 SH_PUT_4(&outstr[i], '=', '0', 'd');
[1]309 i+=3; ++p;
310 break;
311 case 't':
[12]312 SH_PUT_4(&outstr[i], '=', '0', '9');
[1]313 i+=3; ++p;
314 break;
315 case 'v':
[12]316 SH_PUT_4(&outstr[i], '=', '0', 'b');
[1]317 i+=3; ++p;
318 break;
319 case 'f':
[12]320 SH_PUT_4(&outstr[i], '=', '0', 'c');
[1]321 i+=3; ++p;
322 break;
323 case '\'':
[12]324 SH_PUT_4(&outstr[i], '=', '2', '7');
[1]325 i+=3; ++p;
326 break;
[12]327 case '"': /* also encode quoted '"' */
328 SH_PUT_4(&outstr[i], '=', '2', '2');
[1]329 i+=3; ++p;
330 break;
331 case ' ':
[12]332 SH_PUT_4(&outstr[i], '=', '2', '0');
[1]333 i+=3; ++p;
334 break;
335 default:
[18]336 if (strlen(p) < 3) /* certainly not an octal number, skip */
[1]337 {
338 p += strlen(p);
339 }
340 else
341 {
342 tmp[0] = p[0]; tmp[1] = p[1]; tmp[2] = p[2];
343 val_octal = (unsigned char) strtoul(tmp, (char **)NULL, 8);
344 if (val_octal != '\0') {
345 c = val_octal;
[18]346 d = c % 16; c = c / 16;
347 outstr[i] = '='; ++i;
348 outstr[i] = ctable[c]; ++i;
349 outstr[i] = ctable[d]; ++i;
[1]350 }
351 p += 3;
352 }
353 }
354 }
[11]355 else if (*p == '&')
[1]356 {
357 ++p;
[18]358 if (!p || !(*p))
359 {
360 outstr[i] = '&'; ++i;
361 break;
362 }
[1]363
364 if (p[0] == 'a' && p[1] == 'm' && p[2] == 'p' && p[3] == ';')
365 {
[12]366 SH_PUT_4(&outstr[i], '=', '2', '6');
[1]367 i+=3; p += 4;
368 }
369 else if (p[0] == 'q' && p[1] == 'u' && p[2] == 'o' && p[3] == 't' &&
370 p[4] == ';')
371 {
[12]372 SH_PUT_4(&outstr[i], '=', '2', '2');
[1]373 i+=3; p += 5;
374 }
375 else if (p[0] == 'l' && p[1] == 't' && p[2] == ';')
376 {
[12]377 SH_PUT_4(&outstr[i], '=', '3', 'c');
[1]378 i+=3; p += 3;
379 }
380 else if (p[0] == 'g' && p[1] == 't' && p[2] == ';')
381 {
[12]382 SH_PUT_4(&outstr[i], '=', '3', 'e');
[1]383 i+=3; p += 3;
384 }
385 else /* conserve the '&' */
386 {
387 outstr[i] = '&'; ++i;
388 }
[11]389 }
390 else
391 {
392 outstr[i] = *p; ++i;
393 ++p;
394 }
[1]395 } /* while (p && *p) */
[11]396
397 end:
[1]398
399 outstr[i] = '\0';
400 SL_RETURN( outstr, _("sh_tools_safe_name"));
401}
402
403
404/* extern int h_errno; */
405
[132]406char * sh_tools_errmessage (int tellme, char * errbuf, size_t len)
[1]407{
[132]408 char * p = NULL;
[1]409#ifdef HOST_NOT_FOUND
410 if (tellme == HOST_NOT_FOUND)
[132]411 p = _("The specified host is unknown: ");
[1]412#endif
413#ifdef NO_ADDRESS
414 if (tellme == NO_ADDRESS)
[132]415 p = _("The requested name is valid but does not have an IP address: ");
[1]416#endif
417#ifdef NO_RECOVERY
418 if (tellme == NO_RECOVERY)
[132]419 p = _("A non-recoverable name server error occurred: ");
[1]420#endif
421#ifdef TRY_AGAIN
422 if (tellme == TRY_AGAIN)
[132]423 p = _("A temporary error occurred on an authoritative name server. The specified host is unknown: ");
[1]424#endif
[132]425 if (!p) p = _("Unknown error");
426 sl_strlcpy(errbuf, p, len);
427 return errbuf;
[1]428}
429
430int is_numeric (const char * address)
431{
432 int j;
433 int len = sl_strlen(address);
434
435 for (j = 0; j < len; ++j)
436 if ( (address[j] < '0' || address[j] > '9') && address[j] != '.')
437 return (1 == 0);
438 return (1 == 1);
439}
440
441#if defined (SH_WITH_SERVER)
442
443int get_open_max ()
444{
445 int value;
446
447#ifdef _SC_OPEN_MAX
448 value = sysconf (_SC_OPEN_MAX);
449#else
450#ifdef OPEN_MAX
451 value = OPEN_MAX;
452#else
453 value = _POSIX_OPEN_MAX;
454#endif
455#endif
456
457 if (value < 0)
458 value = 8; /* POSIX lower limit */
459
460 if (value > 4096)
461 value = 4096;
462
463 return value;
464}
465
466#endif
467
468typedef struct _sin_cache {
469 char * address;
470 struct sockaddr_in sin;
471 struct _sin_cache * next;
472} sin_cache;
473
474static sin_cache * conn_cache = NULL;
475static int cached_addr = 0;
476
477void delete_cache()
478{
479 sin_cache * check_cache = conn_cache;
480 sin_cache * old_entry = conn_cache;
481
482 SL_ENTER(_("delete_cache"));
483
484 while (check_cache != NULL)
485 {
486 old_entry = check_cache;
487 check_cache = check_cache->next;
488 SH_FREE(old_entry->address);
489 SH_FREE(old_entry);
490 }
491
492 cached_addr = 0;
493
494 conn_cache = NULL;
495 SL_RET0(_("delete_cache"));
496}
497
498int DoReverseLookup = S_TRUE;
499
[22]500int set_reverse_lookup (const char * c)
[1]501{
502 return sh_util_flagval(c, &DoReverseLookup);
503}
504
505int connect_port (char * address, int port,
506 char * ecall, int * errnum, char * errmsg, int errsiz)
507{
508 struct in_addr haddr; /* host address from numeric */
509 /* host details returned by the DNS */
510 struct hostent *host_entry = NULL;
511 struct sockaddr_in sinr; /* socket to the remote host */
512
513 char * host_name;
514
[170]515 volatile int fd = (-1);
[1]516 int status;
[170]517 volatile int fail = 0;
[1]518 int cached = 0;
519
520 int retval;
[132]521 char errbuf[SH_ERRBUF_SIZE];
[1]522
523 sin_cache * check_cache = conn_cache;
524
525 SL_ENTER(_("connect_port"));
526
527 /* paranoia -- should not happen
528 */
529 if (cached_addr > 128)
530 delete_cache();
531
532 if (check_cache != NULL)
533 {
534 while (check_cache && check_cache->address)
535 {
536 if ( 0 == sl_strncmp(check_cache->address,
537 address, sl_strlen(address)))
538 {
539 memcpy (&sinr, &(check_cache->sin), sizeof(struct sockaddr_in));
540 sinr.sin_family = AF_INET;
541 sinr.sin_port = htons (port);
542 cached = 1;
543 break;
544 }
545 if (check_cache->next)
546 check_cache = check_cache->next;
547 else
548 check_cache = NULL;
549 }
550 }
551
552 /* only use gethostbyname() if neccessary
553 */
554 if (cached == 0)
555 {
556#ifdef HAVE_INET_ATON
557 if (0 == inet_aton(address, &haddr))
558#else
559 if ((unsigned long)-1 == (haddr.s_addr = inet_addr(address)))
560#endif
561 {
[170]562 SH_MUTEX_LOCK(mutex_resolv);
563
[143]564 host_name = NULL;
565
[1]566 host_entry = sh_gethostbyname(address);
567
568 if (host_entry == NULL || host_entry->h_addr == NULL)
569 {
570 sl_strlcpy(ecall, _("gethostbyname"), SH_MINIBUF);
571#ifndef NO_H_ERRNO
572 *errnum = h_errno;
573#else
574 *errnum = 666;
575#endif
[132]576 (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
[1]577 sl_strlcat(errmsg, address, errsiz);
578 fail = (-1);
579 }
580 else
581 {
582 sinr.sin_family = AF_INET;
583 sinr.sin_port = htons (port);
584 sinr.sin_addr = *(struct in_addr *) host_entry->h_addr;
585
586
587 /* reverse DNS lookup
588 */
589 if (DoReverseLookup == S_TRUE)
590 {
591 if (host_entry->h_name == NULL)
592 {
593 host_name = SH_ALLOC(1);
594 host_name[0] = '\0';
595 }
596 else
597 {
[34]598 host_name = sh_util_strdup(host_entry->h_name);
[1]599 }
600
601 host_entry = sh_gethostbyaddr ((char *) &sinr.sin_addr,
602 sizeof(struct in_addr),
603 AF_INET);
604 if (host_entry == NULL || host_entry->h_name == NULL)
605 {
606 sl_strlcpy(ecall, _("gethostbyaddr"), SH_MINIBUF);
607#ifndef NO_H_ERRNO
608 *errnum = h_errno;
609#else
610 *errnum = 666;
611#endif
[132]612 (void) sh_tools_errmessage (*errnum, errmsg, errsiz);
[1]613 sl_strlcat(errmsg,
614 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
615 errsiz);
616 fail = (-1);
617 }
618 else
619 {
620 *errnum = 0;
621 if (sl_strlen(host_entry->h_name) == 0 ||
[169]622 (*errnum = sl_strcasecmp(host_name,host_entry->h_name)) != 0)
[1]623 {
624 if (*errnum)
625 sl_strlcpy(ecall, _("strcmp"), SH_MINIBUF);
626 else
627 sl_strlcpy(ecall, _("strlen"), SH_MINIBUF);
[161]628 sl_strlcpy(errmsg, _("Reverse lookup failed: "),
[1]629 errsiz);
630 sl_strlcat(errmsg, address, errsiz);
631 sl_strlcat(errmsg, _(" vs "), errsiz);
632 sl_strlcat(errmsg,
633 inet_ntoa (*(struct in_addr *) &(sinr.sin_addr)),
634 errsiz);
635 fail = -1;
636 }
637 }
638 }
639 }
[134]640 SH_MUTEX_UNLOCK(mutex_resolv);
[143]641 if (host_name) SH_FREE(host_name);
[1]642 }
643
644 else /* address was numeric */
645 {
646 sinr.sin_family = AF_INET;
647 sinr.sin_port = htons (port);
648 sinr.sin_addr = haddr;
649 }
650
651
652 if (fail != -1)
653 {
654 /* put it into the cache
655 */
656 check_cache = SH_ALLOC(sizeof(sin_cache));
657 check_cache->address = SH_ALLOC(sl_strlen(address) + 1);
658 sl_strlcpy (check_cache->address, address, sl_strlen(address) + 1);
659 memcpy(&(check_cache->sin), &sinr, sizeof(struct sockaddr_in));
660 ++cached_addr;
661
662 if (conn_cache)
663 {
664 if (conn_cache->next)
665 check_cache->next = conn_cache->next;
666 else
667 check_cache->next = NULL;
668 conn_cache->next = check_cache;
669 }
670 else
671 {
672 check_cache->next = NULL;
673 conn_cache = check_cache;
674 }
675 }
676 }
677
678
679 if (fail != (-1))
680 {
681 fd = socket(AF_INET, SOCK_STREAM, 0);
682 if (fd < 0) {
683 fail = (-1);
684 status = errno;
685 sl_strlcpy(ecall, _("socket"), SH_MINIBUF);
686 *errnum = status;
[132]687 sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
[1]688 sl_strlcat(errmsg, _(", address "), errsiz);
689 sl_strlcat(errmsg, address, errsiz);
690 }
691 }
692
693 if (fail != (-1)) {
694
695 if ( retry_connect(FIL__, __LINE__, fd,
696 (struct sockaddr *) &sinr, sizeof(sinr)) < 0)
697 {
698 status = errno;
699 sl_strlcpy(ecall, _("connect"), SH_MINIBUF);
700 *errnum = status;
[132]701 sl_strlcpy(errmsg, sh_error_message (status, errbuf, sizeof(errbuf)), errsiz);
[1]702 sl_strlcat(errmsg, _(", address "), errsiz);
703 sl_strlcat(errmsg, address, errsiz);
[252]704 sl_close_fd(FIL__, __LINE__, fd);
[1]705 fail = (-1);
706 }
707 }
708
709 retval = (fail < 0) ? (-1) : fd;
710 SL_RETURN(retval, _("connect_port"));
711}
712
713int connect_port_2 (char * address1, char * address2, int port,
714 char * ecall, int * errnum, char * errmsg, int errsiz)
715{
716 int retval = (-1);
717
718 SL_ENTER(_("connect_port_2"));
719
720 errmsg[0] = '\0';
721 *errnum = 0;
722
723 if (address1 != NULL && address1[0] != '\0')
724 retval = connect_port (address1, port,
725 ecall, errnum,
726 errmsg, errsiz);
727
728 if (retval < 0 && address2 != NULL && address2[0] != '\0')
729 {
730 /* can't use sh_error_handle here, as this would cause an infinite
731 * loop if called from sh_unix_time
732 */
733 TPT(( 0, FIL__, __LINE__, _("msg=<Using alternative server %s.>\n"),
734 address2));
735 retval = connect_port (address2, port,
736 ecall, errnum,
737 errmsg, errsiz);
738 }
739
740 if ((retval < 0) &&
741 (address1 == NULL || address1[0] == '\0') &&
742 (address1 == NULL || address1[0] == '\0'))
743 {
744 sl_strlcpy(ecall, _("connect_port_2"), SH_MINIBUF);
745 sl_strlcpy(errmsg, _("No server address known"), errsiz);
746 }
747 SL_RETURN(retval, _("connect_port_2"));
748 /* return retval; */
749}
750
[27]751#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]752static
753int sh_write_select(int type, int sockfd,
754 char *buf, int nbytes,
755 int * w_error, int timeout)
756{
757 int countbytes, count;
758 fd_set fds;
759 struct timeval tv;
760 int select_now;
761 int num_sel;
762
763 struct sigaction new_act;
764 struct sigaction old_act;
[132]765 char errbuf[SH_ERRBUF_SIZE];
[1]766
767 SL_ENTER(_("sh_write_select"));
768
769 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
770 */
771 new_act.sa_handler = SIG_IGN;
[22]772 sigemptyset( &new_act.sa_mask ); /* set an empty mask */
773 new_act.sa_flags = 0; /* init sa_flags */
[1]774 sigaction (SIGPIPE, &new_act, &old_act);
775
776 FD_ZERO(&fds);
777 FD_SET(sockfd, &fds);
778
779 countbytes = 0;
780 tv.tv_sec = 1;
781 tv.tv_usec = 0;
782 select_now = 0;
783
784 *w_error = 0;
785
786 while ( countbytes < nbytes ) {
787
788 FD_ZERO(&fds);
789 FD_SET(sockfd, &fds);
790
791 if (type == SH_DO_WRITE)
792 {
793 if ( (num_sel = select (sockfd+1, NULL, &fds, NULL, &tv)) == -1)
794 {
795 if (sig_raised == 1)
796 {
797 sig_raised = 2;
798 continue;
799 }
[171]800 if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
[1]801 continue;
802 *w_error = errno;
803 sigaction (SIGPIPE, &old_act, NULL);
[171]804 sh_error_message(*w_error, errbuf, sizeof(errbuf));
805 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
806 errbuf,
807 _("sh_write_select (ws)") );
808 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
[1]809 SL_RETURN( countbytes, _("sh_write_select"));
810 }
811 }
812 else
813 {
814 if ( (num_sel = select (sockfd+1, &fds, NULL, NULL, &tv)) == -1)
815 {
816 if (sig_raised == 1)
817 {
818 sig_raised = 2;
819 continue;
820 }
[171]821 if ( errno == EINTR || errno == EINPROGRESS ) /* try again */
[1]822 continue;
823 *w_error = errno;
824 sigaction (SIGPIPE, &old_act, NULL);
[171]825 sh_error_message(*w_error, errbuf, sizeof(errbuf));
826 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
827 errbuf,
828 _("sh_write_select (rs)") );
829 TPT(( 0, FIL__, __LINE__, _("msg=<select: %s>\n"), errbuf ));
[1]830 SL_RETURN( countbytes, _("sh_write_select"));
831 }
832 }
833
834 /* on Linux, timeout is modified to reflect the amount of
835 * time not slept
836 */
837 tv.tv_sec = 1;
838 tv.tv_usec = 0;
839
840
841 /* let's not hang on forever
842 */
843 if (num_sel == 0)
844 {
845 ++select_now; /* timeout */
846 if ( select_now > timeout ) /* 5 minutes */
847 {
848#ifdef ETIMEDOUT
849 *w_error = ETIMEDOUT;
850#else
851 *w_error = 0;
852#endif
853 sigaction (SIGPIPE, &old_act, NULL);
854 TPT(( 0, FIL__, __LINE__, _("msg=<Timeout>\n")));
855 SL_RETURN( countbytes, _("sh_write_select"));
856 }
857 }
858
859 if ( FD_ISSET (sockfd, &fds) )
860 {
861 if (type == SH_DO_WRITE)
862 count = write (sockfd, buf, nbytes-countbytes);
863 else
864 count = read (sockfd, buf, nbytes-countbytes);
865
866 if (count > 0)
867 {
868 countbytes += count;
869 buf += count; /* move buffer pointer forward */
870 if (countbytes < nbytes) FD_SET( sockfd, &fds );
871 }
872 else if (count < 0 && errno == EINTR)
873 {
874 FD_SET( sockfd, &fds );
875 }
876 else if (count < 0)
877 {
878 *w_error = errno;
879 sigaction (SIGPIPE, &old_act, NULL);
[171]880 sh_error_message(*w_error, errbuf, sizeof(errbuf));
881 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, errno, MSG_E_SUBGEN,
882 errbuf,
883 (type == SH_DO_WRITE) ?
884 _("sh_write_select (w)") : _("sh_write_select (r)"));
[1]885 TPT(( 0, FIL__, __LINE__, _("msg=<count < 0>\n")));
886 SL_RETURN( countbytes, _("sh_write_select"));
887 }
888 else /* count == 0 */
889 {
890 *w_error = errno;
891 sigaction (SIGPIPE, &old_act, NULL);
892 TPT(( 0, FIL__, __LINE__, _("msg=<count == 0>\n")));
893 SL_RETURN( countbytes, _("sh_write_select"));
894 }
895 }
896 }
897
898
899 /* restore signal handler
900 */
901 sigaction (SIGPIPE, &old_act, NULL);
902
903 *w_error = 0;
904
905 TPT(( 0, FIL__, __LINE__, _("msg=<count = %d>\n"), countbytes));
906 SL_RETURN( countbytes, _("sh_write_select"));
907}
908#endif
909
[27]910#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]911unsigned long write_port (int sockfd, char *buf, unsigned long nbytes,
912 int * w_error, int timeout)
913{
914 unsigned long bytes;
915
916 SL_ENTER(_("write_port"));
917
918 bytes = sh_write_select(SH_DO_WRITE, sockfd, buf, nbytes, w_error, timeout);
919 if (*w_error != 0)
920 {
[132]921 char errbuf[SH_ERRBUF_SIZE];
[1]922 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
[132]923 sh_error_message (*w_error, errbuf, sizeof(errbuf)),
924 (long) sockfd, _("write_port"));
[1]925 }
926 SL_RETURN( bytes, _("write_port"));
927}
928#endif
929
[27]930#if defined(HAVE_NTIME) || defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]931
932unsigned long read_port (int sockfd, char *buf, unsigned long nbytes,
933 int * w_error, int timeout)
934{
935 unsigned long bytes;
936
937 SL_ENTER(_("read_port"));
938
939 bytes = sh_write_select(SH_DO_READ, sockfd, buf, nbytes, w_error, timeout);
940 if (*w_error != 0)
941 {
[132]942 char errbuf[SH_ERRBUF_SIZE];
[1]943 sh_error_handle((-1), FIL__, __LINE__, *w_error, MSG_TCP_NETRP,
[132]944 sh_error_message (*w_error, errbuf, sizeof(errbuf)),
945 (long) sockfd, _("read_port"));
[1]946 }
947 SL_RETURN( bytes, _("read_port"));
948}
949#endif
950
951#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
952
953int check_request_nerr (char * have, char * need)
954{
955 SL_ENTER(_("check_request_nerr"));
956 ASSERT_RET((have != NULL && need != NULL),
957 _("have != NULL && need != NULL"), (-1))
958
959 if ( (have[0] == need[0]) && (have[1] == need[1]) &&
960 (have[2] == need[2]) && (have[3] == need[3]))
961 SL_RETURN(0, _("check_request_nerr"));
962 SL_RETURN((-1), _("check_request_nerr"));
963}
964#endif
965
[27]966#if defined (SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]967
968int check_request (char * have, char * need)
969{
970 char first[21], second[5];
971 int i;
972
973 SL_ENTER(_("check_request"));
974 i = check_request_nerr (have, need);
975
976 if (i == 0)
977 SL_RETURN(0, _("check_request"));
978
979 for (i = 0; i < 4; ++i)
980 {
981 second[i] = need[i];
982 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
983 '\\', (unsigned char) have[i]);
984 }
985
986 first[20] = '\0'; second[4] = '\0';
987
988 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST,
989 second, first);
990 SL_RETURN((-1), _("check_request"));
991}
992#endif
993
994#if defined (SH_WITH_SERVER)
995
996int check_request_s (char * have, char * need, char * clt)
997{
998 char first[21], second[5];
999 int i;
1000
1001 SL_ENTER(_("check_request_s"));
1002 i = check_request_nerr (have, need);
1003
1004 if (i == 0)
1005 SL_RETURN( (0), _("check_request_s"));
1006
1007 for (i = 0; i < 4; ++i)
1008 {
1009 second[i] = need[i];
1010 sprintf(&first[i*4], _("%c%03o"), /* known to fit */
1011 '\\', (unsigned char) have[i]);
1012 }
1013 first[20] = '\0'; second[4] = '\0';
1014 sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_NETST1,
1015 second, first, clt);
1016 SL_RETURN( (-1), _("check_request_s"));
1017}
1018#endif
1019
[27]1020#if defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)
[1]1021
1022void get_header (unsigned char * head, unsigned long * bytes, char * u)
1023{
1024 SL_ENTER(_("get_header"));
1025
1026 *bytes =
1027 (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1028
1029 if (u != NULL)
1030 {
1031 u[0] = head[3];
1032 u[1] = head[4];
1033 u[2] = head[5];
1034 u[3] = head[6];
1035 u[4] = '\0';
1036 }
1037
1038 SL_RET0(_("get_header"));
1039}
1040#endif
1041
1042#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1043
1044#ifdef SH_ENCRYPT_2
1045#define TRANS_BYTES 65120
1046#else
1047#define TRANS_BYTES 65280
1048#endif
1049
1050void put_header (unsigned char * head, int protocol,
1051 unsigned long * length, char * u)
1052{
1053
1054 /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
1055 static unsigned long transfer_limit = TRANS_BYTES + 6 + KEY_LEN;
1056
1057 SL_ENTER(_("put_header"));
1058
1059 head[0] = protocol;
1060
1061 ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
1062
1063 if (*length > transfer_limit)
1064 *length = transfer_limit;
1065
1066 head[1] = (unsigned int)(*length/256);
1067 head[2] = (unsigned int)(*length-256 * head[1]);
1068 if (u == NULL)
1069 {
1070 head[3] = 0x01;
1071 head[4] = 0x01;
1072 head[5] = 0x01;
1073 head[6] = 0x01;
1074 }
1075 else
1076 {
1077 head[3] = u[0];
1078 head[4] = u[1];
1079 head[5] = u[2];
1080 head[6] = u[3];
1081 }
1082
1083 SL_RET0(_("put_header"));
1084}
1085#endif
1086
1087/* ------------------------------------------
1088 *
1089 * version 2 client/server protocol
1090 *
1091 * ------------------------------------------
1092 *
1093 * header : flag size[2]
1094 *
1095 * payload: random_pad[8] protocol[4] size[4] payload[payload_size] padding
1096 *
1097 * full_size <= 8192; payload_size <= 8176 (511*16); msg_size <= 8128 (508*16)
1098 * (msg_size = payload_size - key_len = payload_size - 48)
1099 */
[27]1100
1101/*
1102 * only SH_V2_FULLSIZE is used, and only once
1103 */
1104#if 0
[1]1105#ifdef SH_WITH_SERVER
1106#define SH_V2_FULLSIZE 240
1107#define SH_V2_PAYLOAD 224
1108#define SH_V2_MESSAGE 176
1109#else
1110#define SH_V2_FULLSIZE 1024
1111#define SH_V2_PAYLOAD 1008
1112#define SH_V2_MESSAGE 960
1113#endif
[27]1114#endif
1115#define SH_V2_FULLSIZE 1024
[1]1116
1117#ifdef SH_ENCRYPT
1118#include "rijndael-api-fst.h"
1119#endif
1120
1121void sh_tools_show_header (unsigned char * head, char sign)
1122{
1123#define SH_IS_ASCII(c) (((c) & ~0x7f) == 0)
1124
1125
1126 int msg_size = (256 * (unsigned int)head[1] + (unsigned int)head[2]);
1127 char code[32];
1128 char * p = &code[0];
1129
1130 memset (code, ' ', 32); /* space */
1131
1132 if ((head[0] & SH_PROTO_SRP) != 0) { p[0]='S';p[1]='R';p[2]='P';}
1133 p += 4;
1134 if ((head[0] & SH_PROTO_MSG) != 0) { p[0]='M';p[1]='S';p[2]='G';}
1135 p += 4;
1136 if ((head[0] & SH_PROTO_BIG) != 0) { p[0]='B';p[1]='I';p[2]='G';}
1137 p += 4;
1138 if ((head[0] & SH_PROTO_END) != 0) { p[0]='E';p[1]='N';p[2]='D';}
1139 p += 4;
1140 if ((head[0] & SH_PROTO_ENC) != 0) { p[0]='E';p[1]='N';p[2]='C';}
1141 p += 4;
1142 if ((head[0] & SH_PROTO_EN2) != 0) { p[0]='E';p[1]='N';p[2]='2';}
1143 code[23] = '\0';
1144
1145 if (SH_IS_ASCII(head[3]) && isalpha(head[3]) &&
1146 SH_IS_ASCII(head[4]) && isalpha(head[4]) &&
1147 SH_IS_ASCII(head[5]) && isalpha(head[5]) &&
1148 SH_IS_ASCII(head[6]) && isalpha(head[6])) {
1149 fprintf(stderr, "%c %3o %s %5d %c %c %c %c\n", sign,
1150 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1151 } else {
1152 fprintf(stderr, "%c %3o %s %5d %2X %2X %2X %2X\n", sign,
1153 head[0], code, msg_size, head[3], head[4], head[5], head[6]);
1154 }
1155 return;
1156}
1157
1158#ifdef SH_ENCRYPT
1159/*
1160 * #define DEBUG_EN2
1161 *
1162 * ingest version 1 7-byte header and payload, return version2 header/payload
1163 * last 4 bytes of outgoing header are set to dummy value
1164 */
1165char * sh_tools_makePack (unsigned char * header,
[34]1166 char * payload, unsigned long payload_size,
[1]1167 keyInstance * keyInstE)
1168{
1169 UINT32 rpad[3];
1170 unsigned char head[16];
1171 double epad;
[34]1172 unsigned long i_epad = 0;
1173 unsigned long i_blk = payload_size / 16;
1174 unsigned long i_blkmax = SH_V2_FULLSIZE / 16;
1175 unsigned long pads = 0;
1176 size_t full_size;
[1]1177 char * full_ret;
1178
1179 char * p;
1180 RIJ_BYTE inBlock[B_SIZ];
1181 RIJ_BYTE outBlock[B_SIZ];
1182 int j;
1183 cipherInstance cipherInst;
1184 int err_num;
1185 int blkfac;
[34]1186 int oflow = 0;
[1]1187
1188 /*
1189 SL_REQUIRE (i_blk*16 == payload_size, _("payload_size % 16 != 0"));
1190 */
1191 if ((i_blk * 16) != payload_size) ++i_blk;
1192#ifdef DEBUG_EN2
1193 fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
1194#endif
1195 /* random_pad
1196 */
[137]1197 rpad[1] = taus_get ();
[1]1198 memcpy (head, &rpad[1], 4);
[137]1199 rpad[0] = taus_get ();
[1]1200 memcpy (&head[4], &rpad[0], 4);
[137]1201 rpad[2] = taus_get ();
[1]1202 memcpy (&head[8], &rpad[2], 4);
1203
1204 /* protocol
1205 */
1206 /* memcpy (&head[8], &header[3], 4); */
1207
1208 /* size (payload)
1209 */
1210 head[12] = header[1];
1211 head[13] = header[2];
1212 head[14] = '\0';
1213 head[15] = '\0';
1214
1215 if (i_blk < i_blkmax)
1216 {
1217 pads = i_blkmax - i_blk;
1218 /* memcpy((char *) &rpad[2], &head[12], 4); */
1219 epad = taus_get_double (&rpad);
1220#ifdef DEBUG_EN2
1221 fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
1222#endif
[34]1223 i_epad = (unsigned long) (pads * epad);
[1]1224#ifdef DEBUG_EN2
1225 fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
1226#endif
1227 }
1228
[34]1229 full_size = 16; /* head */
1230 if (sl_ok_muls(i_blk, 16) && sl_ok_adds(full_size, (i_blk*16)))
1231 full_size = full_size + (i_blk*16); /* payload */
1232 else
1233 oflow = 1;
1234 if (sl_ok_adds(full_size, (i_epad*16)))
1235 full_size = full_size + (i_epad*16); /* pad */
1236 else
1237 i_epad = 0;
[1]1238
[34]1239 if (oflow)
1240 {
1241 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1242 _("integer overflow"),
1243 _("sh_tools_makePack"));
1244 }
1245
[1]1246 full_ret = SH_ALLOC(full_size);
1247 memcpy(full_ret, head, 16);
[34]1248 if (payload != NULL && !oflow)
[1]1249 {
1250 memcpy(&full_ret[16], payload, payload_size);
1251 }
[34]1252 if ((i_blk*16) > payload_size && !oflow)
[1]1253 {
1254#ifdef DEBUG_EN2
1255 fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
1256#endif
1257 memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
1258 payload_size = i_blk * 16;
1259 }
1260 memset(&full_ret[16+payload_size], '\0', i_epad*16);
1261#ifdef DEBUG_EN2
1262 fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
1263#endif
1264
1265 /* rewrite header
1266 */
1267 header[1] = (unsigned int)(full_size/256);
1268 header[2] = (unsigned int)(full_size - (256 * header[1]));
1269 /* don't erase protocol from header
1270 memset(&header[3], '\0', 4);
1271 */
1272 p = full_ret; blkfac = full_size / 16;
1273
1274 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1275
1276 if (err_num < 0)
1277 {
[132]1278 char expbuf[SH_ERRBUF_SIZE];
[1]1279 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1280 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1281 _("sh_tools_makePack: cipherInit"));
1282 }
1283 for (j = 0; j < blkfac; ++j)
1284 {
1285 memcpy(inBlock, p, B_SIZ);
1286 err_num = blockEncrypt(&cipherInst, keyInstE,
1287 inBlock, 128 * BNUM, outBlock);
1288 if (err_num < 0)
1289 {
[132]1290 char expbuf[SH_ERRBUF_SIZE];
[1]1291 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1292 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1293 _("sh_tools_makePack: blockEncrypt"));
1294 }
1295 memcpy(p, outBlock, B_SIZ);
1296 p += B_SIZ;
1297 }
1298
1299 return full_ret;
1300}
1301
1302/* write a 7-byte header and return payload as expected by version 1
1303 * last 4 bytes of incoming header are dummy
1304 */
1305char * sh_tools_revertPack (unsigned char * header, char * message,
1306 keyInstance * keyInstD,
1307 unsigned long message_size)
1308{
1309 unsigned long msg_size;
1310 char * msg_ret;
1311
1312 char * p;
1313 RIJ_BYTE inBlock[B_SIZ];
1314 RIJ_BYTE outBlock[B_SIZ];
1315 int j;
1316 cipherInstance cipherInst;
1317 int err_num;
1318 int blkfac;
[132]1319 char expbuf[SH_ERRBUF_SIZE];
[1]1320
1321 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1322#ifdef DEBUG_EN2
1323 fprintf(stderr, "RECV <%lu>\n", msg_size);
1324#endif
1325 if (msg_size > message_size) {
1326 msg_size = message_size;
1327#ifdef DEBUG_EN2
1328 fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
1329#endif
1330 }
1331
1332 p = message; blkfac = msg_size / 16;
1333
1334 err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
1335
1336 if (err_num < 0)
1337 {
1338 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1339 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1340 _("sh_tools_revertPack: cipherInit"));
1341 }
1342 for (j = 0; j < blkfac; ++j)
1343 {
1344 memcpy(inBlock, p, B_SIZ);
1345 err_num = blockDecrypt(&cipherInst, keyInstD,
1346 inBlock, 128 * BNUM, outBlock);
1347 if (err_num < 0)
1348 {
1349 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
[132]1350 errorExplain(err_num, expbuf, sizeof(expbuf)),
[1]1351 _("sh_tools_revertPack: blockDecrypt"));
1352 }
1353 memcpy(p, outBlock, B_SIZ);
1354 p += B_SIZ;
1355 }
1356
1357 /* rewrite size in header
1358 */
1359 header[1] = message[12];
1360 header[2] = message[13];
1361 msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
1362
1363 if (msg_size > (message_size-16))
1364 {
1365 msg_size = message_size-16;
1366 header[1] = (unsigned int)(msg_size/256);
1367 header[2] = (unsigned int)(msg_size - (256 * header[1]));
1368#ifdef DEBUG_EN2
1369 fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
1370#endif
1371 }
1372#ifdef DEBUG_EN2
1373 fprintf(stderr, "REC2 <%lu>\n", msg_size);
1374#endif
1375 /* protocol
1376 */
1377 /* memcpy(&header[3], &message[8], 4); */
1378
1379 /* payload
1380 */
1381 msg_ret = SH_ALLOC(msg_size+1);
1382 if (msg_size > 0)
1383 {
1384 memcpy(msg_ret, &message[16], msg_size);
1385 }
1386 msg_ret[msg_size] = '\0';
1387#ifdef DEBUG_EN2
1388 fprintf(stderr, "REC3 <%lu>\n", msg_size);
1389#endif
1390 SH_FREE(message);
1391
1392 return msg_ret;
1393}
1394#endif
1395
1396int sh_tools_hash_add(char * key, char * buf, int buflen)
1397{
1398 char * theSig;
[133]1399 char sigbuf[KEYBUF_SIZE];
[1]1400
1401 SL_ENTER(_("sh_tools_hash_add"));
1402
[133]1403 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1404 sl_strlcat(buf, theSig, buflen + KEY_LEN + 1);
1405
1406 SL_RETURN((0), _("sh_tools_hash_add"));
1407}
1408
1409
1410/* return 0 (== FALSE) if no match, else 1 (== TRUE)
1411 */
1412int sh_tools_hash_vfy(char * key, char * buf, int buflen)
1413{
1414 char hash[KEY_LEN+1];
1415 register int i;
1416 char * theSig;
[133]1417 char sigbuf[KEYBUF_SIZE];
[1]1418
1419 SL_ENTER(_("sh_tools_hash_vfy"));
1420
[133]1421 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1422 sl_strlcpy(hash, theSig, KEY_LEN+1);
1423
1424 for (i = 0; i < KEY_LEN; ++i)
1425 {
1426 if (buf[buflen + i] != hash[i])
1427 SL_RETURN((0), _("sh_tools_hash_vfy"));
1428 }
1429
1430 SL_RETURN((1), _("sh_tools_hash_vfy"));
1431}
1432
1433/* ------------------------------------------ */
1434
1435#if defined (SH_WITH_SERVER)
1436
1437/* add a checksum to a buffer; put checksum in front
1438 */
1439char * hash_me (char * key, char * buf, int buflen)
1440{
1441 char hash[KEY_LEN+1];
[34]1442 char * temp = NULL;
[1]1443 register int i;
1444 int total = 0;
1445 char * theSig;
[133]1446 char sigbuf[KEYBUF_SIZE];
[1]1447
1448
1449 SL_ENTER(_("hash_me"));
1450
1451#ifdef DEBUG_EN2
1452 fprintf(stderr, "hash_me <%s> <%d>\n",
1453 (key == NULL) ? "NULL" : key, buflen);
1454#endif
1455 /* key = H(NSRV,NCLT,SK)
1456 */
1457 ASSERT_RET((key != NULL), _("key != NULL"), (NULL));
1458 ASSERT_RET((buflen >= 0), _("buflen >= 0"), (NULL));
1459
[133]1460 theSig = sh_util_siggen (key, buf, buflen, sigbuf, sizeof(sigbuf));
[1]1461 sl_strlcpy(hash, theSig, KEY_LEN+1);
1462
[34]1463 if (sl_ok_adds(buflen, KEY_LEN))
1464 {
1465 total = KEY_LEN + buflen;
1466 temp = SH_ALLOC (total);
[1]1467
[34]1468 for (i = 0; i < KEY_LEN; ++i)
1469 temp[i] = hash[i];
[1]1470
[34]1471 for (i = 0; i < buflen; ++i)
1472 temp[i+KEY_LEN] = buf[i];
1473 }
1474 else
1475 {
1476 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
1477 _("integer overflow"),
1478 _("hash_me"));
1479 temp = sh_util_strdup(buf);
1480 }
[1]1481 SL_RETURN(temp, _("hash_me"));
1482}
1483#endif
1484
[27]1485#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1486
1487/* verify the checksum of a buffer; checksum comes first
1488 */
1489int hash_check(char * key,
1490 char * buf, int buflen)
1491{
1492 char hash[KEY_LEN+1];
1493 register int i;
1494 char * theSig;
[133]1495 char sigbuf[KEYBUF_SIZE];
[1]1496
1497 SL_ENTER(_("hash_check"));
1498
1499#ifdef DEBUG_EN2
1500 fprintf(stderr, "hash_check <%s> <%d>\n",
1501 (key == NULL) ? "NULL" : key, buflen);
1502#endif
[133]1503 theSig = sh_util_siggen (key, &buf[KEY_LEN], buflen-KEY_LEN,
1504 sigbuf, sizeof(sigbuf));
[1]1505 sl_strlcpy(hash, theSig, KEY_LEN+1);
1506
1507 for (i = 0; i < KEY_LEN; ++i)
1508 {
1509 if (buf[i] != hash[i])
1510 SL_RETURN((-1), _("hash_check"));
1511 }
1512 SL_RETURN((0), _("hash_check"));
1513}
1514
1515#endif
1516
1517#if defined (SH_WITH_SERVER)
1518
1519char * get_client_conf_file (char * peer, unsigned long * length)
1520{
1521 char * ret;
[34]1522 int status;
[1]1523 struct stat buf;
1524 char * base;
[34]1525 size_t size;
[1]1526
1527 SL_ENTER(_("get_client_conf_file"));
1528
[34]1529 base = sh_util_strdup(DEFAULT_DATAROOT);
[1]1530
[34]1531 size = sl_strlen(base);
1532 if (sl_ok_adds(size, sl_strlen(peer)))
1533 size += sl_strlen(peer);
1534 if (sl_ok_adds(size, 6))
1535 size += 6;
[1]1536
1537 ret = SH_ALLOC(size);
1538 sl_strlcpy(ret, base, size);
1539 sl_strlcat(ret, _("/rc."), size);
1540 sl_strlcat(ret, peer, size);
1541
1542 status = retry_stat (FIL__, __LINE__, ret, &buf);
1543
1544 if (status == 0)
1545 goto lab_end;
1546 else
1547 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1548 (long) sh.effective.uid, ret);
1549
1550 sl_strlcpy(ret, base, size);
1551 sl_strlcat(ret, "/rc", size);
1552
1553 status = retry_stat (FIL__, __LINE__, ret, &buf);
1554
1555 if (status == 0)
1556 goto lab_end;
1557 else
1558 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
1559 (long) sh.effective.uid, ret);
1560
1561 SH_FREE(base);
[34]1562 SH_FREE(ret);
[1]1563 *length=0;
1564 SL_RETURN(NULL, _("get_client_conf_file"));
1565
1566 lab_end:
1567 if (buf.st_size > 0x7fffffff)
1568 {
1569 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1570 _("File too large"), _("get_client_conf_file"));
1571 SH_FREE(base);
1572 SL_RETURN(NULL, _("get_client_conf_file"));
1573 }
1574 *length = (unsigned long) buf.st_size;
1575 SH_FREE(base);
1576 SL_RETURN(ret, _("get_client_conf_file"));
1577}
1578
1579char * get_client_data_file (char * peer, unsigned long * length)
1580{
1581 char * ret;
[34]1582 int status;
[1]1583 struct stat buf;
1584
1585 char * base;
[34]1586 size_t size;
[1]1587
1588 SL_ENTER(_("get_client_data_file"));
1589
[34]1590 base = sh_util_strdup(DEFAULT_DATAROOT);
[1]1591
[34]1592 size = sl_strlen(base);
1593 if (sl_ok_adds(size, sl_strlen(peer)))
1594 size += sl_strlen(peer);
1595 if (sl_ok_adds(size, 8))
1596 size += 8;
[1]1597
1598 ret = SH_ALLOC(size);
1599 sl_strlcpy(ret, base, size);
1600 sl_strlcat(ret, _("/file."), size);
1601 sl_strlcat(ret, peer, size);
1602
1603 status = retry_stat (FIL__, __LINE__, ret, &buf);
1604
1605 if (status == 0)
1606 goto lab1_end;
1607 else
1608 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1609 (long) sh.effective.uid, ret);
1610
1611
1612 sl_strlcpy(ret, base, size);
1613 sl_strlcat(ret, _("/file"), size);
1614
1615 status = retry_stat (FIL__, __LINE__, ret, &buf);
1616
1617 if (status == 0)
1618 goto lab1_end;
1619 else
1620 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_ACCESS,
1621 (long) sh.effective.uid, ret);
1622
1623
1624 *length = 0;
1625 SH_FREE(base);
[34]1626 SH_FREE(ret);
[1]1627 SL_RETURN(NULL, _("get_client_data_file"));
1628
1629 lab1_end:
1630 if (buf.st_size > 0x7fffffff)
1631 {
1632 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
1633 _("File too large"), _("get_client_data_file"));
1634 SH_FREE(base);
1635 SL_RETURN(NULL, _("get_client_data_file"));
1636 }
1637 *length = (unsigned long) buf.st_size;
1638 SH_FREE(base);
1639 SL_RETURN(ret, _("get_client_data_file"));
1640
1641}
1642#endif
1643
[27]1644#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
[1]1645
1646/* --------- secure temporary file ------------ */
1647
1648SL_TICKET open_tmp ()
1649{
1650 SL_TICKET fd;
1651 UINT32 ticks;
1652 char * file;
1653 struct stat buf;
1654 int error;
1655 int status = BAD;
1656 char * my_tmp_dir;
[133]1657 char hashbuf[KEYBUF_SIZE];
[1]1658
1659 SL_ENTER(_("open_tmp"));
1660
1661#if defined(SH_TMPDIR)
[34]1662 my_tmp_dir = sh_util_strdup(SH_TMPDIR);
[1]1663#else
1664#if defined(SH_WITH_SERVER)
[34]1665 my_tmp_dir = sh_util_strdup(DEFAULT_LOGDIR);
[1]1666#else
[34]1667 my_tmp_dir = sh_util_strdup(sh.effective.home);
[1]1668#endif
1669#endif
1670
1671 if (0 != tf_trust_check (my_tmp_dir, SL_YESPRIV))
1672 {
1673 dlog(1, FIL__, __LINE__,
1674 _("The directory for temporary files: %s is untrusted, i.e. an\nuntrusted user owns or can write to some directory in the path.\n"),
1675 my_tmp_dir);
1676 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_TRUST,
1677 (long) sh.effective.uid,
1678 my_tmp_dir);
1679 SH_FREE(my_tmp_dir);
1680 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1681 }
1682
1683 do {
1684
1685 /* create random filename in effective users home directory
1686 */
[137]1687 ticks = taus_get ();
[1]1688 if (my_tmp_dir[0] == '/' && my_tmp_dir[1] == '\0')
1689 file = sh_util_strconcat (my_tmp_dir,
[133]1690 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1691 hashbuf, sizeof(hashbuf)),
[1]1692 NULL);
1693 else
1694 file = sh_util_strconcat (my_tmp_dir,
1695 "/",
[133]1696 sh_tiger_hash( (char *) &ticks, TIGER_DATA, 4,
1697 hashbuf, sizeof(hashbuf)),
[1]1698 NULL);
1699
1700 /* check whether it already exists (paranoia)
1701 */
1702 errno = 0;
1703 status = retry_lstat(FIL__, __LINE__, file, &buf);
1704 error = errno;
1705
1706 if ( (status < 0) && (error == ENOENT) ) /* file does not exist */
1707 status = GOOD;
1708 else if (status < 0) /* unexpected error condition */
1709 {
1710 SH_FREE (file);
1711 SH_FREE(my_tmp_dir);
[169]1712 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
1713 _("Error (lstat) while opening temporary file"), _("open_tmp"));
[1]1714 TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
1715 SL_RETURN((-1), _("open_tmp"));
1716 }
1717 else /* file exists */
1718 {
1719 status = BAD;
1720 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file exists already>\n")));
1721 }
1722
1723 if (status == GOOD)
1724 {
1725 if (0 == tf_trust_check (file, SL_YESPRIV))
1726 status = GOOD;
1727 else
1728 {
1729 status = BAD;
1730 TPT(( 0, FIL__, __LINE__, _("msg=<Temporary file untrusted>\n")));
1731 }
1732 }
1733
1734 if (status == BAD)
1735 SH_FREE (file);
1736
1737 } while (status == BAD);
1738
[248]1739 fd = sl_open_safe_rdwr (FIL__, __LINE__, file, SL_YESPRIV);
[1]1740 if (SL_ISERROR(fd))
1741 {
1742 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN,
1743 _("Error opening temporary file"), _("open_tmp"));
1744 TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"),
1745 fd, file));
1746 }
1747
1748
1749 SH_FREE (file);
1750 SH_FREE(my_tmp_dir);
1751
1752 if (!SL_ISERROR(fd)) {
1753 sl_unlink(fd);
1754 }
1755
1756 if (!SL_ISERROR(fd))
1757 SL_RETURN((fd), _("open_tmp"));
1758 else
1759 SL_RETURN((-1), _("open_tmp"));
1760}
1761
1762
1763int close_tmp (SL_TICKET fd)
1764{
1765 SL_ENTER(_("close_tmp"));
1766
1767 if (SL_ISERROR(sl_close (fd)))
1768 SL_RETURN((-1), _("close_tmp"));
1769 SL_RETURN((0), _("close_tmp"));
1770}
1771
1772int rewind_tmp (SL_TICKET fd)
1773{
1774 SL_ENTER(_("rewind_tmp"));
1775
1776 if (SL_ISERROR(sl_rewind (fd)))
1777 SL_RETURN((-1), _("rewind_tmp"));
1778 SL_RETURN((0), _("rewind_tmp"));
1779}
1780#endif
Note: See TracBrowser for help on using the repository browser.