source: trunk/src/sh_tools.c@ 141

Last change on this file since 141 was 137, checked in by rainer, 17 years ago

Fix compile errors.

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