source: trunk/src/sh_tools.c@ 71

Last change on this file since 71 was 34, checked in by rainer, 19 years ago

Code cleanup and minor fixes

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