source: trunk/src/sh_tools.c@ 5

Last change on this file since 5 was 1, checked in by katerina, 19 years ago

Initial import

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