source: trunk/src/sh_socket.c@ 6

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

Initial import

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