source: trunk/src/sh_socket.c@ 47

Last change on this file since 47 was 46, checked in by rainer, 18 years ago

Fix x86_64 build failure with gcc 4.x (as well as some gcc 4.x warnings)

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#ifdef HAVE_SOCKLEN_T
525 socklen_t cl = sizeof(cr);
526#else
527 int cl = sizeof(cr);
528#endif
529
530#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
531
532#ifdef HAVE_STRUCT_CMSGCRED
533 typedef struct cmsgcred Cred;
534#define CRED_UID cmcred_uid
535
536#elif HAVE_STRUCT_FCRED
537 typedef struct fcred Cred;
538#define CRED_UID fc_uid
539
540#elif HAVE_STRUCT_SOCKCRED
541 typedef struct sockcred Cred;
542#define CRED_UID sc_uid
543
544#endif
545 Cred *cred;
546
547 /* Compute size without padding */
548 char cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))];
549 /* for NetBSD */
550
551 /* Point to start of first structure */
552 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
553#endif
554
555 if (pf_unix_fd < 0)
556 {
557 return 0;
558 }
559
560 iov.iov_base = (char *) &message;
561 iov.iov_len = sizeof(message);
562
563 memset (&msg, 0, sizeof (msg));
564 msg.msg_iov = &iov;
565 msg.msg_iovlen = 1;
566
567#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
568#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
569 msg.msg_control = (char *) cmsg;
570 msg.msg_controllen = sizeof (cmsgmem);
571 memset (cmsg, 0, sizeof (cmsgmem));
572#endif
573#endif
574
575 /* the socket is non-blocking
576 * 'name' is the address of the sender socket
577 */
578 size = sizeof (name);
579 talkfd = retry_accept(FIL__, __LINE__,
580 pf_unix_fd, (struct sockaddr *) & name, &size);
581 if ((talkfd < 0) && (errno == EAGAIN))
582 {
583 return 0;
584 }
585 else if (talkfd < 0)
586 {
587 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
588 sh_error_message (errno),
589 _("sh_socket_read: accept"));
590 return -1;
591 }
592
593
594#if defined(LOCAL_CREDS) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
595 /* Set the socket to receive credentials on the next message
596 */
597 {
598 int on = 1;
599 if (setsockopt (talkfd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
600 {
601 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
602 sh_error_message (errno),
603 _("sh_socket_read: setsockopt"));
604 close(talkfd);
605 return -1;
606 }
607 }
608#endif
609
610 do {
611 nbytes = recvmsg (talkfd, &msg, 0);
612 if ((nbytes < 0) && (errno != EAGAIN))
613 {
614 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
615 sh_error_message (errno),
616 _("sh_socket_read: recvmsg"));
617 close(talkfd);
618 return -1;
619 }
620 else if (nbytes < 0)
621 {
622 ++retry;
623 retry_msleep(0, 1);
624 }
625 } while ((nbytes < 0) && (retry < 3));
626
627#ifdef SH_DEBUG_SOCKET
628 fprintf(stderr, "%d bytes received\n", nbytes);
629#endif
630
631 /* msg.msg_iov.iov_base, filled by recvmsg
632 */
633 message[sizeof(message)-1] = '\0';
634
635 if (nbytes < 0)
636 {
637 if (errno == EAGAIN)
638 {
639 /* no data */
640 close(talkfd);
641 return 0;
642 }
643 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
644 sh_error_message (errno),
645 _("sh_socket_read: recvfrom"));
646 close(talkfd);
647 return -1;
648 }
649
650#if defined(HAVE_GETPEEREID)
651 if (0 != getpeereid(talkfd, &peer_uid, &peer_gid))
652 {
653 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
654 sh_error_message (errno),
655 _("sh_socket_read: getpeereid"));
656 close(talkfd);
657 return -1;
658 }
659 client_uid = peer_uid;
660 cmd = message;
661#elif defined(SO_PEERCRED)
662 if (0 != getsockopt(talkfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
663 {
664 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
665 sh_error_message (errno),
666 _("sh_socket_read: getsockopt"));
667 close(talkfd);
668 return -1;
669 }
670 client_uid = cr.uid;
671 cmd = message;
672#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
673 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
674 {
675 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
676 _("Message from recvmsg() was not SCM_CREDS"),
677 _("sh_socket_read"));
678 close(talkfd);
679 return -1;
680 }
681 cred = (Cred *) CMSG_DATA (cmsg);
682 client_uid = cred->CRED_UID;
683 cmd = message;
684#elif defined(NEED_PASSWORD_AUTH)
685 goodpassword = sh_get_sockpass();
686 eopw = strchr(message, '@');
687 if (eopw)
688 *eopw = '\0';
689 /*
690 * message is null-terminated and >> goodpassword
691 */
692 if (0 == strcmp(goodpassword, message) &&
693 strlen(goodpassword) < (sizeof(message)/2))
694 {
695 client_uid = sh_socket_flaguid;
696 cmd = &message[strlen(goodpassword)+1];
697 sh_set_sockpass();
698 }
699 else
700 {
701 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
702 _("Bad password"),
703 _("sh_socket_read"));
704 sh_set_sockpass();
705 close(talkfd);
706 return -1;
707 }
708#else
709 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
710 _("Socket credentials not supported on this OS"),
711 _("sh_socket_read"));
712 close(talkfd);
713 return -1;
714#endif
715
716#ifdef SH_DEBUG_SOCKET
717 fprintf(stderr, "Peer uid=%d, required=%d\n",
718 client_uid, sh_socket_flaguid);
719#endif
720
721 if (client_uid != sh_socket_flaguid)
722 {
723 sh_error_handle((-1), FIL__, __LINE__, client_uid, MSG_E_SUBGEN,
724 _("client does not have required uid"),
725 _("sh_socket_read: getsockopt"));
726 close(talkfd);
727 return -1;
728 }
729
730
731 /* Give a diagnostic message.
732 */
733#ifdef SH_DEBUG_SOCKET
734 fprintf (stderr, "Server: got message: %s\n", cmd);
735#endif
736
737 clt = strchr(cmd, ':');
738 if (clt != NULL)
739 {
740 *clt = '\0'; ++clt;
741 if (sl_strlen(cmd) >= SH_MAXMSGLEN)
742 {
743 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
744 _("Bad message format: command too long"),
745 _("sh_socket_read"));
746 close(talkfd);
747 return -1;
748 }
749 else if (sl_strlen(clt) >= SH_MAXMSGLEN)
750 {
751 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
752 _("Bad message format: hostname too long"),
753 _("sh_socket_read"));
754 close(talkfd);
755 return -1;
756 }
757 if (cmd[0] == 'L' && cmd[1] == 'I' &&
758 cmd[2] == 'S' && cmd[3] == 'T')
759 {
760 goto list_all;
761 }
762 else if (cmd[0] == 'P' && cmd[1] == 'R' &&
763 cmd[2] == 'O' && cmd[3] == 'B' && cmd[4] == 'E')
764 {
765 sh_socket_probe4reload();
766 cmd[0] = 'L'; cmd[1] = 'I'; cmd[2] = 'S'; cmd[3] = 'T';cmd[4] = '\0';
767 goto list_all;
768 }
769 sl_strlcpy (srvcmd->cmd, cmd, SH_MAXMSGLEN);
770 sl_strlcpy (srvcmd->clt, clt, SH_MAXMSGLEN);
771 --clt; *clt = ':';
772 }
773 else
774 {
775 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
776 _("Bad message format"),
777 _("sh_socket_read"));
778 close(talkfd);
779 return -1;
780 }
781
782 /* Bounce the message back to the sender.
783 * 'name' is the receiver address; it has been been filled
784 * with the sender address in the recvfrom call
785 */
786#ifdef SH_DEBUG_SOCKET
787 fprintf (stderr, "Server: send message: %s to %s\n",
788 cmd, name.sun_path);
789#endif
790 /*
791 nbytes = sendto (pf_unix_fd, message, nbytes, 0,
792 (struct sockaddr *) & name, size);
793 */
794 nbytes = send (talkfd, cmd, strlen(cmd) + 1, 0);
795 close(talkfd);
796 if (nbytes < 0)
797 {
798 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
799 sh_error_message (errno),
800 _("sh_socket_read: send"));
801 return -1;
802 }
803#ifdef SH_DEBUG_SOCKET
804 fprintf (stderr, "Server: message is out\n");
805#endif
806 return nbytes;
807
808 list_all:
809#ifdef SH_DEBUG_SOCKET
810 fprintf (stderr, "Server: list all\n");
811#endif
812 if (cmd[4] == 'A' && cmd[5] == 'L' && cmd[6] == 'L')
813 {
814 list_cmd = runlist;
815 while (list_cmd)
816 {
817 sl_snprintf(message, sizeof(message), _("SENT %8s %32s %s"),
818 list_cmd->cmd, list_cmd->clt, list_cmd->cti);
819 /*
820 sl_strlcpy(message, _("DONE"), SH_MAXMSG);
821 sl_strlcat(message, " ", SH_MAXMSG);
822 sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
823 sl_strlcat(message, " ", SH_MAXMSG);
824 sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
825 sl_strlcat(message, " ", SH_MAXMSG);
826 sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
827 */
828 nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
829 if (nbytes < 0)
830 {
831 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
832 sh_error_message (errno),
833 _("sh_socket_read: sendto"));
834 close(talkfd);
835 return -1;
836 }
837 list_cmd = list_cmd->next;
838 }
839 }
840
841 list_cmd = cmdlist;
842 while (list_cmd)
843 {
844 sl_snprintf(message, sizeof(message), _(">>>> %8s %32s %s"),
845 list_cmd->cmd, list_cmd->clt, list_cmd->cti);
846 /*
847 sl_strlcpy(message, _(">>>>"), SH_MAXMSG);
848 sl_strlcat(message, " ", SH_MAXMSG);
849 sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
850 sl_strlcat(message, " ", SH_MAXMSG);
851 sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
852 sl_strlcat(message, " ", SH_MAXMSG);
853 sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
854 */
855 /*
856 nbytes = sendto (pf_unix_fd, message, sl_strlen(message) + 1, 0,
857 (struct sockaddr *) & name, size);
858 */
859 nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
860 if (nbytes < 0)
861 {
862 sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
863 sh_error_message (errno),
864 _("sh_socket_read: sendto"));
865 close(talkfd);
866 return -1;
867 }
868 list_cmd = list_cmd->next;
869 }
870
871 /*
872 nbytes = sendto (pf_unix_fd, _("END"), 4, 0,
873 (struct sockaddr *) & name, size);
874 */
875 nbytes = send (talkfd, _("END"), 4, 0);
876 close(talkfd);
877 return 0;
878}
879/* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
880/* #endif */
881
882static void sh_socket_add2list (struct socket_cmd * in)
883{
884 struct socket_cmd * new;
885
886 new = SH_ALLOC(sizeof(struct socket_cmd));
887 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
888 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
889 sl_strlcpy (new->cti, sh_unix_time(0), sizeof(new->cti));
890 new->next = cmdlist;
891 cmdlist = new;
892
893 return;
894}
895
896static void sh_socket_add2run (struct socket_cmd * in)
897{
898 struct socket_cmd * new = runlist;
899 char * client_name = in->clt;
900
901 while (new)
902 {
903 if (0 == sl_strcmp(new->clt, client_name))
904 {
905 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
906 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
907 sl_strlcpy (new->cti, sh_unix_time(0), sizeof(new->cti));
908 return;
909 }
910 new = new->next;
911 }
912
913 new = SH_ALLOC(sizeof(struct socket_cmd));
914 sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
915 sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
916 sl_strlcpy (new->cti, sh_unix_time(0), sizeof(new->cti));
917 new->next = runlist;
918 runlist = new;
919
920 return;
921}
922
923
924
925static void sh_socket_rm2list (const char * client_name)
926{
927 struct socket_cmd * old = cmdlist;
928 struct socket_cmd * new = cmdlist;
929
930 while (new)
931 {
932 if (0 == sl_strcmp(new->clt, client_name))
933 {
934 if ((new == cmdlist) && (new->next == NULL))
935 {
936 cmdlist = NULL;
937 SH_FREE(new);
938 return;
939 }
940 else if (new == cmdlist)
941 {
942 cmdlist = new->next;
943 SH_FREE(new);
944 return;
945 }
946 else
947 {
948 old->next = new->next;
949 SH_FREE(new);
950 return;
951 }
952 }
953 old = new;
954 new = new->next;
955 }
956 return;
957}
958
959/* poll the socket to gather input
960 */
961int sh_socket_poll()
962{
963 struct socket_cmd cmd;
964 char cancel_cmd[SH_MAXMSGLEN];
965
966 /* struct pollfd sh_poll = { pf_unix_fd, POLLIN, 0 }; */
967
968 if (pf_unix_fd < 0)
969 {
970 return 0;
971 }
972
973 sl_strlcpy(cancel_cmd, _("CANCEL"), sizeof(cancel_cmd));
974
975 while (sh_socket_read (&cmd) > 0)
976 {
977 if (0 == sl_strcmp(cmd.cmd, cancel_cmd))
978 {
979 sh_socket_rm2list (cmd.clt);
980 }
981 else
982 {
983 sh_socket_rm2list (cmd.clt);
984 sh_socket_add2list (&cmd);
985 }
986 }
987 return 0;
988}
989
990/* return the command associated with client_name
991 and remove the corresponding entry
992 */
993char * sh_socket_check(const char * client_name)
994{
995 struct socket_cmd * old = cmdlist;
996 struct socket_cmd * new = cmdlist;
997 static char out[SH_MAXMSGLEN];
998
999 while (new)
1000 {
1001 if (0 == sl_strcmp(new->clt, client_name))
1002 {
1003 sl_strlcpy(out, new->cmd, sizeof(out));
1004 sh_socket_add2run (new);
1005 sh_socket_rm2list (client_name);
1006 return out;
1007 }
1008 old = new;
1009 new = new->next;
1010 }
1011 return NULL;
1012}
1013
1014/* #if defined (SH_WITH_SERVER)
1015 */
1016#endif
1017
Note: See TracBrowser for help on using the repository browser.