示例#1
0
文件: http.c 项目: ezotrank/monit-src
int check_http(Socket_T socket) {
        Port_T P;
        char host[STRLEN];
        char auth[STRLEN]= {0};
        const char *request = NULL;
        const char *hostheader = NULL;

        ASSERT(socket);

        P = socket_get_Port(socket);

        ASSERT(P);

        request = P->request ? P->request : "/";

        Util_getHTTPHostHeader(socket, host, STRLEN);
        hostheader = P->request_hostheader ? P->request_hostheader : host;

        if (socket_print(socket,
                         "GET %s HTTP/1.1\r\n"
                         "Host: %s\r\n"
                         "Accept: */*\r\n"
                         "User-Agent: %s/%s\r\n"
                         "%s\r\n",
                         request, hostheader, prog, VERSION,
                         get_auth_header(P, auth, STRLEN)) < 0) {
                socket_setError(socket, "HTTP: error sending data -- %s\n", STRERROR);
                return FALSE;
        }

        return check_request(socket, P);
}
示例#2
0
文件: http.c 项目: Happy-Ferret/Monit
int check_http(Socket_T socket) {
        Port_T P;
        char host[STRLEN];
        char auth[STRLEN] = {};
        const char *request = NULL;
        const char *hostheader = NULL;

        ASSERT(socket);

        P = socket_get_Port(socket);

        ASSERT(P);

        request = P->request ? P->request : "/";

        hostheader = _findHostHeaderIn(P->http_headers);
        hostheader = hostheader ? hostheader : P->request_hostheader
                                ? P->request_hostheader : Util_getHTTPHostHeader(socket, host, STRLEN); // Otherwise use deprecated request_hostheader or default host
        StringBuffer_T sb = StringBuffer_create(168);
        StringBuffer_append(sb,
                            "GET %s HTTP/1.1\r\n"
                            "Host: %s\r\n"
                            "Accept: */*\r\n"
                            "User-Agent: Monit/%s\r\n"
                            "%s",
                            request, hostheader, VERSION,
                            get_auth_header(P, auth, STRLEN));
        // Add headers if we have them
        if (P->http_headers) {
                for (list_t p = P->http_headers->head; p; p = p->next) {
                        if (Str_startsWith(p->e, "Host")) // Already set contrived above
                                continue;
                        StringBuffer_append(sb, "%s\r\n", p->e);
                }
        }
        StringBuffer_append(sb, "\r\n");
        int send_status = socket_write(socket, (void*)StringBuffer_toString(sb), StringBuffer_length(sb));
        StringBuffer_free(&sb);
        if (send_status < 0) {
                socket_setError(socket, "HTTP: error sending data -- %s", STRERROR);
                return FALSE;
        }

        return check_request(socket, P);
}
示例#3
0
/**
 * Extract the Scoreboard line from the mod_status response.
 * Count the active apache child processes, and those which are
 * in other states. If each percentage exceeds the corresponding
 * limit, then return FALSE.
 * @param s A socket
 * @param limit The maximum percentage of logging processes
 * @return TRUE if logging is OK otherwise FALSE
 */
static int check_apache_stat(Socket_T socket) {

  int scored = 0;
  int errors = 0;
  char line[READ_SIZE];
  char search_string[READ_SIZE + 1];

  int loglimit= 0;
  int closelimit= 0;
  int dnslimit= 0;
  int keepalivelimit= 0;
  int replylimit= 0;
  int requestlimit= 0;
  int startlimit= 0;
  int waitlimit= 0;
  int gracefullimit= 0;
  int cleanuplimit= 0;

  int no_logging = 0;
  int no_close = 0;
  int no_dns = 0;
  int no_keepalive = 0;
  int no_reply = 0;
  int no_request = 0;
  int no_start = 0;
  int no_wait = 0;
  int no_graceful = 0;
  int no_cleanup = 0;
  int active_servers = 0;
  char *p;
  Port_T myPort= (Port_T)socket_get_Port(socket);

  ASSERT(myPort);

  loglimit= myPort->ApacheStatus.loglimit;
  closelimit= myPort->ApacheStatus.closelimit;
  dnslimit= myPort->ApacheStatus.dnslimit;
  keepalivelimit= myPort->ApacheStatus.keepalivelimit;
  replylimit= myPort->ApacheStatus.replylimit;
  requestlimit= myPort->ApacheStatus.requestlimit;
  startlimit= myPort->ApacheStatus.startlimit;
  waitlimit= myPort->ApacheStatus.waitlimit;
  gracefullimit= myPort->ApacheStatus.gracefullimit;
  cleanuplimit= myPort->ApacheStatus.cleanuplimit;


  while(NULL != socket_readln(socket, line, READ_SIZE)) {
    if(Str_startsWith(line, "Scoreboard")) {
      if(1 != sscanf(line, "%*s%*[: ]%1024s", search_string)) {
       Str_chomp(line);
       socket_setError(socket, "APACHE-STATUS error: parsing Apache status response '%s'\n",
         line);
       return FALSE;
      } else {
        scored = 1;
      }
    }
  }

  DEBUG("Scoreboard: %s\n", search_string);

  /* Check that some scoreboard line was found, if not return an error */
  if(!scored){
    socket_setError(socket, "APACHE-STATUS error: no scoreboard line returned by Apache\n");
    return FALSE;
  }

  /* Total each of the status messages in the scoreboard */
  for(p = search_string ; *p ; p++){
    active_servers++;
    switch(*p){
    case 'S':
      no_start++;
      break;
    case 'R':
      no_request++;
      break;
    case 'W':
      no_reply++;
      break;
    case 'K':
      no_keepalive++;
      break;
    case 'D':
      no_dns++;
      break;
    case 'C':
      no_close++;
      break;
    case 'L':
      no_logging++;
      break;
    case 'G':
      no_graceful++;
      break;
    case 'I':
      no_cleanup++;
      break;
    case '_':
      no_wait++;
      break;
    case '.':
      active_servers--;
      break;
    }
  }

  if(active_servers <= 0){
    socket_setError(socket, "APACHE-STATUS warning: No idle server or threads found\n");
    /* This is not really an error, only a very bussy server */
    return TRUE;
  }

  /*
   * Conditions are only tested if the limit parameter is greater than zero.
   */

  if(loglimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.loglimitOP,
                            (100 * no_logging / active_servers), loglimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are logging\n", loglimit);
      errors++;
    }
  }

  if(startlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.startlimitOP,
                            (100 * no_start / active_servers), startlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are starting\n", startlimit);
      errors++;
    }
  }

  if(requestlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.requestlimitOP,
                    (100 * no_request / active_servers), requestlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are reading requests\n",
          requestlimit);
      errors++;
    }
  }

  if(replylimit > 0 ){
    if(Util_evalQExpression(myPort->ApacheStatus.replylimitOP,
                            (100 * no_reply / active_servers), replylimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are sending a reply\n", replylimit);
      errors++;
    }
  }

  if(keepalivelimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.keepalivelimitOP,
                    (100 * no_keepalive / active_servers), keepalivelimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are in keepalive\n", keepalivelimit);
      errors++;
    }
  }

  if(dnslimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.dnslimitOP,
                            (100 * no_dns / active_servers), dnslimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are waiting for DNS\n", dnslimit);
      errors++;
    }
  }

  if(closelimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.closelimitOP,
                            (100 * no_close / active_servers), closelimit)){
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are closing connections\n",
          closelimit);
      errors++;
    }
  }

  if(gracefullimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.gracefullimitOP,
                     (100 * no_graceful / active_servers), gracefullimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are finishing gracefully\n",
          gracefullimit);
      errors++;
    }
  }

  if(cleanuplimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.cleanuplimitOP,
                    (100 * no_cleanup / active_servers), cleanuplimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are in idle cleanup\n",
          cleanuplimit);
      errors++;
    }
  }

  if(waitlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.waitlimitOP,
                            (100 * no_wait / active_servers), waitlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are waiting for a connection\n",
          waitlimit);
      errors++;
    }
  }

  return (errors==0);

}
示例#4
0
static int parse_scoreboard(Socket_T socket, char *scoreboard) {
        int logging = 0, close = 0, dns = 0, keepalive = 0, reply = 0, request = 0, start = 0, wait = 0, graceful = 0, cleanup = 0, open = 0;
        for (char *state = scoreboard; *state; state++) {
                switch (*state) {
                        case 'S':
                                start++;
                                break;
                        case 'R':
                                request++;
                                break;
                        case 'W':
                                reply++;
                                break;
                        case 'K':
                                keepalive++;
                                break;
                        case 'D':
                                dns++;
                                break;
                        case 'C':
                                close++;
                                break;
                        case 'L':
                                logging++;
                                break;
                        case 'G':
                                graceful++;
                                break;
                        case 'I':
                                cleanup++;
                                break;
                        case '_':
                                wait++;
                                break;
                        case '.':
                                open++;
                                break;
                }
        }

        int total = logging + close + dns + keepalive + reply + request + start + wait + graceful + cleanup + open;
        if (! total)
                return TRUE; // Idle server

        int errors = 0;
        Port_T p = socket_get_Port(socket);
        ASSERT(p);

        //FIXME: socket_setError overrides previous => either stop on first error, or append errors and set error at the end (convert error buffer to stringbuffer?)
        if (p->ApacheStatus.loglimit > 0 && Util_evalQExpression(p->ApacheStatus.loglimitOP, (100 * logging / total), p->ApacheStatus.loglimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are logging", 100 * logging / total);
                errors++;
        }
        if (p->ApacheStatus.startlimit > 0 && Util_evalQExpression(p->ApacheStatus.startlimitOP, (100 * start / total), p->ApacheStatus.startlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are starting", 100 * start / total);
                errors++;
        }
        if (p->ApacheStatus.requestlimit > 0 && Util_evalQExpression(p->ApacheStatus.requestlimitOP, (100 * request / total), p->ApacheStatus.requestlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are reading requests", 100 * request / total);
                errors++;
        }
        if (p->ApacheStatus.replylimit > 0 && Util_evalQExpression(p->ApacheStatus.replylimitOP, (100 * reply / total), p->ApacheStatus.replylimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are sending a reply", 100 * reply / total);
                errors++;
        }
        if (p->ApacheStatus.keepalivelimit > 0 && Util_evalQExpression(p->ApacheStatus.keepalivelimitOP, (100 * keepalive / total), p->ApacheStatus.keepalivelimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are in keepalive", 100 * keepalive / total);
                errors++;
        }
        if (p->ApacheStatus.dnslimit > 0 && Util_evalQExpression(p->ApacheStatus.dnslimitOP, (100 * dns / total), p->ApacheStatus.dnslimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are waiting for DNS", 100 * dns / total);
                errors++;
        }
        if (p->ApacheStatus.closelimit > 0 && Util_evalQExpression(p->ApacheStatus.closelimitOP, (100 * close / total), p->ApacheStatus.closelimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are closing connections", 100 * close / total);
                errors++;
        }
        if (p->ApacheStatus.gracefullimit > 0 && Util_evalQExpression(p->ApacheStatus.gracefullimitOP, (100 * graceful / total), p->ApacheStatus.gracefullimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are finishing gracefully", 100 * graceful / total);
                errors++;
        }
        if (p->ApacheStatus.cleanuplimit > 0 && Util_evalQExpression(p->ApacheStatus.cleanuplimitOP, (100 * cleanup / total), p->ApacheStatus.cleanuplimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are in idle cleanup", 100 * cleanup / total);
                errors++;
        }
        if (p->ApacheStatus.waitlimit > 0 && Util_evalQExpression(p->ApacheStatus.waitlimitOP, (100 * wait / total), p->ApacheStatus.waitlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are waiting for a connection", 100 * wait / total);
                errors++;
        }

        return (errors == 0);
}
示例#5
0
/**
 *  Generic service test.
 *
 *  @file
 */
int check_generic(Socket_T socket) {
  Generic_T g = NULL;
  char *buf;
#ifdef HAVE_REGEX_H
  int regex_return;
#endif

  ASSERT(socket);

  if(socket_get_Port(socket))
    g = ((Port_T)(socket_get_Port(socket)))->generic;

  buf = CALLOC(sizeof(char), Run.expectbuffer + 1);

  while (g != NULL) {

    if (g->send != NULL) {

      /* Unescape any \0x00 escaped chars in g's send string
      to allow sending a string containing \0 bytes also */
      char *X = Str_dup(g->send);
      int l = Util_handle0Escapes(X);

      if(socket_write(socket, X, l) < 0) {
        socket_setError(socket, "GENERIC: error sending data -- %s", STRERROR);
        FREE(X);
        FREE(buf);
        return FALSE;
      } else
        DEBUG("GENERIC: successfully sent: '%s'\n", g->send);

      FREE(X);

    } else if (g->expect != NULL) {
      int n;
      /* Need read, not readln here */
      if((n = socket_read(socket, buf, Run.expectbuffer)) < 0) {
        socket_setError(socket, "GENERIC: error receiving data -- %s", STRERROR);
        FREE(buf);
        return FALSE;
      }
      buf[n] = 0;
      if (n > 0)
              _escapeZeroInExpectBuffer(buf, n);
#ifdef HAVE_REGEX_H
      regex_return = regexec(g->expect, buf, 0, NULL, 0);
      if (regex_return != 0) {
        char e[STRLEN];
        regerror(regex_return, g->expect, e, STRLEN);
        socket_setError(socket, "GENERIC: receiving unexpected data [%s] -- %s", Str_trunc(buf, STRLEN - 4), e);
        FREE(buf);
        return FALSE;
      } else
        DEBUG("GENERIC: successfully received: '%s'\n", Str_trunc(buf, STRLEN - 4));

#else
      /* w/o regex support */

      if (strncmp(buf, g->expect, strlen(g->expect)) != 0) {
        socket_setError(socket, "GENERIC: receiving unexpected data [%s]", Str_trunc(buf, STRLEN - 4));
        FREE(buf);
        return FALSE;
      } else
        DEBUG("GENERIC: successfully received: '%s'\n", Str_trunc(buf, STRLEN - 4));

#endif

    } else {
      /* This should not happen */
      socket_setError(socket, "GENERIC: unexpected strangeness");
      FREE(buf);
      return FALSE;
    }
    g = g->next;
  }

  FREE(buf);
  return TRUE;

}
示例#6
0
int check_sip(Socket_T socket) {
  int status;
  char buf[STRLEN];
  int port;
  char *transport;
  Port_T P;
  const char *request;
  const char *myip;
  char *rport= "";
  char *proto;

  ASSERT(socket);

  P= socket_get_Port(socket);
  ASSERT(P);
  request= P->request?P->request:"*****@*****.**";

  port = socket_get_local_port(socket);
  proto = socket_is_secure(socket) ? "sips" : "sip";  

  switch(socket_get_type(socket)) {
    case SOCK_DGRAM:
    {
      transport="UDP";
      rport=";rport";
      break;
    }
    case SOCK_STREAM:
    {
      transport="TCP";
      break;
    }
    default:
    {
      socket_setError(socket, "Unsupported socket type, only TCP and UDP are supported\n");
      return TRUE;
    }
  }

  myip= socket_get_local_host(socket);

  if(socket_print(socket,
    "OPTIONS %s:%s SIP/2.0\r\n"
    "Via: SIP/2.0/%s %s:%d;branch=z9hG4bKh%u%s\r\n"
    "Max-Forwards: %d\r\n"
    "To: <%s:%s>\r\n"
    "From: monit <%s:monit@%s>;tag=%d\r\n"
    "Call-ID: %u\r\n"
    "CSeq: 63104 OPTIONS\r\n"
    "Contact: <%s:%s:%d>\r\n"
    "Accept: application/sdp\r\n"
    "Content-Length: 0\r\n"
    "User-Agent: %s/%s\r\n\r\n",
    proto,            // protocol
    request,          // to
    transport,        // via transport udp|tcp
    myip,             // who its from
    port,             // our port
    random(),         // branch
    rport,            // rport option
    P->maxforward,    // maximum forwards
    proto,            // protocol
    request,          // to
    proto,            // protocol
    myip,             // from host
    random(),         // tag
    random(),         // call id
    proto,            // protocol
    myip,             // contact host
    port,             // contact port
    prog, VERSION     // user agent
    ) < 0) {
    socket_setError(socket, "SIP: error sending data -- %s\n", STRERROR);
    return FALSE;
  }

  if(! socket_readln(socket, buf, sizeof(buf))) {
    socket_setError(socket, "SIP: error receiving data -- %s\n", STRERROR);
    return FALSE;
  }

  Str_chomp(buf);

  DEBUG("Response from SIP server: %s\n", buf);

  if(! sscanf(buf, "%*s %d", &status)) { 
    socket_setError(socket, "SIP error: cannot parse SIP status in response: %s\n", buf);
    return FALSE;
  }

  if(status >= 400) {
    socket_setError(socket, "SIP error: Server returned status %d\n", status);
    return FALSE;
  }

  if(status >= 300 && status < 400) {
    socket_setError(socket, "SIP info: Server redirection. Returned status %d\n", status); 
    return FALSE;
  }

  if(status > 100 && status < 200) {
    socket_setError(socket, "SIP error: Provisional response . Returned status %d\n", status);
    return FALSE;
  }

  return TRUE;

}
示例#7
0
/**
 *  Simple RADIUS test.
 *
 *  We send a Status-Server packet, and expect an Access-Accept or Accounting-Response packet.
 *
 *
 */
int check_radius(Socket_T socket) {
        int i, length, left;
        int secret_len;
        Port_T P;
        md5_context_t ctx;
        char *secret;
        unsigned char *attr;
        unsigned char  digest[16];
        unsigned char  response[STRLEN];
        unsigned char  request[38] = {
                /* Status-Server */
                0x0c,

                /* Code, we always use zero */
                0x00,

                /* Packet length */
                0x00,
                0x26,

                /* Request Authenticator */
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,

                /* Message-Authenticator */
                0x50,

                /* Length */
                0x12,

                /* Contents of Message-Authenticator */
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00,
                0x00
        };

        ASSERT(socket);

        if (socket_get_type(socket) != SOCK_DGRAM) {
                socket_setError(socket, "RADIUS: unsupported socket type -- protocol test skipped\n");
                return TRUE;
        }

        P = socket_get_Port(socket);
        ASSERT(P);
  
        secret = P->request ? P->request : "testing123";
        secret_len = (int)strlen(secret);

        /* get 16 bytes of random data */
        for (i = 0; i < 16; i++)
                request[i + 4] = ((unsigned int)random()) & 0xff;

        /* sign the packet */
        Util_hmacMD5(request, sizeof(request), (unsigned char *)secret, secret_len, request + 22);

        if (socket_write(socket, (unsigned char *)request, sizeof(request)) < 0) {
                socket_setError(socket, "RADIUS: error sending query -- %s\n", STRERROR);
                return FALSE;
        }

        /* the response should have at least 20 bytes */
        if ((length = socket_read(socket, (unsigned char *)response, sizeof(response))) < 20) {
                socket_setError(socket, "RADIUS: error receiving response -- %s\n", STRERROR);
                return FALSE;
        }

        /* compare the response code (should be Access-Accept or Accounting-Response) */
        if ((response[0] != 2) && (response[0] != 5)) {
                socket_setError(socket, "RADIUS: Invalid reply code -- error occured\n");
                return FALSE;
        }

        /* compare the packet ID (it should be the same as in our request) */
        if (response[1] != 0x00) {
                socket_setError(socket, "RADIUS: ID mismatch\n");
                return FALSE;
        }

        /* check the length */
        if (response[2] != 0) {
                socket_setError(socket, "RADIUS: message is too long\n");
                return FALSE;
        }

        /* check length against packet data */
        if (response[3] != length) {
                socket_setError(socket, "RADIUS: message has invalid length\n");
                return FALSE;
        }

        /* validate that it is a well-formed packet */
        attr = response + 20;
        left = length - 20;
        while (left > 0) {
                if (left < 2) {
                        socket_setError(socket, "RADIUS: message is malformed\n");
                        return FALSE;
                }

                if (attr[1] < 2) {
                        socket_setError(socket, "RADIUS: message has invalid attribute length\n");
                        return FALSE;
                }

                if (attr[1] > left) {
                        socket_setError(socket, "RADIUS: message has attribute that is too long\n");
                        return FALSE;
                }

                /* validate Message-Authenticator, if found */
                if (attr[0] == 0x50) {
                        /* FIXME: validate it */
                }
                left -= attr[1];
        }

        /* save the reply authenticator, and copy the request authenticator over */
        memcpy(digest, response + 4, 16);
        memcpy(response + 4, request + 4, 16);

        md5_init(&ctx);
        md5_append(&ctx, (const md5_byte_t *)response, length);
        md5_append(&ctx, (const md5_byte_t *)secret, secret_len);
        md5_finish(&ctx, response + 4);

        if (memcmp(digest, response + 4, 16) != 0)
                socket_setError(socket, "RADIUS: message fails authentication\n");

        return TRUE;
}