source: trunk/src/sh_socket.c@ 44

Last change on this file since 44 was 40, checked in by rainer, 18 years ago

Fix for tickets #13, #14, #15, #16, #17

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