Changeset 481 for trunk/src/sh_socket.c


Ignore:
Timestamp:
Jul 18, 2015, 5:06:52 PM (6 years ago)
Author:
katerina
Message:

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/sh_socket.c

    r421 r481  
    3333#include <string.h>
    3434
     35#if TIME_WITH_SYS_TIME
     36#include <sys/time.h>
     37#include <time.h>
     38#else
     39#if HAVE_SYS_TIME_H
     40#include <sys/time.h>
     41#else
     42#include <time.h>
     43#endif
     44#endif
     45
    3546#include "samhain.h"
    3647#include "sh_socket.h"
     
    3849#include "sh_unix.h"
    3950#include "sh_calls.h"
     51#include "sh_guid.h"
     52#include "sh_fifo.h"
     53#include "sh_utils.h"
    4054
    4155#undef  FIL__
     
    4660#include <signal.h>
    4761
     62typedef struct delta_tofetch {
     63  char            uuid[SH_UUID_BUF];
     64  time_t          last_time;
     65  unsigned int    count;
     66} SH_DELTA_DB;
     67
     68static SH_DELTA_DB * parse_entry(SH_DELTA_DB * db, const char * str)
     69{
     70  long last_time;
     71  unsigned int count;
     72  char buf[SH_UUID_BUF];
     73  int res = sscanf(str, _("%u:%ld:%36s"), &count, &last_time, buf);
     74  if (res == 3)
     75    {
     76      db->count = count;
     77      db->last_time  = (time_t) last_time;
     78      sl_strlcpy(db->uuid, buf, SH_UUID_BUF);
     79      return db;
     80    }
     81  return NULL;
     82}
     83
     84static char * unparse_entry(const SH_DELTA_DB * db, char * str, size_t len)
     85{
     86  int nbytes = sl_snprintf(str, len, _("%u:%ld:%s"),
     87                           db->count, (long) db->last_time, db->uuid);
     88  if (nbytes < 0 || nbytes >= (int) len)
     89    return NULL;
     90  return str;
     91}
     92
     93static SH_FIFO xfifo = SH_FIFO_INITIALIZER;
     94
     95int sh_socket_store_uuid(const char * cmd)
     96{
     97  char * p = sh_util_strdup(cmd);
     98  char * q = strchr(cmd, ':');
     99  char   entry[SH_BUFSIZE];
     100  SH_DELTA_DB db;
     101
     102  if (!q) { SH_FREE(p); return -1; }
     103
     104  ++q;
     105
     106  if (0 != sh_uuid_check(q)) { SH_FREE(p); return -1; }
     107
     108  db.count = 0;
     109  db.last_time = (time_t) 0;
     110  sl_strlcpy(db.uuid, q, SH_UUID_BUF);
     111  SH_FREE(p);
     112
     113  if (NULL != unparse_entry(&db, entry, sizeof(entry)))
     114    {
     115      sh_fifo_push(&xfifo, entry);
     116      return 0;
     117    }
     118  return -1;
     119}
     120
     121static unsigned int try_interval = 60;
     122static unsigned int try_max = 2;
     123
     124int set_delta_retry_interval(const char * str)
     125{
     126  long val = strtol (str, (char **)NULL, 10);
     127
     128  if (val < 0 || val > INT_MAX)
     129    return -1;
     130  try_interval = (unsigned int) val;
     131  return 0;
     132}
     133int set_delta_retry_count(const char * str)
     134{
     135  long val = strtol (str, (char **)NULL, 10);
     136
     137  if (val < 0 || val > INT_MAX)
     138    return -1;
     139  try_max = (unsigned int) val;
     140  return 0;
     141}
     142
     143char * sh_socket_get_uuid(int * errflag, unsigned int * count, time_t * last)
     144{
     145  char * entry = sh_fifo_pop(&xfifo);
     146  char * uuid = NULL;
     147
     148  if (entry)
     149    {
     150      SH_DELTA_DB db;
     151      time_t      now;
     152     
     153      if (NULL == parse_entry(&db, entry))
     154        {
     155          SH_FREE(entry);
     156          sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     157                          _("Bad entry in fifo"),
     158                          _("sh_socket_get_uuid"));
     159          *errflag = -1;
     160          return NULL;
     161        }
     162
     163      now = time(NULL);
     164
     165      if ( (db.count > 0) && ((unsigned long)(now - db.last_time) < try_interval) )
     166        {
     167          sh_fifo_push_tail(&xfifo, entry);
     168          SH_FREE(entry);
     169          *errflag = -1;
     170          return NULL;
     171        }
     172
     173      SH_FREE(entry);
     174      uuid   = sh_util_strdup(db.uuid);
     175      *count = db.count;
     176      *last  = db.last_time;
     177    }
     178
     179  *errflag = 0;
     180  return uuid;
     181}
     182
     183int sh_socket_return_uuid (const char * uuid, unsigned int count, time_t last)
     184{
     185  (void) last;
     186
     187  if (count < try_max)
     188    {
     189      char   entry[SH_BUFSIZE];
     190      SH_DELTA_DB db;
     191      time_t now = time(NULL);
     192
     193      db.count     = count + 1;
     194      db.last_time = now;
     195      sl_strlcpy(db.uuid, uuid, SH_UUID_BUF);
     196
     197      if (NULL != unparse_entry(&db, entry, sizeof(entry)))
     198        return sh_fifo_push_tail(&xfifo, entry); /* >0 for success */
     199    }
     200  return -1;
     201}
     202
    48203void sh_socket_server_cmd(const char * srvcmd)
    49204{
     
    54209      SL_RET0(_("sh_socket_server_cmd"));
    55210    }
    56   if ((srvcmd[0] == 'S') && (srvcmd[1] == 'T') &&
    57       (srvcmd[2] == 'O') && (srvcmd[3] == 'P'))
     211
     212  if (0 == strncmp(srvcmd, _("STOP"), 4))
    58213    {
    59214      TPT((0, FIL__, __LINE__, _("msg=<stop command from server>\n")));
     
    65220#endif
    66221    }
    67   else if ((srvcmd[0] == 'R') && (srvcmd[1] == 'E') &&
    68            (srvcmd[2] == 'L') && (srvcmd[3] == 'O') &&
    69            (srvcmd[4] == 'A') && (srvcmd[5] == 'D'))
     222
     223  else if (0 == strncmp(srvcmd, _("RELOAD"), 6))
    70224    {
    71225      TPT((0, FIL__, __LINE__, _("msg=<reload command from server>\n")));
     
    77231#endif
    78232    }
    79   else if ((srvcmd[0] == 'S') && (srvcmd[1] == 'C') &&
    80            (srvcmd[2] == 'A') && (srvcmd[3] == 'N'))
     233
     234  else if (0 == strncmp(srvcmd, _("DELTA:"), 6))
     235    {
     236      TPT((0, FIL__, __LINE__, _("msg=<delta load command from server>\n")));
     237
     238      if (sh_socket_store_uuid(srvcmd) == 0)
     239        {
     240          ++sh_load_delta_flag;
     241          ++sig_raised;
     242        }
     243    }
     244
     245  else if (0 == strncmp(srvcmd, _("SCAN"), 4))
    81246    {
    82247      TPT((0, FIL__, __LINE__, _("msg=<scan command from server>\n")));
    83       if (sh.flag.isdaemon == ON)
     248      if (sh.flag.isdaemon == S_TRUE)
    84249        {
    85250#ifdef SIGTTOU
     
    96261        }
    97262    }
     263
     264  /* Unknown command
     265   */
    98266  else
    99267    {
    100       sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
     268      sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
    101269                      srvcmd,
    102270                      _("sh_socket_server_cmd"));
     
    104272  SL_RET0(_("sh_socket_server_cmd"));
    105273}
    106 /* #if defined (SH_WITH_CLIENT)
    107  */
    108 #endif
     274#endif  /* #if defined (SH_WITH_CLIENT) */
    109275
    110276#if defined(SH_WITH_SERVER)
     
    225391  struct stat buf;
    226392
    227 #ifdef SH_DEBUG_SOCKET
    228   fprintf(stderr, "PROBE\n");
    229 #endif
    230 
    231393  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
    232394       item = (client_t *) zAVLNext(&avlcursor))
    233395    {
    234 #ifdef SH_DEBUG_SOCKET
    235       fprintf(stderr, "%s %d\n", item->hostname, (int)item->status_now);
    236 #endif
    237 
    238396      if (item->status_now != CLT_INACTIVE)
    239397        {
     
    242400          file = get_client_conf_file (item->hostname, &dummy);
    243401
    244 #ifdef SH_DEBUG_SOCKET
    245           fprintf(stderr, "%s\n", file);
    246 #endif
    247402          if (0 == stat (file, &buf))
    248403            {
     
    250405              while (new)
    251406                {
    252 #ifdef SH_DEBUG_SOCKET
    253                   fprintf(stderr, "%s <> %s\n", new->clt, item->hostname);
    254 #endif
    255407                  if (0 == sl_strcmp(new->clt, item->hostname))
    256408                    {
    257409                      flag = 1; /* Client is in list already */
    258410
    259 #ifdef SH_DEBUG_SOCKET
    260                       fprintf(stderr, "%lu <> %lu\n",
    261                               (unsigned long) buf.st_mtime,
    262                               (unsigned long)new->cti);
    263 #endif
    264411                      if (buf.st_mtime > new->cti)
    265412                        {
     
    368515
    369516#define NEED_PASSWORD_AUTH
    370 
    371517#endif
    372518
     
    540686  SL_RETURN( (0), _("sh_socket_open_int"));
    541687}
    542 /* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
    543 /* #endif */
    544 
    545 /*
    546 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
    547 static
    548 int sh_socket_read (struct socket_cmd * srvcmd)
    549 {
    550   srvcmd->cmd[0] = '\0';
    551   srvcmd->clt[0] = '\0';
    552   return 0;
    553 }
    554 #else
    555 */
     688
    556689
    557690/*
     
    582715 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    583716 */
    584 static
    585 int sh_socket_read (struct socket_cmd * srvcmd)
    586 {
    587   struct socket_cmd * list_cmd;
    588   char message[SH_MAXMSG];
    589   struct sockaddr_un name;
    590   ACCEPT_TYPE_ARG3 size = sizeof(name);
    591 
     717
     718static int receive_message(int talkfd, struct msghdr * msg, size_t message_size)
     719{
     720  unsigned int retry = 0;
    592721  int nbytes;
    593   int talkfd;
    594   int retry = 0;
    595 
    596   char * cmd = NULL;
    597   char * clt = NULL;
    598 
    599   int  client_uid = -1;
     722  char * message = msg->msg_iov->iov_base;
    600723  char errbuf[SH_ERRBUF_SIZE];
    601724
    602 
    603   struct msghdr msg;
    604   struct iovec iov;
    605 
    606 #if defined(NEED_PASSWORD_AUTH)
    607   char * eopw = NULL;
    608   char * goodpassword = NULL;
    609 #endif
    610 
    611 #if defined(HAVE_GETPEEREID)
    612   uid_t peer_uid;
    613   gid_t peer_gid;
    614 #elif defined(SO_PEERCRED)
    615   struct ucred cr;
    616 #ifdef HAVE_SOCKLEN_T
    617   socklen_t cl = sizeof(cr);
    618 #else
    619   int       cl = sizeof(cr);
    620 #endif
    621 
    622 #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
    623 
    624 #ifdef HAVE_STRUCT_CMSGCRED
    625   typedef struct cmsgcred Cred;
    626 #define CRED_UID cmcred_uid
    627 
    628 #elif HAVE_STRUCT_FCRED
    629   typedef struct fcred Cred;
    630 #define CRED_UID fc_uid
    631 
    632 #elif HAVE_STRUCT_SOCKCRED
    633   typedef struct sockcred Cred;
    634 #define CRED_UID sc_uid
    635 
    636 #endif
    637   Cred       *cred;
    638 
    639   /* Compute size without padding */
    640   char   cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))];   
    641   /* for NetBSD */
    642 
    643   /* Point to start of first structure */
    644   struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
    645 #endif
    646 
    647   if (pf_unix_fd  < 0)
    648     {
    649       return 0;
    650     }
    651 
    652   iov.iov_base = (char *) &message;
    653   iov.iov_len  = sizeof(message);
    654 
    655   memset (&msg, 0, sizeof (msg));
    656   msg.msg_iov = &iov;
    657   msg.msg_iovlen = 1;
    658 
    659 #if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
    660 #if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
    661   msg.msg_control = (char *) cmsg;
    662   msg.msg_controllen = sizeof (cmsgmem);
    663   memset (cmsg, 0, sizeof (cmsgmem));
    664 #endif
    665 #endif
    666 
    667   /* the socket is non-blocking
    668    * 'name' is the address of the sender socket
    669    */
    670725  do {
    671     talkfd = accept(pf_unix_fd, (struct sockaddr *) &name, &size);
    672   } while (talkfd < 0 && errno == EINTR);
    673 
    674   if ((talkfd < 0) && (errno == EAGAIN))
    675     {
    676       return 0;
    677     }
    678   else if (talkfd < 0)
    679     {
    680       sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    681                       sh_error_message (errno, errbuf, sizeof(errbuf)),
    682                       _("sh_socket_read: accept"));
    683       return -1;
    684     }
    685 
    686 
    687 #if defined(LOCAL_CREDS) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
    688   /* Set the socket to receive credentials on the next message
    689    */
    690   {
    691     int on = 1;
    692     if (setsockopt (talkfd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
    693       {
    694         sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    695                         sh_error_message (errno, errbuf, sizeof(errbuf)),
    696                         _("sh_socket_read: setsockopt"));
    697         sl_close_fd(FIL__, __LINE__, talkfd);
    698         return -1;
    699       }
    700   }
    701 #endif
    702 
    703   do {
    704     nbytes = recvmsg (talkfd, &msg, 0);
     726    nbytes = recvmsg (talkfd, msg, 0);
    705727    if ((nbytes < 0) && (errno != EAGAIN))
    706728      {
     
    718740  } while ((nbytes < 0) && (retry < 3));
    719741
    720 #ifdef SH_DEBUG_SOCKET
    721   fprintf(stderr, "%d bytes received\n", nbytes);
    722 #endif
    723 
    724742  /* msg.msg_iov.iov_base, filled by recvmsg
    725743   */
    726   message[sizeof(message)-1] = '\0';
     744  message[message_size-1] = '\0';
    727745
    728746  if (nbytes < 0)
     
    731749        {
    732750          /* no data */
     751          sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN,
     752                          sh_error_message (errno, errbuf, sizeof(errbuf)),
     753                          _("sh_socket_read: recvfrom"));
    733754          sl_close_fd(FIL__, __LINE__, talkfd);
    734755          return 0;
     
    740761      return -1;
    741762    }
     763  return 0;
     764}
    742765
    743766#if defined(HAVE_GETPEEREID)
     767
     768static int get_peer_uid(int talkfd)
     769{
     770  uid_t peer_uid;
     771  gid_t peer_gid;
     772  char errbuf[SH_ERRBUF_SIZE];
     773
    744774  if (0 != getpeereid(talkfd, &peer_uid, &peer_gid))
    745775    {
     
    750780      return -1;
    751781    }
    752   client_uid = peer_uid;
    753   cmd = message;
    754 #elif defined(SO_PEERCRED)
     782  return peer_uid;
     783}
     784
     785#elif defined(SO_PEERCRED)
     786
     787static int get_peer_uid(int talkfd)
     788{
     789  char errbuf[SH_ERRBUF_SIZE];
     790  struct ucred cr;
     791#ifdef HAVE_SOCKLEN_T
     792  socklen_t cl = sizeof(cr);
     793#else
     794  int       cl = sizeof(cr);
     795#endif
     796
    755797  if (0 != getsockopt(talkfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
    756798    {
     
    761803      return -1;
    762804    }
    763   client_uid = cr.uid;
    764   cmd = message;
    765 #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
    766   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
    767     {
    768       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
    769                       _("Message from recvmsg() was not SCM_CREDS"),
    770                       _("sh_socket_read"));
    771 
    772       /* Check for file descriptors sent using SCM_RIGHTS, and
    773        * close them. If MSG_CTRUNC is set, the buffer was too small,
    774        * and no fds are duped.
    775        */
    776       if (msg.msg_controllen >= sizeof(struct cmsghdr) &&
    777           (msg.msg_flags & MSG_CTRUNC) == 0)
    778         {
    779           unsigned int     data_size;
    780           unsigned int     data_i;
    781           int              fdcount, fdmax;
    782           struct cmsghdr * cmptr;
    783           int              fdsbuf[1 + (sizeof(cmsgmem)/sizeof(int))];
    784 
    785           for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
    786                cmptr = CMSG_NXTHDR(&msg, cmptr))
    787             {
    788               if (cmptr->cmsg_len > sizeof (cmsgmem) ||
    789                   cmptr->cmsg_level != SOL_SOCKET ||
    790                   cmptr->cmsg_type  != SCM_RIGHTS)
    791                 continue;
    792 
    793               /* Crappy way of finding the data length.
    794                * cmptr->cmsg_len includes both header and padding,
    795                * how are you supposed to find the data length?
    796                * cmptr->cmsg_len - ALIGN(sizeof(struct cmsghdr)) ?
    797                */
    798               data_size = 0;
    799 
    800               for (data_i = 0; data_i < cmptr->cmsg_len; ++data_i)
    801                 {
    802                   if (CMSG_LEN(data_i) == cmptr->cmsg_len)
    803                     {
    804                       data_size = data_i;
    805                       break;
    806                     }
    807                 }
    808               memcpy(fdsbuf, CMSG_DATA(cmptr), data_size);
    809               fdmax = data_size / sizeof(int);
    810               for (fdcount = 0; fdcount < fdmax; ++fdcount)
    811                 (void) sl_close_fd(FIL__, __LINE__, fdsbuf[fdcount]);
    812             }
    813         }
    814      
    815       sl_close_fd(FIL__, __LINE__, talkfd);
    816       return -1;
    817     }
    818   cred = (Cred *) CMSG_DATA (cmsg);
    819   client_uid = cred->CRED_UID;
    820   cmd = message;
    821 #elif defined(NEED_PASSWORD_AUTH)
     805  return cr.uid;
     806}
     807
     808#endif
     809
     810#if defined(NEED_PASSWORD_AUTH)
     811char * check_password(char * message, int * client_uid, int talkfd)
     812{
     813  char * cmd = NULL;
     814  char * eopw = NULL;
     815  char * goodpassword = NULL;
     816
    822817  goodpassword = sh_get_sockpass();
    823818  eopw = strchr(message, '@');
     
    830825      strlen(goodpassword) < (sizeof(message)/2))
    831826    {
    832       client_uid = sh_socket_flaguid;
     827      *client_uid = sh_socket_flaguid;
    833828      cmd = &message[strlen(goodpassword)+1];
    834829      sh_set_sockpass();
     
    841836      sh_set_sockpass();
    842837      sl_close_fd(FIL__, __LINE__, talkfd);
     838      return NULL;
     839    }
     840  return cmd;
     841}
     842#endif
     843
     844static int list_all (int talkfd, char * cmd);
     845static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd);
     846
     847static
     848int sh_socket_read (struct socket_cmd * srvcmd)
     849{
     850  char message[SH_MAXMSG];
     851  struct sockaddr_un name;
     852  ACCEPT_TYPE_ARG3 size = sizeof(name);
     853  int talkfd;
     854  char * cmd = NULL;
     855  int  client_uid = -1;
     856  char errbuf[SH_ERRBUF_SIZE];
     857  struct msghdr msg;
     858  struct iovec iov;
     859  int status;
     860
     861  if (pf_unix_fd  < 0)
     862    return 0;
     863
     864  iov.iov_base = (char *) &message;
     865  iov.iov_len  = sizeof(message);
     866
     867  memset (&msg, 0, sizeof (msg));
     868  msg.msg_iov = &iov;
     869  msg.msg_iovlen = 1;
     870
     871  /* the socket is non-blocking
     872   * 'name' is the address of the sender socket
     873   */
     874  do {
     875    talkfd = accept(pf_unix_fd, (struct sockaddr *) &name, &size);
     876  } while (talkfd < 0 && errno == EINTR);
     877
     878  if ((talkfd < 0) && (errno == EAGAIN))
     879    {
     880      return 0;
     881    }
     882  else if (talkfd < 0)
     883    {
     884      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
     885                      sh_error_message (errno, errbuf, sizeof(errbuf)),
     886                      _("sh_socket_read: accept"));
    843887      return -1;
    844888    }
     889
     890  if (receive_message(talkfd, &msg, sizeof(message)) < 0)
     891    return -1;
     892
     893  /* Authenticate request by peer uid or password.
     894   */
     895#if defined(HAVE_GETPEEREID)
     896  client_uid = get_peer_uid(talkfd);
     897  cmd = message;
     898
     899#elif defined(SO_PEERCRED)
     900  client_uid = get_peer_uid(talkfd);
     901  cmd = message;
     902
     903#elif defined(NEED_PASSWORD_AUTH)
     904  cmd = check_password(message, &client_uid, talkfd);
     905
    845906#else
    846907  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
     
    851912#endif
    852913
    853 #ifdef SH_DEBUG_SOCKET
    854   fprintf(stderr, "Peer uid=%d, required=%d\n",
    855           client_uid, sh_socket_flaguid);
    856 #endif
    857 
    858914  if (client_uid != sh_socket_flaguid)
    859915    {
     
    865921    }
    866922
    867 
    868   /* Give a diagnostic message.
    869    */
    870 #ifdef SH_DEBUG_SOCKET
    871   fprintf (stderr, "Server: got message: %s\n", cmd);
    872 #endif
    873 
    874   clt = strchr(cmd, ':');
     923  status = process_message(talkfd, cmd, srvcmd);
     924
     925  sl_close_fd(FIL__, __LINE__, talkfd);
     926  return status;
     927}
     928
     929static int check_valid_command(const char * str)
     930{
     931  unsigned int i = 0;
     932  char * commands[] = { N_("DELTA"),  N_("RELOAD"),  N_("STOP"), N_("SCAN"),
     933                        N_("CANCEL"), N_("LISTALL"), N_("LIST"), N_("PROBE"), NULL };
     934
     935  while (commands[i])
     936    {
     937      if (0 == strcmp(_(commands[i]), str))
     938        {
     939          return 0;
     940        }
     941      ++i;
     942    }
     943  return -1;
     944}
     945
     946static int send_reply (int fd, char * msg)
     947{
     948  int nbytes = send (fd, msg, strlen(msg) + 1, 0);
     949
     950  if (nbytes < 0)
     951    {
     952      char errbuf[SH_ERRBUF_SIZE];
     953      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
     954                      sh_error_message (errno, errbuf, sizeof(errbuf)),
     955                      _("send_reply"));
     956      return -1;
     957    }
     958
     959  return nbytes;
     960}
     961
     962static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd)
     963{
     964  int nbytes;
     965  char error_type[SH_ERRBUF_SIZE] = { '\0' };
     966  char * clt  = (cmd) ? strchr(cmd, ':') : NULL;
     967
     968  if (clt && 0 == strncmp(cmd, _("DELTA:"), 6))
     969    {
     970      /* DELTA:uuid:hostname
     971       */
     972      char * uuid = clt;
     973     
     974      *uuid = '\0'; ++uuid;
     975      clt = strchr(uuid, ':');
     976      if (clt) { *clt = '\0'; ++clt; }
     977     
     978      if (sh_uuid_check(uuid) < 0)
     979        {
     980          sl_strlcpy(error_type, _("!E:uuid-format:"), sizeof(error_type));
     981          sl_strlcat(error_type, uuid, sizeof(error_type));
     982          clt = NULL;
     983        }
     984     
     985      --uuid; *uuid = ':';
     986    }
     987  else if (clt && *clt == ':')
     988    {
     989      *clt = '\0'; ++clt;
     990      if (check_valid_command(cmd) < 0)
     991        {
     992          sl_strlcpy(error_type, _("!E:cmd-invalid:"), sizeof(error_type));
     993          sl_strlcat(error_type, cmd, sizeof(error_type));
     994          clt = NULL;
     995        }
     996    }
     997   
    875998  if (clt != NULL)
    876999    {
    877       *clt = '\0'; ++clt;
    8781000      if (sl_strlen(cmd) >= SH_MAXMSGLEN)
    8791001        {
    880 #ifdef SH_DEBUG_SOCKET
    881           fprintf (stderr, "Server: command too long: %s\n", cmd);
    882 #endif
    8831002          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    8841003                          _("Bad message format: command too long"),
    8851004                          _("sh_socket_read"));
    886           sl_close_fd(FIL__, __LINE__, talkfd);
     1005          sl_strlcpy(error_type, _("!E:cmd-toolong"), sizeof(error_type));
     1006          send_reply(talkfd, error_type);
    8871007          return -1;
    8881008        }
    8891009      else if (sl_strlen(clt) >= SH_MAXMSGLEN)
    8901010        {
    891 #ifdef SH_DEBUG_SOCKET
    892           fprintf (stderr, "Server: hostname too long: %s\n", clt);
    893 #endif
    8941011          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    8951012                          _("Bad message format: hostname too long"),
    8961013                          _("sh_socket_read"));
    897           sl_close_fd(FIL__, __LINE__, talkfd);
     1014          sl_strlcpy(error_type, _("!E:hostname-toolong"), sizeof(error_type));
     1015          send_reply(talkfd, error_type);
    8981016          return -1;
    8991017        }
    900       if (cmd[0] == 'L' && cmd[1] == 'I' &&
    901           cmd[2] == 'S' && cmd[3] == 'T')
    902         {
    903 #ifdef SH_DEBUG_SOCKET
    904           fprintf (stderr, "Server: list %s\n", clt);
    905 #endif
    906           goto list_all;
    907         }
    908       else if (cmd[0] == 'P' && cmd[1] == 'R' &&
    909           cmd[2] == 'O' && cmd[3] == 'B' && cmd[4] == 'E')
    910         {
    911 #ifdef SH_DEBUG_SOCKET
    912           fprintf (stderr, "Server: probe start %s\n", clt);
    913 #endif
     1018
     1019      if (0 == strncmp(cmd, _("LIST"), 4))
     1020        return list_all(talkfd, cmd);
     1021      else if (0 == strncmp(cmd, _("PROBE"), 4))
     1022        {
    9141023          sh_socket_probe4reload();
    915 #ifdef SH_DEBUG_SOCKET
    916           fprintf (stderr, "Server: probe done  %s\n", clt);
    917 #endif
    918           cmd[0] = 'L'; cmd[1] = 'I'; cmd[2] = 'S'; cmd[3] = 'T';cmd[4] = '\0';
    919           goto list_all;
    920         }
     1024          sl_strlcpy(cmd, _("LIST"), 5);
     1025          return list_all(talkfd, cmd);
     1026        }
     1027
    9211028      sl_strlcpy (srvcmd->cmd, cmd, SH_MAXMSGLEN);
    9221029      sl_strlcpy (srvcmd->clt, clt, SH_MAXMSGLEN);
     
    9251032  else
    9261033    {
    927 #ifdef SH_DEBUG_SOCKET
    928       fprintf (stderr, "Server: bad message\n");
    929 #endif
    9301034      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    9311035                      _("Bad message format"),
    9321036                      _("sh_socket_read"));
    933       sl_close_fd(FIL__, __LINE__, talkfd);
     1037      if (error_type[0] == '\0')
     1038        sl_strlcpy(error_type, _("!E:message-format"), sizeof(error_type));
     1039      send_reply(talkfd, error_type);
    9341040      return -1;
    9351041    }
    9361042
    9371043  /* Bounce the message back to the sender.
    938    * 'name' is the receiver address; it has been been filled
    939    *        with the sender address in the recvfrom call
    9401044   */
    941 #ifdef SH_DEBUG_SOCKET
    942   fprintf (stderr, "Server: send message: %s to %s\n",
    943            cmd, name.sun_path);
    944 #endif
    945   /*
    946   nbytes = sendto (pf_unix_fd, message, nbytes, 0,
    947                        (struct sockaddr *) & name, size);
    948   */
    949   nbytes = send (talkfd, cmd, strlen(cmd) + 1, 0);
    950   sl_close_fd(FIL__, __LINE__, talkfd);
    951   if (nbytes < 0)
    952     {
    953       sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
    954                       sh_error_message (errno, errbuf, sizeof(errbuf)),
    955                       _("sh_socket_read: send"));
    956       return -1;
    957     }
    958 #ifdef SH_DEBUG_SOCKET
    959   fprintf (stderr, "Server: message is out\n");
    960 #endif
     1045  nbytes = send_reply(talkfd, cmd);
     1046
    9611047  return nbytes;
    962 
    963  list_all:
    964 #ifdef SH_DEBUG_SOCKET
    965   fprintf (stderr, "Server: list all\n");
    966 #endif
    967   if (cmd[4] == 'A' && cmd[5] == 'L' && cmd[6] == 'L')
     1048}
     1049
     1050static int list_all (int talkfd, char * cmd)
     1051{
     1052  int nbytes;
     1053  struct socket_cmd * list_cmd;
     1054  char message[SH_MAXMSG];
     1055  char errbuf[SH_ERRBUF_SIZE];
     1056
     1057  if (0 == strncmp(cmd, _("LISTALL"), 7))
    9681058    {
    9691059      list_cmd = runlist;
    9701060      while (list_cmd)
    9711061        {
    972           sl_snprintf(message, sizeof(message), _("SENT  %8s  %32s  %s"),
     1062          sl_snprintf(message, sizeof(message), _("SENT  %42s  %32s  %s"),
    9731063                      list_cmd->cmd, list_cmd->clt, list_cmd->cti);
    974           /*
    975           sl_strlcpy(message,     _("DONE"), SH_MAXMSG);
    976           sl_strlcat(message,          "  ", SH_MAXMSG);
    977           sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
    978           sl_strlcat(message,          "  ", SH_MAXMSG);
    979           sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
    980           sl_strlcat(message,          "  ", SH_MAXMSG);
    981           sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
    982           */
     1064
    9831065          nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
    9841066          if (nbytes < 0)
     
    9871069                              sh_error_message (errno, errbuf, sizeof(errbuf)),
    9881070                              _("sh_socket_read: sendto"));
    989               sl_close_fd(FIL__, __LINE__, talkfd);
    9901071              return -1;
    9911072            }
     
    9971078  while (list_cmd)
    9981079    {
    999       sl_snprintf(message, sizeof(message), _(">>>>  %8s  %32s  %s"),
     1080      sl_snprintf(message, sizeof(message), _(">>>>  %42s  %32s  %s"),
    10001081                  list_cmd->cmd, list_cmd->clt, list_cmd->cti);
    1001       /*
    1002       sl_strlcpy(message,     _(">>>>"), SH_MAXMSG);
    1003       sl_strlcat(message,          "  ", SH_MAXMSG);
    1004       sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
    1005       sl_strlcat(message,          "  ", SH_MAXMSG);
    1006       sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
    1007       sl_strlcat(message,          "  ", SH_MAXMSG);
    1008       sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
    1009       */
    1010       /*
    1011       nbytes = sendto (pf_unix_fd, message, sl_strlen(message) + 1, 0,
    1012                        (struct sockaddr *) & name, size);
    1013       */
     1082
    10141083      nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
    10151084      if (nbytes < 0)
     
    10181087                          sh_error_message (errno, errbuf, sizeof(errbuf)),
    10191088                          _("sh_socket_read: sendto"));
    1020           sl_close_fd(FIL__, __LINE__, talkfd);
    10211089          return -1;
    10221090        }
     
    10241092    }
    10251093
    1026   /*
    1027   nbytes = sendto (pf_unix_fd, _("END"), 4, 0,
    1028                    (struct sockaddr *) & name, size);
    1029   */
    1030   /* nbytes = *//* never read */ send (talkfd, _("END"), 4, 0);
    1031   sl_close_fd(FIL__, __LINE__, talkfd);
     1094  send (talkfd, _("END"), 4, 0);
    10321095  return 0;
    10331096}
    1034 /* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
    1035 /* #endif */
    10361097
    10371098static void sh_socket_add2list (struct socket_cmd * in)
    10381099{
    1039   struct socket_cmd  * new;
    1040 
    1041   new = SH_ALLOC(sizeof(struct socket_cmd));
    1042   sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
    1043   sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
    1044 #ifdef SH_DEBUG_SOCKET
    1045   fprintf(stderr, "add2list: time set for %s\n", new->clt);
    1046 #endif
    1047   (void) sh_unix_time(0, new->cti, sizeof(new->cti));
    1048   new->next = cmdlist;
    1049   cmdlist   = new;
    1050 
    1051   return;
    1052 }
    1053 
    1054 static void sh_socket_add2run (struct socket_cmd * in)
    1055 {
    1056   struct socket_cmd  * new = runlist;
    1057   char * client_name       = in->clt;
     1100  struct socket_cmd  * new  = cmdlist;
     1101  struct socket_cmd  * last = cmdlist;
    10581102
    10591103  while (new)
    10601104    {
    1061       if (0 == sl_strcmp(new->clt, client_name))
    1062         {
    1063           sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
    1064           sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
    1065 #ifdef SH_DEBUG_SOCKET
    1066           fprintf(stderr, "add2run: time reset for %s\n", new->clt);
    1067 #endif
     1105      /* Only skip identical commands.
     1106       */
     1107      if (0 == sl_strcmp(new->clt,  in->clt) &&
     1108          0 == sl_strcmp(new->cmd,  in->cmd))
     1109        {
    10681110          (void) sh_unix_time(0, new->cti, sizeof(new->cti));
    10691111          return;
     
    10731115
    10741116  new = SH_ALLOC(sizeof(struct socket_cmd));
    1075   sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
    1076   sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
     1117  sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
     1118  sl_strlcpy (new->clt,  in->clt,  sizeof(new->clt));
     1119  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
     1120  new->next  = NULL;
     1121
     1122  if (last)
     1123    {
     1124      while (last->next) { last = last->next; }
     1125      last->next = new;
     1126    }
     1127  else
     1128    {
     1129      cmdlist = new;
     1130    }
     1131  return;
     1132}
     1133
     1134static void sh_socket_add2run (struct socket_cmd * in)
     1135{
     1136  struct socket_cmd  * new  = runlist;
     1137  struct socket_cmd  * last = runlist;
     1138
     1139  while (new)
     1140    {
     1141      /* Only skip identical commands. First 5 will
     1142       * make all 'DELTA' identical.
     1143       */
     1144      if (0 == sl_strcmp(new->clt,  in->clt) &&
     1145          0 == sl_strncmp(new->cmd,  in->cmd, 5))
     1146        {
     1147          sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
     1148          (void) sh_unix_time(0, new->cti, sizeof(new->cti));
     1149          return;
     1150        }
     1151      new = new->next;
     1152    }
     1153
     1154  new = SH_ALLOC(sizeof(struct socket_cmd));
     1155  sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
     1156  sl_strlcpy (new->clt,  in->clt,  sizeof(new->clt));
    10771157#ifdef SH_DEBUG_SOCKET
    10781158  fprintf(stderr, "add2run: time set for %s\n", new->clt);
    10791159#endif
    10801160  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
    1081   new->next = runlist;
    1082   runlist   = new;
    1083 
     1161  new->next  = NULL;
     1162
     1163  if (last)
     1164    {
     1165      while (last->next) { last = last->next; }
     1166      last->next = new;
     1167    }
     1168  else
     1169    {
     1170      runlist = new;
     1171    }
    10841172  return;
    10851173}
     
    10871175
    10881176
    1089 static void sh_socket_rm2list (const char * client_name)
     1177static void sh_socket_rm2list (const char * client_name, int remove_all)
    10901178{
    10911179  struct socket_cmd * old = cmdlist;
     
    10981186          if ((new == cmdlist) && (new->next == NULL))
    10991187            {
     1188              /* There is only one entry */
    11001189              cmdlist = NULL;
    11011190              SH_FREE(new);
     
    11041193          else if (new == cmdlist)
    11051194            {
     1195              /* first entry: new = old = cmdlist */
    11061196              cmdlist = new->next;
    11071197              SH_FREE(new);
    1108               return;
     1198              if (remove_all == S_FALSE)
     1199                return;
     1200              old = cmdlist;
     1201              new = cmdlist;
     1202              continue;
    11091203            }
    11101204          else
     
    11121206              old->next = new->next;
    11131207              SH_FREE(new);
    1114               return;
     1208              if (remove_all == S_FALSE)
     1209                return;
     1210              new = old;
    11151211            }
    11161212        }
     
    11311227
    11321228  if (pf_unix_fd  < 0)
    1133     {
    1134       return 0;
    1135     }
     1229    return 0;
    11361230
    11371231  sl_strlcpy(cancel_cmd, _("CANCEL"), sizeof(cancel_cmd));
     
    11401234    {
    11411235      if (0 == sl_strcmp(cmd.cmd, cancel_cmd))
    1142         {
    1143           sh_socket_rm2list  (cmd.clt);
    1144         }
     1236        sh_socket_rm2list  (cmd.clt, S_TRUE);
    11451237      else
    1146         {
    1147           sh_socket_rm2list  (cmd.clt);
    1148           sh_socket_add2list (&cmd);
    1149         }
     1238        sh_socket_add2list (&cmd);
    11501239    }
    11511240  return 0;
     
    11641253      if (0 == sl_strcmp(new->clt, client_name))
    11651254        {
    1166           sl_strlcpy(out, new->cmd, sizeof(out));
     1255          sl_strlcpy(out,  new->cmd, sizeof(out));
    11671256          sh_socket_add2run (new);
    1168           sh_socket_rm2list  (client_name);
     1257          sh_socket_rm2list (client_name, S_FALSE);
    11691258          return out;
    11701259        }
     
    11731262  return NULL;
    11741263}
    1175 
    11761264/* #if defined (SH_WITH_SERVER)
    11771265 */
    11781266#endif
    11791267
     1268
     1269#ifdef SH_CUTEST
     1270#include "CuTest.h"
     1271
     1272void Test_cmdlist (CuTest *tc) {
     1273
     1274#if defined (SH_WITH_SERVER)
     1275  struct socket_cmd cmd;
     1276  char * p;
     1277
     1278  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
     1279  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1280
     1281  sh_socket_add2list (&cmd);
     1282  p = sh_socket_check("one");
     1283  CuAssertPtrNotNull(tc, p);
     1284  CuAssertStrEquals(tc, "RELOAD", p);
     1285
     1286  p = sh_socket_check("one");
     1287  CuAssertPtrEquals(tc, NULL, p);
     1288
     1289  sh_socket_add2list (&cmd);
     1290  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
     1291  sh_socket_add2list (&cmd);
     1292
     1293  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
     1294  sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd));
     1295  sh_socket_add2list (&cmd);
     1296  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
     1297  sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd));
     1298  sh_socket_add2list (&cmd);
     1299
     1300  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
     1301  sl_strlcpy(cmd.cmd, "DELTA",   sizeof(cmd.cmd));
     1302  sh_socket_add2list (&cmd);
     1303
     1304  p = sh_socket_check("one");
     1305  CuAssertPtrNotNull(tc, p);
     1306  CuAssertStrEquals(tc, "RELOAD", p);
     1307
     1308  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
     1309  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1310  sh_socket_add2list (&cmd);
     1311  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
     1312  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1313  sh_socket_add2list (&cmd);
     1314
     1315  p = sh_socket_check("one");
     1316  CuAssertPtrNotNull(tc, p);
     1317  CuAssertStrEquals(tc, "STOP", p);
     1318  p = sh_socket_check("one");
     1319  CuAssertPtrNotNull(tc, p);
     1320  CuAssertStrEquals(tc, "DELTA", p);
     1321  p = sh_socket_check("one");
     1322  CuAssertPtrEquals(tc, NULL, p);
     1323
     1324  /* Test removal in correct order */
     1325  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
     1326  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1327  sh_socket_add2list (&cmd);
     1328  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
     1329  sh_socket_add2list (&cmd);
     1330  sl_strlcpy(cmd.cmd, "DELTA",  sizeof(cmd.cmd));
     1331  sh_socket_add2list (&cmd);
     1332  sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd));
     1333  sh_socket_add2list (&cmd);
     1334 
     1335  sh_socket_rm2list ("one", S_FALSE);
     1336
     1337  p = sh_socket_check("one");
     1338  CuAssertPtrNotNull(tc, p);
     1339  CuAssertStrEquals(tc, "STOP", p);
     1340
     1341  sh_socket_rm2list ("one", S_FALSE);
     1342 
     1343  p = sh_socket_check("one");
     1344  CuAssertPtrNotNull(tc, p);
     1345  CuAssertStrEquals(tc, "FOOBAR", p);
     1346
     1347  p = sh_socket_check("one");
     1348  CuAssertPtrEquals(tc, NULL, p);
     1349
     1350  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
     1351  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1352  sh_socket_add2list (&cmd);
     1353  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
     1354  sh_socket_add2list (&cmd);
     1355
     1356  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
     1357  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1358  sh_socket_add2list (&cmd);
     1359  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
     1360  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
     1361  sh_socket_add2list (&cmd);
     1362
     1363  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
     1364  sl_strlcpy(cmd.cmd, "DELTA",  sizeof(cmd.cmd));
     1365  sh_socket_add2list (&cmd);
     1366  sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd));
     1367  sh_socket_add2list (&cmd);
     1368
     1369  sh_socket_rm2list ("one", S_TRUE);
     1370  p = sh_socket_check("one");
     1371  CuAssertPtrEquals(tc, NULL, p);
     1372
     1373  p = sh_socket_check("two");
     1374  CuAssertPtrNotNull(tc, p);
     1375  CuAssertStrEquals(tc, "STOP", p);
     1376  p = sh_socket_check("two");
     1377  CuAssertPtrNotNull(tc, p);
     1378  CuAssertStrEquals(tc, "RELOAD", p);
     1379  p = sh_socket_check("two");
     1380  CuAssertPtrEquals(tc, NULL, p);
     1381
     1382  p = sh_socket_check("three");
     1383  CuAssertPtrNotNull(tc, p);
     1384  CuAssertStrEquals(tc, "STOP", p);
     1385  p = sh_socket_check("three");
     1386  CuAssertPtrNotNull(tc, p);
     1387  CuAssertStrEquals(tc, "RELOAD", p);
     1388  p = sh_socket_check("three");
     1389  CuAssertPtrEquals(tc, NULL, p);
     1390
     1391  p = sh_socket_check("four");
     1392  CuAssertPtrEquals(tc, NULL, p);
     1393#else
     1394  (void) tc;
     1395#endif
     1396}
     1397
     1398#endif  /* #ifdef SH_CUTEST */
     1399
     1400
     1401
Note: See TracChangeset for help on using the changeset viewer.