source: trunk/src/sh_tools.c@ 176

Last change on this file since 176 was 171, checked in by katerina, 16 years ago

Include dnmalloc (ticket #108) and fix bugs #106 (EINPROGRESS) and #107 (compressBound).

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