source: trunk/src/sh_socket.c@ 265

Last change on this file since 265 was 265, checked in by katerina, 15 years ago

Enhance logfile monitoring (tickets #183, #184, #185).

File size: 28.2 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2003,2005 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/* define if you want debug info
23 * #define SH_DEBUG_SOCKET
24 */
[177]25#if defined(SH_WITH_SERVER) && defined(__linux__)
26#define _GNU_SOURCE
27#endif
[1]28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stddef.h>
32#include <string.h>
33
34#include "samhain.h"
35#include "sh_socket.h"
36#include "sh_error.h"
37#include "sh_unix.h"
38#include "sh_calls.h"
39
40#undef FIL__
41#define FIL__ _("sh_socket.c")
42
43#if defined (SH_WITH_CLIENT)
44
45#include <signal.h>
46
47void sh_socket_server_cmd(const char * srvcmd)
48{
49 SL_ENTER(_("sh_tools_server_cmd"));
50
51 if ((srvcmd == NULL) || (srvcmd[0] == '\0') || (sl_strlen(srvcmd) < 4))
52 {
53 SL_RET0(_("sh_socket_server_cmd"));
54 }
[200]55 if ((srvcmd[0] == 'S') && (srvcmd[1] == 'T') &&
56 (srvcmd[2] == 'O') && (srvcmd[3] == 'P'))
[1]57 {
58 TPT((0, FIL__, __LINE__, _("msg=<stop command from server>\n")));
59#ifdef SIGQUIT
60 raise(SIGQUIT);
61#else
[200]62 sig_terminate = 1;
63 ++sig_raised;
[1]64#endif
65 }
[200]66 else if ((srvcmd[0] == 'R') && (srvcmd[1] == 'E') &&
67 (srvcmd[2] == 'L') && (srvcmd[3] == 'O') &&
68 (srvcmd[4] == 'A') && (srvcmd[5] == 'D'))
[1]69 {
70 TPT((0, FIL__, __LINE__, _("msg=<reload command from server>\n")));
71#ifdef SIGHUP
72 raise(SIGHUP);
73#else
[200]74 sig_config_read_again = 1;
75 ++sig_raised;
[1]76#endif
77 }
[200]78 else if ((srvcmd[0] == 'S') && (srvcmd[1] == 'C') &&
79 (srvcmd[2] == 'A') && (srvcmd[3] == 'N'))
80 {
81 TPT((0, FIL__, __LINE__, _("msg=<scan command from server>\n")));
82 if (sh.flag.isdaemon == ON)
83 {
84#ifdef SIGTTOU
85 raise(SIGTTOU);
86#else
87 sig_force_check = 1;
88 ++sig_raised;
89#endif
90 }
91 else
92 {
93 sig_force_check = 1;
94 ++sig_raised;
95 }
96 }
[1]97 else
98 {
99 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
100 srvcmd,
101 _("sh_socket_server_cmd"));
102 }
103 SL_RET0(_("sh_socket_server_cmd"));
104}
105/* #if defined (SH_WITH_CLIENT)
106 */
107#endif
108
109#if defined(SH_WITH_SERVER)
110#include <errno.h>
111
112#include <sys/types.h>
113#include <sys/stat.h>
114
115#include <unistd.h>
116#include <fcntl.h>
117
118#include <time.h>
119
120#include <sys/socket.h>
121#include <sys/un.h>
122
123
124#ifdef HAVE_SYS_UIO_H
125#include <sys/uio.h>
126#endif
127#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED)
128#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
129#include <sys/param.h>
130#include <sys/ucred.h>
131#endif
132#endif
133
134
135int pf_unix_fd = -1;
136static char * sh_sockname = NULL;
[40]137static char sh_sockpass_real[SOCKPASS_MAX+1];
[1]138
139struct socket_cmd {
140 char cmd[SH_MAXMSGLEN];
141 char clt[SH_MAXMSGLEN];
142 char cti[81];
143 struct socket_cmd * next;
144};
145
146#if !defined(O_NONBLOCK)
147#if defined(O_NDELAY)
148#define O_NONBLOCK O_NDELAY
149#else
150#define O_NONBLOCK 0
151#endif
152#endif
153
154#if !defined(AF_FILE)
155#define AF_FILE AF_UNIX
156#endif
157
158static struct socket_cmd * cmdlist = NULL;
159static struct socket_cmd * runlist = NULL;
160
161static int sh_socket_flaguse = S_FALSE;
162static int sh_socket_flaguid = 0;
163
164#include "sh_utils.h"
165
166
167struct reload_cmd {
168 char clt[SH_MAXMSGLEN];
169 time_t cti;
170 struct reload_cmd * next;
171};
172static struct reload_cmd * reloadlist = NULL;
173
174void sh_socket_add2reload (const char * clt)
175{
176 struct reload_cmd * new = reloadlist;
177
178 while (new)
179 {
180 if (0 == sl_strcmp(new->clt, clt))
181 {
182 sl_strlcpy (new->clt, clt, SH_MAXMSGLEN);
183 new->cti = time(NULL);
184 return;
185 }
186 new = new->next;
187 }
188
189 new = SH_ALLOC(sizeof(struct reload_cmd));
190 sl_strlcpy (new->clt, clt, SH_MAXMSGLEN);
191 new->cti = time(NULL);
192
193 new->next = reloadlist;
194 reloadlist = new;
195
196 return;
197}
198
199#include "zAVLTree.h"
200#include "sh_html.h"
201#include "sh_tools.h"
202static void sh_socket_add2list (struct socket_cmd * in);
203
[170]204static void sh_socket_probe4reload (void)
[1]205{
206 struct reload_cmd * new;
207 struct socket_cmd cmd;
208
209 zAVLCursor avlcursor;
210 client_t * item;
211 extern zAVLTree * all_clients;
212
213 char * file;
214 unsigned long dummy;
215 struct stat buf;
216
217 for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
218 item = (client_t *) zAVLNext(&avlcursor))
219 {
220 if (item->status_now != CLT_INACTIVE)
221 {
222 file = get_client_conf_file (item->hostname, &dummy);
223
224 if (0 == stat (file, &buf))
225 {
226 new = reloadlist;
227 while (new)
228 {
229 if (0 == sl_strcmp(new->clt, item->hostname))
230 {
231 if (buf.st_mtime > new->cti)
232 {
233 /* reload */
234 sl_strlcpy(cmd.cmd, _("RELOAD"), SH_MAXMSGLEN);
235 sl_strlcpy(cmd.clt, item->hostname, SH_MAXMSGLEN);
236 sh_socket_add2list (&cmd);
237 }
238 break;
239 }
240 new = new->next;
241 }
242 }
243 }
244 }
245 return;
246}
247
[170]248char * sh_get_sockpass (void)
[1]249{
[50]250 size_t j = 0;
251
[40]252 while (skey->sh_sockpass[2*j] != '\0' && j < sizeof(sh_sockpass_real))
[1]253 {
254 sh_sockpass_real[j] = skey->sh_sockpass[2*j];
255 ++j;
256 }
257 sh_sockpass_real[j] = '\0';
[50]258
[1]259 return sh_sockpass_real;
260}
261
[170]262void sh_set_sockpass (void)
[1]263{
264 int j;
265 for (j = 0; j < 15; ++j)
266 {
267 sh_sockpass_real[j] = '\0';
268 }
269}
270
[22]271int sh_socket_use (const char * c)
[1]272{
273 return sh_util_flagval(c, &sh_socket_flaguse);
274}
275
276int sh_socket_remove ()
277{
278 int retval = 0;
279#ifdef S_ISSOCK
280 struct stat sbuf;
281#endif
282
283 SL_ENTER(_("sh_socket_remove"));
284
285 if (NULL == sh_sockname)
286 {
287 SL_RETURN((retval),_("sh_socket_remove"));
288 }
289
290 if (0 != tf_trust_check (DEFAULT_PIDDIR, SL_YESPRIV))
291 {
292 SL_RETURN((-1),_("sh_socket_remove"));
293 }
294
295 if ( (retry_lstat(FIL__, __LINE__, sh_sockname, &sbuf) == 0) &&
296 (sbuf.st_uid == getuid()))
297 {
298#ifdef S_ISSOCK
299 if (S_ISSOCK (sbuf.st_mode))
300 {
301 retval = retry_aud_unlink (FIL__, __LINE__, sh_sockname);
302 }
303#else
304 retval = retry_aud_unlink (FIL__, __LINE__, sh_sockname);
305#endif
306 }
307 SL_RETURN((retval),_("sh_socket_remove"));
308}
309
310#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
311
312#define NEED_PASSWORD_AUTH
313
314#endif
315
[22]316int sh_socket_uid (const char * c)
[1]317{
318 uid_t val = (uid_t) strtol (c, (char **)NULL, 10);
319 sh_socket_flaguid = val;
320#if defined(NEED_PASSWORD_AUTH)
321 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, errno, MSG_E_SUBGEN,
322 _("Config option SetSocketAllowUID not supported, use SetSocketPassword"),
323 _("sh_socket_uid"));
324#endif
325 return 0;
326}
327
[22]328int sh_socket_password (const char * c)
[1]329{
330#if defined(NEED_PASSWORD_AUTH)
331 int j, i;
332
333#define LCG(n) ((69069 * n) & 0xffffffffUL)
334
335 i = sl_strlen(c);
[40]336 if (i > SOCKPASS_MAX) {
[1]337 return -1;
338 }
[40]339 for (j = 0; j < (2*SOCKPASS_MAX+1); ++j)
[1]340 {
341 skey->sh_sockpass[j] = '\0';
342 }
343 for (j = 0; j < i; ++j)
344 {
345 skey->sh_sockpass[2*j] = c[j];
346 skey->sh_sockpass[(2*j)+1] = (LCG(c[j]) % 256);
347 }
348 return 0;
349#else
350 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, errno, MSG_E_SUBGEN,
351 _("Config option SetSocketPassword not supported, use SetSocketAllowUID"),
352 _("sh_socket_password"));
353 (void) c;
354 return 0;
355#endif
356}
357
358
359int sh_socket_open_int ()
360{
361 struct sockaddr_un name;
362 size_t size;
363 int flags;
364#if defined(SO_PASSCRED)
365 socklen_t optval = 1;
366#endif
367 struct stat buf;
[132]368 char errbuf[SH_ERRBUF_SIZE];
[1]369
370 SL_ENTER(_("sh_socket_open_int"));
371
372 if (sh_socket_flaguse == S_FALSE)
373 {
374 SL_RETURN(0, _("sh_socket_open_int"));
375 }
376
377 if (sh_sockname == NULL)
378 {
379 size = sl_strlen(DEFAULT_PIDDIR) + 1 + sl_strlen(SH_INSTALL_NAME) + 6;
[34]380 sh_sockname = SH_ALLOC(size); /* compile-time constant */
[1]381 sl_strlcpy(sh_sockname, DEFAULT_PIDDIR, size);
382 sl_strlcat(sh_sockname, "/", size);
383 sl_strlcat(sh_sockname, SH_INSTALL_NAME, size);
384 sl_strlcat(sh_sockname, _(".sock"), size);
385 }
386
[265]387 if (0 != sh_unix_check_piddir (sh_sockname))
388 {
389 SH_FREE(sh_sockname);
390 SL_RETURN((-1),_("sh_socket_open_int"));
391 }
[264]392
[1]393 pf_unix_fd = socket (PF_UNIX, SOCK_STREAM, 0);
394 if ((pf_unix_fd) < 0)
395 {
396 sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]397 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]398 _("sh_socket_open_int: socket"));
399 SL_RETURN( (-1), _("sh_socket_open_int"));
400 }
401
402 if (sizeof(name.sun_path) < (1 + sl_strlen(sh_sockname)))
403 {
[252]404 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]405 sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
406 _("PID dir path too long"),
407 _("sh_socket_open_int"));
408 SL_RETURN( (-1), _("sh_socket_open_int"));
409 }
410
411 name.sun_family = AF_FILE;
[22]412 sl_strlcpy (name.sun_path, sh_sockname, sizeof(name.sun_path));
[1]413
414 size = (offsetof (struct sockaddr_un, sun_path)
415 + strlen (name.sun_path) + 1);
416
417 flags = retry_lstat (FIL__, __LINE__, sh_sockname, &buf);
418
419 if (flags == 0)
420 {
421 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, -1, MSG_E_SUBGEN,
422 _("Socket exists, trying to unlink it"),
423 _("sh_socket_open_int"));
424 if (sh_socket_remove() < 0)
425 {
[252]426 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]427 sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
428 _("Unlink of socket failed, maybe path not trusted"),
429 _("sh_socket_open_int"));
430 SL_RETURN( (-1), _("sh_socket_open_int"));
431 }
432 }
433
434 if (bind ((pf_unix_fd), (struct sockaddr *) &name, size) < 0)
435 {
[252]436 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]437 sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]438 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]439 _("sh_socket_open_int: bind"));
440 SL_RETURN( (-1), _("sh_socket_open_int"));
441 }
442
443#ifdef SO_PASSCRED
444 if (0 != setsockopt(pf_unix_fd, SOL_SOCKET, SO_PASSCRED,
445 &optval, sizeof(optval)))
446 {
[252]447 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]448 sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]449 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]450 _("sh_socket_open_int: setsockopt"));
451 SL_RETURN( (-1), _("sh_socket_open_int"));
452 }
453#endif
454
455 flags = fcntl((pf_unix_fd), F_GETFL);
456 if (flags < 0)
457 {
[252]458 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]459 sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]460 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]461 _("sh_socket_open_int: fcntl1"));
462 SL_RETURN( (-1), _("sh_socket_open_int"));
463 }
464
465 flags = fcntl((pf_unix_fd), F_SETFL, flags|O_NONBLOCK);
466 if (flags < 0)
467 {
[252]468 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]469 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]470 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]471 _("sh_socket_open_int: fcntl2"));
472 SL_RETURN( (-1), _("sh_socket_open_int"));
473 }
474
475 if (0 != listen(pf_unix_fd, 5))
476 {
[252]477 sl_close_fd(FIL__, __LINE__, pf_unix_fd); pf_unix_fd = -1;
[1]478 sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]479 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]480 _("sh_socket_open_int: listen"));
481 SL_RETURN( (-1), _("sh_socket_open_int"));
482 }
483 SL_RETURN( (0), _("sh_socket_open_int"));
484}
485/* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
486/* #endif */
487
488/*
489#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
490static
491int sh_socket_read (struct socket_cmd * srvcmd)
492{
493 srvcmd->cmd[0] = '\0';
494 srvcmd->clt[0] = '\0';
495 return 0;
496}
497#else
498*/
499
500/*
501 * Parts of the socket authentication code is copied from PostgreSQL:
502 *
503 * PostgreSQL Database Management System
504 * (formerly known as Postgres, then as Postgres95)
505 *
506 * Portions Copyright (c) 1996-2001, The PostgreSQL Global Development Group
507 *
508 * Portions Copyright (c) 1994, The Regents of the University of California
509 *
510 * Permission to use, copy, modify, and distribute this software and its
511 * documentation for any purpose, without fee, and without a written agreement
512 * is hereby granted, provided that the above copyright notice and this
513 * paragraph and the following two paragraphs appear in all copies.
514 *
515 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
516 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
517 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
518 * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
519 * POSSIBILITY OF SUCH DAMAGE.
520 *
521 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
522 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
523 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
524 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
525 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
526 */
527static
528int sh_socket_read (struct socket_cmd * srvcmd)
529{
530 struct socket_cmd * list_cmd;
531 char message[SH_MAXMSG];
532 struct sockaddr_un name;
533 int size;
534 int nbytes;
535 int talkfd;
536 int retry = 0;
537
538 char * cmd = NULL;
539 char * clt = NULL;
540
541 int client_uid = -1;
[132]542 char errbuf[SH_ERRBUF_SIZE];
[1]543
544
545 struct msghdr msg;
546 struct iovec iov;
547
548#if defined(NEED_PASSWORD_AUTH)
549 char * eopw = NULL;
550 char * goodpassword = NULL;
551#endif
552
553#if defined(HAVE_GETPEEREID)
554 uid_t peer_uid;
555 gid_t peer_gid;
556#elif defined(SO_PEERCRED)
557 struct ucred cr;
[46]558#ifdef HAVE_SOCKLEN_T
559 socklen_t cl = sizeof(cr);
560#else
561 int cl = sizeof(cr);
562#endif
[1]563
564#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
565
566#ifdef HAVE_STRUCT_CMSGCRED
567 typedef struct cmsgcred Cred;
568#define CRED_UID cmcred_uid
569
570#elif HAVE_STRUCT_FCRED
571 typedef struct fcred Cred;
572#define CRED_UID fc_uid
573
574#elif HAVE_STRUCT_SOCKCRED
575 typedef struct sockcred Cred;
576#define CRED_UID sc_uid
577
578#endif
579 Cred *cred;
580
581 /* Compute size without padding */
582 char cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))];
583 /* for NetBSD */
584
585 /* Point to start of first structure */
586 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
587#endif
588
589 if (pf_unix_fd < 0)
590 {
591 return 0;
592 }
593
594 iov.iov_base = (char *) &message;
[40]595 iov.iov_len = sizeof(message);
[1]596
597 memset (&msg, 0, sizeof (msg));
598 msg.msg_iov = &iov;
599 msg.msg_iovlen = 1;
600
601#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
602#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
603 msg.msg_control = (char *) cmsg;
604 msg.msg_controllen = sizeof (cmsgmem);
605 memset (cmsg, 0, sizeof (cmsgmem));
606#endif
607#endif
608
609 /* the socket is non-blocking
610 * 'name' is the address of the sender socket
611 */
612 size = sizeof (name);
613 talkfd = retry_accept(FIL__, __LINE__,
614 pf_unix_fd, (struct sockaddr *) & name, &size);
615 if ((talkfd < 0) && (errno == EAGAIN))
616 {
617 return 0;
618 }
619 else if (talkfd < 0)
620 {
621 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]622 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]623 _("sh_socket_read: accept"));
624 return -1;
625 }
626
627
628#if defined(LOCAL_CREDS) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
629 /* Set the socket to receive credentials on the next message
630 */
631 {
632 int on = 1;
633 if (setsockopt (talkfd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
634 {
635 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]636 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]637 _("sh_socket_read: setsockopt"));
[252]638 sl_close_fd(FIL__, __LINE__, talkfd);
[1]639 return -1;
640 }
641 }
642#endif
643
644 do {
645 nbytes = recvmsg (talkfd, &msg, 0);
646 if ((nbytes < 0) && (errno != EAGAIN))
647 {
648 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]649 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]650 _("sh_socket_read: recvmsg"));
[252]651 sl_close_fd(FIL__, __LINE__, talkfd);
[1]652 return -1;
653 }
654 else if (nbytes < 0)
655 {
656 ++retry;
657 retry_msleep(0, 1);
658 }
659 } while ((nbytes < 0) && (retry < 3));
660
661#ifdef SH_DEBUG_SOCKET
662 fprintf(stderr, "%d bytes received\n", nbytes);
663#endif
664
[40]665 /* msg.msg_iov.iov_base, filled by recvmsg
666 */
667 message[sizeof(message)-1] = '\0';
[1]668
669 if (nbytes < 0)
670 {
671 if (errno == EAGAIN)
672 {
673 /* no data */
[252]674 sl_close_fd(FIL__, __LINE__, talkfd);
[1]675 return 0;
676 }
677 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]678 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]679 _("sh_socket_read: recvfrom"));
[252]680 sl_close_fd(FIL__, __LINE__, talkfd);
[1]681 return -1;
682 }
683
684#if defined(HAVE_GETPEEREID)
685 if (0 != getpeereid(talkfd, &peer_uid, &peer_gid))
686 {
687 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]688 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]689 _("sh_socket_read: getpeereid"));
[252]690 sl_close_fd(FIL__, __LINE__, talkfd);
[1]691 return -1;
692 }
693 client_uid = peer_uid;
694 cmd = message;
695#elif defined(SO_PEERCRED)
696 if (0 != getsockopt(talkfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
697 {
698 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]699 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]700 _("sh_socket_read: getsockopt"));
[252]701 sl_close_fd(FIL__, __LINE__, talkfd);
[1]702 return -1;
703 }
704 client_uid = cr.uid;
705 cmd = message;
706#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
707 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
708 {
709 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
710 _("Message from recvmsg() was not SCM_CREDS"),
711 _("sh_socket_read"));
[118]712
713 /* Check for file descriptors sent using SCM_RIGHTS, and
714 * close them. If MSG_CTRUNC is set, the buffer was too small,
715 * and no fds are duped.
716 */
717 if (msg.msg_controllen >= sizeof(struct cmsghdr) &&
718 (msg.msg_flags & MSG_CTRUNC) == 0)
719 {
720 unsigned int data_size;
721 unsigned int data_i;
722 int fdcount, fdmax;
723 struct cmsghdr * cmptr;
724 int fdsbuf[1 + (sizeof(cmsgmem)/sizeof(int))];
725
726 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
727 cmptr = CMSG_NXTHDR(&msg, cmptr))
728 {
729 if (cmptr->cmsg_len > sizeof (cmsgmem) ||
730 cmptr->cmsg_level != SOL_SOCKET ||
731 cmptr->cmsg_type != SCM_RIGHTS)
732 continue;
733
734 /* Crappy way of finding the data length.
735 * cmptr->cmsg_len includes both header and padding,
736 * how are you supposed to find the data length?
737 * cmptr->cmsg_len - ALIGN(sizeof(struct cmsghdr)) ?
738 */
739 data_size = 0;
740
741 for (data_i = 0; data_i < cmptr->cmsg_len; ++data_i)
742 {
743 if (CMSG_LEN(data_i) == cmptr->cmsg_len)
744 {
745 data_size = data_i;
746 break;
747 }
748 }
749 memcpy(fdsbuf, CMSG_DATA(cmptr), data_size);
750 fdmax = data_size / sizeof(int);
751 for (fdcount = 0; fdcount < fdmax; ++fdcount)
[252]752 (void) sl_close_fd(FIL__, __LINE__, fdsbuf[fdcount]);
[118]753 }
754 }
755
[252]756 sl_close_fd(FIL__, __LINE__, talkfd);
[1]757 return -1;
758 }
759 cred = (Cred *) CMSG_DATA (cmsg);
760 client_uid = cred->CRED_UID;
761 cmd = message;
762#elif defined(NEED_PASSWORD_AUTH)
763 goodpassword = sh_get_sockpass();
764 eopw = strchr(message, '@');
765 if (eopw)
766 *eopw = '\0';
[40]767 /*
768 * message is null-terminated and >> goodpassword
769 */
770 if (0 == strcmp(goodpassword, message) &&
771 strlen(goodpassword) < (sizeof(message)/2))
[1]772 {
773 client_uid = sh_socket_flaguid;
774 cmd = &message[strlen(goodpassword)+1];
775 sh_set_sockpass();
776 }
777 else
778 {
779 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
780 _("Bad password"),
781 _("sh_socket_read"));
782 sh_set_sockpass();
[252]783 sl_close_fd(FIL__, __LINE__, talkfd);
[1]784 return -1;
785 }
786#else
787 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
788 _("Socket credentials not supported on this OS"),
789 _("sh_socket_read"));
[252]790 sl_close_fd(FIL__, __LINE__, talkfd);
[1]791 return -1;
792#endif
793
794#ifdef SH_DEBUG_SOCKET
795 fprintf(stderr, "Peer uid=%d, required=%d\n",
796 client_uid, sh_socket_flaguid);
797#endif
798
799 if (client_uid != sh_socket_flaguid)
800 {
801 sh_error_handle((-1), FIL__, __LINE__, client_uid, MSG_E_SUBGEN,
802 _("client does not have required uid"),
803 _("sh_socket_read: getsockopt"));
[252]804 sl_close_fd(FIL__, __LINE__, talkfd);
[1]805 return -1;
806 }
807
808
809 /* Give a diagnostic message.
810 */
811#ifdef SH_DEBUG_SOCKET
812 fprintf (stderr, "Server: got message: %s\n", cmd);
813#endif
814
815 clt = strchr(cmd, ':');
816 if (clt != NULL)
817 {
818 *clt = '\0'; ++clt;
819 if (sl_strlen(cmd) >= SH_MAXMSGLEN)
820 {
821 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
822 _("Bad message format: command too long"),
823 _("sh_socket_read"));
[252]824 sl_close_fd(FIL__, __LINE__, talkfd);
[1]825 return -1;
826 }
827 else if (sl_strlen(clt) >= SH_MAXMSGLEN)
828 {
829 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
830 _("Bad message format: hostname too long"),
831 _("sh_socket_read"));
[252]832 sl_close_fd(FIL__, __LINE__, talkfd);
[1]833 return -1;
834 }
835 if (cmd[0] == 'L' && cmd[1] == 'I' &&
836 cmd[2] == 'S' && cmd[3] == 'T')
837 {
838 goto list_all;
839 }
840 else if (cmd[0] == 'P' && cmd[1] == 'R' &&
841 cmd[2] == 'O' && cmd[3] == 'B' && cmd[4] == 'E')
842 {
843 sh_socket_probe4reload();
844 cmd[0] = 'L'; cmd[1] = 'I'; cmd[2] = 'S'; cmd[3] = 'T';cmd[4] = '\0';
845 goto list_all;
846 }
847 sl_strlcpy (srvcmd->cmd, cmd, SH_MAXMSGLEN);
848 sl_strlcpy (srvcmd->clt, clt, SH_MAXMSGLEN);
849 --clt; *clt = ':';
850 }
851 else
852 {
853 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
854 _("Bad message format"),
855 _("sh_socket_read"));
[252]856 sl_close_fd(FIL__, __LINE__, talkfd);
[1]857 return -1;
858 }
859
860 /* Bounce the message back to the sender.
861 * 'name' is the receiver address; it has been been filled
862 * with the sender address in the recvfrom call
863 */
864#ifdef SH_DEBUG_SOCKET
865 fprintf (stderr, "Server: send message: %s to %s\n",
866 cmd, name.sun_path);
867#endif
868 /*
869 nbytes = sendto (pf_unix_fd, message, nbytes, 0,
870 (struct sockaddr *) & name, size);
871 */
872 nbytes = send (talkfd, cmd, strlen(cmd) + 1, 0);
[252]873 sl_close_fd(FIL__, __LINE__, talkfd);
[1]874 if (nbytes < 0)
875 {
876 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]877 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]878 _("sh_socket_read: send"));
879 return -1;
880 }
881#ifdef SH_DEBUG_SOCKET
882 fprintf (stderr, "Server: message is out\n");
883#endif
884 return nbytes;
885
886 list_all:
887#ifdef SH_DEBUG_SOCKET
888 fprintf (stderr, "Server: list all\n");
889#endif
890 if (cmd[4] == 'A' && cmd[5] == 'L' && cmd[6] == 'L')
891 {
892 list_cmd = runlist;
893 while (list_cmd)
894 {
[40]895 sl_snprintf(message, sizeof(message), _("SENT %8s %32s %s"),
[1]896 list_cmd->cmd, list_cmd->clt, list_cmd->cti);
897 /*
898 sl_strlcpy(message, _("DONE"), SH_MAXMSG);
899 sl_strlcat(message, " ", SH_MAXMSG);
900 sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
901 sl_strlcat(message, " ", SH_MAXMSG);
902 sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
903 sl_strlcat(message, " ", SH_MAXMSG);
904 sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
905 */
906 nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
907 if (nbytes < 0)
908 {
909 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]910 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]911 _("sh_socket_read: sendto"));
[252]912 sl_close_fd(FIL__, __LINE__, talkfd);
[1]913 return -1;
914 }
915 list_cmd = list_cmd->next;
916 }
917 }
918
919 list_cmd = cmdlist;
920 while (list_cmd)
921 {
[40]922 sl_snprintf(message, sizeof(message), _(">>>> %8s %32s %s"),
[1]923 list_cmd->cmd, list_cmd->clt, list_cmd->cti);
924 /*
925 sl_strlcpy(message, _(">>>>"), SH_MAXMSG);
926 sl_strlcat(message, " ", SH_MAXMSG);
927 sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
928 sl_strlcat(message, " ", SH_MAXMSG);
929 sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
930 sl_strlcat(message, " ", SH_MAXMSG);
931 sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
932 */
933 /*
934 nbytes = sendto (pf_unix_fd, message, sl_strlen(message) + 1, 0,
935 (struct sockaddr *) & name, size);
936 */
937 nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
938 if (nbytes < 0)
939 {
940 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
[132]941 sh_error_message (errno, errbuf, sizeof(errbuf)),
[1]942 _("sh_socket_read: sendto"));
[252]943 sl_close_fd(FIL__, __LINE__, talkfd);
[1]944 return -1;
945 }
946 list_cmd = list_cmd->next;
947 }
948
949 /*
950 nbytes = sendto (pf_unix_fd, _("END"), 4, 0,
951 (struct sockaddr *) & name, size);
952 */
953 nbytes = send (talkfd, _("END"), 4, 0);
[252]954 sl_close_fd(FIL__, __LINE__, talkfd);
[1]955 return 0;
956}
957/* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
958/* #endif */
959
960static void sh_socket_add2list (struct socket_cmd * in)
961{
962 struct socket_cmd * new;
963
964 new = SH_ALLOC(sizeof(struct socket_cmd));
[22]965 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
966 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
[132]967 (void) sh_unix_time(0, new->cti, sizeof(new->cti));
[1]968 new->next = cmdlist;
969 cmdlist = new;
970
971 return;
972}
973
974static void sh_socket_add2run (struct socket_cmd * in)
975{
976 struct socket_cmd * new = runlist;
977 char * client_name = in->clt;
978
979 while (new)
980 {
981 if (0 == sl_strcmp(new->clt, client_name))
982 {
[22]983 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
984 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
[132]985 (void) sh_unix_time(0, new->cti, sizeof(new->cti));
[1]986 return;
987 }
988 new = new->next;
989 }
990
991 new = SH_ALLOC(sizeof(struct socket_cmd));
[22]992 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
993 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
[132]994 (void) sh_unix_time(0, new->cti, sizeof(new->cti));
[1]995 new->next = runlist;
996 runlist = new;
997
998 return;
999}
1000
1001
1002
1003static void sh_socket_rm2list (const char * client_name)
1004{
1005 struct socket_cmd * old = cmdlist;
1006 struct socket_cmd * new = cmdlist;
1007
1008 while (new)
1009 {
1010 if (0 == sl_strcmp(new->clt, client_name))
1011 {
1012 if ((new == cmdlist) && (new->next == NULL))
1013 {
1014 cmdlist = NULL;
1015 SH_FREE(new);
1016 return;
1017 }
1018 else if (new == cmdlist)
1019 {
1020 cmdlist = new->next;
1021 SH_FREE(new);
1022 return;
1023 }
1024 else
1025 {
1026 old->next = new->next;
1027 SH_FREE(new);
1028 return;
1029 }
1030 }
1031 old = new;
1032 new = new->next;
1033 }
1034 return;
1035}
1036
1037/* poll the socket to gather input
1038 */
1039int sh_socket_poll()
1040{
1041 struct socket_cmd cmd;
1042 char cancel_cmd[SH_MAXMSGLEN];
1043
1044 /* struct pollfd sh_poll = { pf_unix_fd, POLLIN, 0 }; */
1045
1046 if (pf_unix_fd < 0)
1047 {
1048 return 0;
1049 }
1050
[40]1051 sl_strlcpy(cancel_cmd, _("CANCEL"), sizeof(cancel_cmd));
[1]1052
1053 while (sh_socket_read (&cmd) > 0)
1054 {
1055 if (0 == sl_strcmp(cmd.cmd, cancel_cmd))
1056 {
1057 sh_socket_rm2list (cmd.clt);
1058 }
1059 else
1060 {
1061 sh_socket_rm2list (cmd.clt);
1062 sh_socket_add2list (&cmd);
1063 }
1064 }
1065 return 0;
1066}
1067
1068/* return the command associated with client_name
1069 and remove the corresponding entry
1070 */
1071char * sh_socket_check(const char * client_name)
1072{
1073 struct socket_cmd * old = cmdlist;
1074 struct socket_cmd * new = cmdlist;
1075 static char out[SH_MAXMSGLEN];
1076
1077 while (new)
1078 {
1079 if (0 == sl_strcmp(new->clt, client_name))
1080 {
[40]1081 sl_strlcpy(out, new->cmd, sizeof(out));
[1]1082 sh_socket_add2run (new);
1083 sh_socket_rm2list (client_name);
1084 return out;
1085 }
1086 old = new;
1087 new = new->next;
1088 }
1089 return NULL;
1090}
1091
1092/* #if defined (SH_WITH_SERVER)
1093 */
1094#endif
1095
Note: See TracBrowser for help on using the repository browser.