source: trunk/src/sh_tools.c@ 136

Last change on this file since 136 was 134, checked in by rainer, 17 years ago

More thread-safety changes.

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