source: trunk/src/sh_tools.c@ 30

Last change on this file since 30 was 30, checked in by rainer, 18 years ago

Release candidate 3 for version 2.2.0

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