Пример #1
0
/* GPattern only works with utf8 strings, if the input is not utf8, we risk
 * a crash
 */
static gboolean
log_matcher_glob_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len)
{
  LogMatcherGlob *self =  (LogMatcherGlob *) s;
  
  if (G_LIKELY((msg->flags & LF_UTF8) || g_utf8_validate(value, value_len, NULL)))
    {
      static gboolean warned = FALSE;
      gchar *buf;
      
      if (G_UNLIKELY(!warned && (msg->flags & LF_UTF8) == 0))
        {
          msg_warning("Input is valid utf8, but the log message is not tagged as such, this performs worse than enabling validate-utf8 flag on input", 
                      evt_tag_printf("value", "%.*s", (gint) value_len, value),
                      NULL);
          warned = TRUE;
        }
      APPEND_ZERO(buf, value, value_len);
      return g_pattern_match(self->pattern, value_len, buf, NULL);
    }
  else
    {
      msg_warning("Input is not valid utf8, glob match requires utf8 input, thus it never matches in this case", 
                  evt_tag_printf("value", "%.*s", (gint) value_len, value),
                  NULL);
    }
  return FALSE;
}
Пример #2
0
static gboolean
date_parser_process(LogParser *s,
                    LogMessage **pmsg,
                    const LogPathOptions *path_options,
                    const gchar *input,
                    gsize input_len)
{
  DateParser *self = (DateParser *) s;
  LogMessage *msg = log_msg_make_writable(pmsg, path_options);
  msg_trace("date-parser message processing started",
            evt_tag_str ("input", input),
            evt_tag_str ("format", self->date_format),
            evt_tag_printf("msg", "%p", *pmsg));

  /* this macro ensures zero termination by copying input to a
   * g_alloca()-d buffer if necessary. In most cases it's not though.
   */

  APPEND_ZERO(input, input, input_len);
  gboolean res = _convert_timestamp_to_logstamp(self,
                                                msg->timestamps[LM_TS_RECVD].ut_sec,
                                                &msg->timestamps[self->time_stamp],
                                                input);

  return res;
}
Пример #3
0
static gboolean
log_reader_handle_line(LogReader *self, const guchar *line, gint length, GSockAddr *saddr)
{
  LogMessage *m;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  gint i;
  
  msg_debug("Incoming log entry", 
            evt_tag_printf("line", "%.*s", length, line),
            NULL);
  /* use the current time to get the time zone offset */
  m = log_msg_new((gchar *) line, length,
                  saddr,
                  &self->options->parse_options);
  
  if (!m->saddr && self->peer_addr)
    {
      m->saddr = g_sockaddr_ref(self->peer_addr);
    }

  if (self->options->tags)
    {
      for (i = 0; i < self->options->tags->len; i++)
        {
          log_msg_set_tag_by_id(m, g_array_index(self->options->tags, LogTagId, i));
        }
    }

  log_msg_set_tag_by_id(m, self->super.options->source_group_tag);

  log_pipe_queue(&self->super.super, m, &path_options);
  return log_source_free_to_send(&self->super);
}
Пример #4
0
static gssize
log_transport_streams_read(LogTransport *self, void *buf, gsize buflen, GSockAddr **sa)
{
  struct strbuf ctl, data;
  struct log_ctl lc;
  gint flags;
  gint res;
  gchar tmpbuf[buflen];
  gint len;

  ctl.maxlen = ctl.len = sizeof(lc);
  ctl.buf = (char *) &lc;
  data.maxlen = buflen;
  data.len = 0;
  data.buf = tmpbuf;
  flags = 0;

  res = getmsg(self->fd, &ctl, &data, &flags);
  if (res == -1)
    return -1;
  else if ((res & (MORECTL+MOREDATA)) == 0)
    {
      len = g_snprintf(buf, buflen, "<%d>%.*s", lc.pri, data.len, data.buf);
      return MIN(len, buflen);
    }
  else
    {
      msg_error("Insufficient buffer space for retrieving STREAMS log message",
                evt_tag_printf("res", "%x", res));
    }
  return 0;
}
Пример #5
0
static gint
afinet_lookup_service_and_proto(const gchar *service, const gchar *proto)
{
  gchar *end;
  gint port;

  /* check if service is numeric */
  port = strtol(service, &end, 10);
  if ((*end != 0))
    {
      struct servent *se;

      /* service is not numeric, check if it's a service in /etc/services */
      se = getservbyname(service, proto);
      if (se)
        {
          port = ntohs(se->s_port);
        }
      else
        {
          msg_error("Error finding port number, falling back to default",
                    evt_tag_printf("service", "%s/%s", proto, service),
                    NULL);
          return 0;
        }
    }
  return port;
}
Пример #6
0
/* Read zic-coded 64-bit integer from file */
static gint64
readcoded64(unsigned char **input, gint64 minv, gint64 maxv)
{
    unsigned char buf[8]; /* must be UNSIGNED */
    gint64 val = 0;
    gint32 i = 0;
    gint32 shift = 0;

    memcpy (buf, *input, sizeof(buf));
    *input += 8;

    for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
        val |= (gint64)buf[i] << shift;

    if (val < minv || val > maxv)
    {
        msg_error("Error while processing the time zone file",
                  evt_tag_str("message", "Coded value out-of-range"),
                  evt_tag_int("value", val),
                  evt_tag_printf("expected", "[%"G_GINT64_FORMAT", %"G_GINT64_FORMAT"]", minv, maxv),
                  NULL);
        g_assert_not_reached();
    }
    return val;
}
Пример #7
0
static void 
log_rewrite_rule_call_item(gpointer item, gpointer user_data)
{
  LogRewrite *r = (LogRewrite *) item;
  LogMessage *msg = (LogMessage *) user_data;
  gssize length;
  const gchar *value;

  if (r->condition && !filter_expr_eval(r->condition, msg))
    {
      msg_debug("Rewrite condition unmatched, skipping rewrite",
                evt_tag_str("value", log_msg_get_value_name(r->value_handle, NULL)),
                NULL);
      return;
    }
  r->process(r, msg);
  if (G_UNLIKELY(debug_flag))
    {
      value = log_msg_get_value(msg, r->value_handle, &length);
      msg_debug("Rewrite expression evaluation result",
                evt_tag_str("value", log_msg_get_value_name(r->value_handle, NULL)),
                evt_tag_printf("new_value", "%.*s", (gint) length, value),
                NULL);
    }
}
Пример #8
0
static gboolean
maxminddb_parser_process(LogParser *s, LogMessage **pmsg,
                         const LogPathOptions *path_options,
                         const gchar *input, gsize input_len)
{
  GeoIPParser *self = (GeoIPParser *) s;
  LogMessage *msg = log_msg_make_writable(pmsg, path_options);
  msg_trace("geoip2-parser message processing started",
            evt_tag_str ("input", input),
            evt_tag_str ("prefix", self->prefix),
            evt_tag_printf("msg", "%p", *pmsg));

  MMDB_entry_data_list_s *entry_data_list;
  if (!_mmdb_load_entry_data_list(self, input, &entry_data_list))
    return TRUE;

  GArray *path = g_array_new(TRUE, FALSE, sizeof(gchar *));
  g_array_append_val(path, self->prefix);

  gint status;
  dump_geodata_into_msg(msg, entry_data_list, path, &status);

  MMDB_free_entry_data_list(entry_data_list);
  g_array_free(path, TRUE);

  return TRUE;
}
Пример #9
0
static void
_map_key_value_pairs_to_syslog_macros(LogMessage *msg, gchar *key, gchar *value, gssize value_len)
{
    if (strcmp(key, "MESSAGE") == 0)
    {
        log_msg_set_value(msg, LM_V_MESSAGE, value, value_len);
        msg_debug("Incoming log entry from journal",
                  evt_tag_printf("message", "%.*s", (int)value_len, value));
    }
    else if (strcmp(key, "_HOSTNAME") == 0)
    {
        log_msg_set_value(msg, LM_V_HOST, value, value_len);
    }
    else if (strcmp(key, "_PID") == 0)
    {
        log_msg_set_value(msg, LM_V_PID, value, value_len);
    }
    else if (strcmp(key, "SYSLOG_FACILITY") == 0)
    {
        msg->pri = (msg->pri & 7) | atoi(value) << 3;
    }
    else if (strcmp(key, "PRIORITY") == 0)
    {
        msg->pri = (msg->pri & ~7) | atoi(value);
    }
}
Пример #10
0
gint
tls_lookup_options(GList *options)
{
  gint ret=TSO_NONE;
  GList *l;
  for (l=options; l != NULL; l=l->next)
    {
      msg_debug("ssl-option", evt_tag_str("opt", l->data), NULL);
      if (strcasecmp(l->data, "no-sslv2") == 0 || strcasecmp(l->data, "no_sslv2") == 0)
        ret|=TSO_NOSSLv2;
      else if (strcasecmp(l->data, "no-sslv3") == 0 || strcasecmp(l->data, "no_sslv3") == 0)
        ret|=TSO_NOSSLv3;
      else if (strcasecmp(l->data, "no-tlsv1") == 0 || strcasecmp(l->data, "no_tlsv1") == 0)
        ret|=TSO_NOTLSv1;
#ifdef SSL_OP_NO_TLSv1_2
      else if (strcasecmp(l->data, "no-tlsv11") == 0 || strcasecmp(l->data, "no_tlsv11") == 0)
        ret|=TSO_NOTLSv11;
      else if (strcasecmp(l->data, "no-tlsv12") == 0 || strcasecmp(l->data, "no_tlsv12") == 0)
        ret|=TSO_NOTLSv12;
#endif
      else
        msg_error("Unknown ssl-option", evt_tag_str("option", l->data), NULL);
    }
  msg_debug("ssl-options parsed", evt_tag_printf("parsed value", "%d", ret), NULL);
  return ret;
}
Пример #11
0
static void
log_rewrite_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  LogRewrite *self = (LogRewrite *) s;
  gchar buf[128];
  gssize length;
  const gchar *value;

  if (self->condition && !filter_expr_eval_root(self->condition, &msg, path_options))
    {
      msg_debug("Rewrite condition unmatched, skipping rewrite",
                evt_tag_str("value", log_msg_get_value_name(self->value_handle, NULL)),
                NULL);
    }
  else
    {
      self->process(self, &msg, path_options);
    }
  if (G_UNLIKELY(debug_flag))
    {
      value = log_msg_get_value(msg, self->value_handle, &length);
      msg_debug("Rewrite expression evaluation result",
                evt_tag_str("value", log_msg_get_value_name(self->value_handle, NULL)),
                evt_tag_printf("new_value", "%.*s", (gint) length, value),
                evt_tag_str("rule", self->name),
                evt_tag_str("location", log_expr_node_format_location(s->expr_node, buf, sizeof(buf))),
                NULL);
    }
  log_pipe_forward_msg(s, msg, path_options);
}
Пример #12
0
static gboolean
log_proto_framed_server_extract_frame_length(LogProtoFramedServer *self, gboolean *need_more_data)
{
    gint i;

    *need_more_data = TRUE;
    self->frame_len = 0;
    for (i = self->buffer_pos; i < self->buffer_end; i++)
    {
        if (isdigit(self->buffer[i]) && (i - self->buffer_pos < 10))
        {
            self->frame_len = self->frame_len * 10 + (self->buffer[i] - '0');
        }
        else if (self->buffer[i] == ' ')
        {
            *need_more_data = FALSE;
            self->buffer_pos = i + 1;
            return TRUE;
        }
        else
        {
            msg_error("Invalid frame header",
                      evt_tag_printf("header", "%.*s", (gint) (i - self->buffer_pos), &self->buffer[self->buffer_pos]),
                      NULL);
            return FALSE;
        }
    }
    /* couldn't extract frame header, no error but need more data */
    return TRUE;
}
Пример #13
0
static void
__handle_data(gchar *key, gchar *value, gpointer user_data)
{
  gpointer *args = user_data;

  LogMessage *msg = args[0];
  JournalReaderOptions *options = args[1];
  gssize value_len = MIN(strlen(value), options->max_field_size);

  if (strcmp(key, "MESSAGE") == 0)
    {
      log_msg_set_value(msg, LM_V_MESSAGE, value, value_len);
      msg_debug("Incoming log entry from journal",
                evt_tag_printf("message", "%.*s", (int)value_len, value),
                NULL);
    }
  else if (strcmp(key, "_HOSTNAME") == 0)
    {
      log_msg_set_value(msg, LM_V_HOST, value, value_len);
    }
  else if (strcmp(key, "_PID") == 0)
    {
      log_msg_set_value(msg, LM_V_PID, value, value_len);
    }
  else if (strcmp(key, "_COMM") == 0)
    {
      log_msg_set_value(msg, LM_V_PROGRAM, value, value_len);
    }
  else if (strcmp(key, "SYSLOG_IDENTIFIER") == 0)
    {
      gssize program_length;
      (void)log_msg_get_value(msg, LM_V_PROGRAM, &program_length);
      if (program_length == 0)
        {
          log_msg_set_value(msg, LM_V_PROGRAM, value, value_len);
        }
    }
  else if (strcmp(key, "SYSLOG_FACILITY") == 0)
    {
      msg->pri = (msg->pri & 7) | atoi(value) << 3;
    }
  else if (strcmp(key, "PRIORITY") == 0)
    {
      msg->pri = (msg->pri & ~7) | atoi(value);
    }
  else
    {
      if (!options->prefix)
        {
          log_msg_set_value_by_name(msg, key, value, value_len);
        }
      else
        {
          gchar *prefixed_key = g_strdup_printf("%s%s", options->prefix, key);
          log_msg_set_value_by_name(msg, prefixed_key, value, value_len);
          g_free(prefixed_key);
        }
    }
}
Пример #14
0
/*
 * returns the number of bytes that represent the UTF8 encoding buffer
 * in the original encoding that the user specified.
 *
 * NOTE: this is slow, but we only call this for the remainder of our
 * buffer (e.g. the partial line at the end of our last chunk of read
 * data). Also, this is only invoked if the file uses an encoding.
 */
static gsize
log_proto_text_server_get_raw_size_of_buffer(LogProtoTextServer *self, const guchar *buffer, gsize buffer_len)
{
  gchar *out;
  const guchar *in;
  gsize avail_out, avail_in;
  gint ret;

  if (self->reverse_convert == ((GIConv) -1) && !self->convert_scale)
    {
      /* try to speed up raw size calculation by recognizing the most
       * prominent character encodings and in the case the encoding
       * uses fixed size characters set that in self->convert_scale,
       * which in turn will speed up the reversal of the UTF8 buffer
       * size to raw buffer sizes.
       */
      self->convert_scale = log_proto_get_char_size_for_fixed_encoding(self->super.super.options->encoding);
      if (self->convert_scale == 0)
        {
          /* this encoding is not known, do the conversion for real :( */
          self->reverse_convert = g_iconv_open(self->super.super.options->encoding, "utf-8");
        }
    }

  if (self->convert_scale)
    return g_utf8_strlen((gchar *) buffer, buffer_len) * self->convert_scale;

  if (self->reverse_buffer_len < buffer_len * 6)
    {
      /* we free and malloc, since we never need the data still in reverse buffer */
      g_free(self->reverse_buffer);
      self->reverse_buffer_len = buffer_len * 6;
      self->reverse_buffer = g_malloc(buffer_len * 6);
    }

  avail_out = self->reverse_buffer_len;
  out = self->reverse_buffer;

  avail_in = buffer_len;
  in = buffer;

  ret = g_iconv(self->reverse_convert, (gchar **) &in, &avail_in, &out, &avail_out);
  if (ret == (gsize) -1)
    {
      /* oops, we cannot reverse that we ourselves converted to UTF-8,
       * this is simply impossible, but never say never */
      msg_error("Internal error, couldn't reverse the internal UTF8 string to the original encoding",
                evt_tag_printf("buffer", "%.*s", (gint) buffer_len, buffer),
                NULL);
      return 0;
    }
  else
    {
      return self->reverse_buffer_len - avail_out;
    }
}
Пример #15
0
static gssize
log_transport_tls_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux)
{
  LogTransportTLS *self = (LogTransportTLS *) s;
  gint ssl_error;
  gint rc;

  /* assume that we need to poll our input for reading unless
   * SSL_ERROR_WANT_WRITE is specified by libssl */
  self->super.cond = G_IO_IN;

  do
    {
      rc = SSL_read(self->tls_session->ssl, buf, buflen);

      if (rc < 0)
        {
          ssl_error = SSL_get_error(self->tls_session->ssl, rc);
          switch (ssl_error)
            {
            case SSL_ERROR_WANT_READ:
              errno = EAGAIN;
              break;
            case SSL_ERROR_WANT_WRITE:
              /* although we are writing this fd, libssl wants to write. This
               * happens during renegotiation for example */
              self->super.cond = G_IO_OUT;
              errno = EAGAIN;
              break;
            case SSL_ERROR_SYSCALL:
              /* errno is set accordingly */
              break;
            default:
              goto tls_error;
            }
        }
    }
  while (rc == -1 && errno == EINTR);

  return rc;
 tls_error:

  ssl_error = ERR_get_error();
  msg_error("SSL error while reading stream",
            evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error)),
            NULL);
  ERR_clear_error();

  errno = ECONNRESET;
  return -1;

}
Пример #16
0
static void
stats_log_format_counter(StatsCluster *sc, gint type, StatsCounterItem *item, gpointer user_data)
{
  EVTREC *e = (EVTREC *) user_data;
  EVTTAG *tag;
  gchar buf[32];

  tag = evt_tag_printf(stats_cluster_get_type_name(type), "%s(%s%s%s)=%u", 
                       stats_cluster_get_component_name(sc, buf, sizeof(buf)),
                       sc->id,
                       (sc->id[0] && sc->instance[0]) ? "," : "",
                       sc->instance,
                       stats_counter_get(&sc->counters[type]));
  evt_rec_add_tag(e, tag);
}
Пример #17
0
static PersistValueHeader *
_map_header_of_entry_from_handle(PersistState *self, PersistEntryHandle handle)
{
  PersistValueHeader *header;

  if (handle > self->current_size)
    {
      msg_error("Corrupted handle in persist_state_lookup_entry, handle value too large",
                evt_tag_printf("handle", "%08x", handle),
                NULL);
      return NULL;
    }
  header = (PersistValueHeader *) persist_state_map_entry(self, handle - sizeof(PersistValueHeader));
  if (GUINT32_FROM_BE(header->size) + handle > self->current_size)
    {
      msg_error("Corrupted entry header found in persist_state_lookup_entry, size too large",
                evt_tag_printf("handle", "%08x", handle),
                evt_tag_int("size", GUINT32_FROM_BE(header->size)),
                evt_tag_int("file_size", self->current_size),
                NULL);
      return NULL;
    }
  return header;
}
Пример #18
0
static void
afinet_set_port(GSockAddr *addr, gchar *service, const gchar *proto)
{
  if (addr)
    {
      gchar *end;
      gint port;

      /* check if service is numeric */
      port = strtol(service, &end, 10);
      if ((*end != 0))
        {
          struct servent *se;

          /* service is not numeric, check if it's a service in /etc/services */
          se = getservbyname(service, proto);
          if (se)
            {
              port = ntohs(se->s_port);
            }
          else
            {
              msg_error("Error finding port number, falling back to default",
                        evt_tag_printf("service", "%s/%s", proto, service),
                        NULL);
              return;
            }
        }

      switch (addr->sa.sa_family)
        {
        case AF_INET:
          g_sockaddr_inet_set_port(addr, port);
          break;
#if ENABLE_IPV6
        case AF_INET6:
          g_sockaddr_inet6_set_port(addr, port);
          break;
#endif
        default:
          g_assert_not_reached();
          break;
        }
    }
}
Пример #19
0
gboolean
confgen_exec_generate(CfgBlockGenerator *s, GlobalConfig *cfg, CfgArgs *args, GString *result, const gchar *reference)
{
  ConfgenExec *self = (ConfgenExec *) s;
  FILE *out;
  gchar buf[256];
  gint res;

  g_snprintf(buf, sizeof(buf), "%s confgen %s", cfg_lexer_lookup_context_name_by_type(self->super.context),
             self->super.name);

  cfg_args_foreach(args, confgen_set_args_as_env, NULL);
  out = popen(self->exec, "r");
  cfg_args_foreach(args, confgen_unset_args_from_env, NULL);

  if (!out)
    {
      msg_error("confgen: Error executing generator program",
                evt_tag_str("reference", reference),
                evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)),
                evt_tag_str("block", self->super.name),
                evt_tag_str("exec", self->exec),
                evt_tag_error("error"));
      return FALSE;
    }

  _read_program_output(out, result);
  res = pclose(out);
  if (res != 0)
    {
      msg_error("confgen: Generator program returned with non-zero exit code",
                evt_tag_str("reference", reference),
                evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)),
                evt_tag_str("block", self->super.name),
                evt_tag_str("exec", self->exec),
                evt_tag_int("rc", res));
      return FALSE;
    }
  msg_debug("confgen: output from the executed program to be included is",
            evt_tag_printf("block", "%.*s", (gint) result->len, result->str));
  return TRUE;
}
Пример #20
0
static gboolean
log_reader_handle_line(LogReader *self, const guchar *line, gint length, LogTransportAuxData *aux)
{
  LogMessage *m;

  msg_debug("Incoming log entry",
            evt_tag_printf("line", "%.*s", length, line));
  /* use the current time to get the time zone offset */
  m = log_msg_new((gchar *) line, length,
                  aux->peer_addr ? : self->peer_addr,
                  &self->options->parse_options);

  log_msg_refcache_start_producer(m);

  log_transport_aux_data_foreach(aux, _add_aux_nvpair, m);

  log_source_post(&self->super, m);
  log_msg_refcache_stop();
  return log_source_free_to_send(&self->super);
}
Пример #21
0
static void
afinet_set_port(GSockAddr *addr, gint port, gchar *service, gchar *proto)
{
  if (addr)
    {
      if (proto)
        {
          struct servent *se;
          
          se = getservbyname(service, proto);
          if (se)
            {
              port = ntohs(se->s_port);
            }
          else
            {
              msg_error("Error finding port number, falling back to default",
                        evt_tag_printf("service", "%s/%s", proto, service),
                        NULL);
              return;
            }
        }
        
      switch (addr->sa.sa_family)
        {
        case AF_INET:
          g_sockaddr_inet_set_port(addr, port);
          break;
#if ENABLE_IPV6
        case AF_INET6:
          g_sockaddr_inet6_set_port(addr, port);
          break;
#endif
        default:
          g_assert_not_reached();
          break;
        }
    }  
}
Пример #22
0
int
main(void)
{
  EVTCONTEXT *ctx;
  EVTREC *e;
  char *es;
  
  ctx = evt_ctx_init("evtfmt", LOG_AUTH);
  e = evt_rec_init(ctx, LOG_INFO, "Test message with an embedded ';' in it. It also contains an <XML> like tag.");
  evt_rec_add_tags(e, 
                   evt_tag_str("test:tag", "'value'"),
                   evt_tag_str("test:tag2", "\n\n\n\n"),
                   evt_tag_int("test:fd", fileno(stderr)),
                   evt_tag_errno("test:error", EAGAIN),
                   evt_tag_printf("test:printf", "%d %d", 5, 6),
                   NULL);
  
  es = evt_format(e);
  printf("%s\n", es);
  free(es);
  
  evt_log(e);
  return 0;
}
Пример #23
0
static gboolean
log_reader_handle_line(LogReader *self, const guchar *line, gint length, GSockAddr *saddr)
{
  LogMessage *m;
  LogPathOptions path_options = LOG_PATH_OPTIONS_INIT;
  
  msg_debug("Incoming log entry", 
            evt_tag_printf("line", "%.*s", length, line),
            NULL);
  /* use the current time to get the time zone offset */
  m = log_msg_new((gchar *) line, length,
                  saddr,
                  &self->options->parse_options);

  log_msg_refcache_start_producer(m);
  if (!m->saddr && self->peer_addr)
    {
      m->saddr = g_sockaddr_ref(self->peer_addr);
    }

  log_pipe_queue(&self->super.super, m, &path_options);
  log_msg_refcache_stop();
  return log_source_free_to_send(&self->super);
}
Пример #24
0
static gboolean
_load_v4(PersistState *self, gboolean load_all_entries)
{
  gint fd;
  gint64 file_size;
  gpointer map;
  gpointer key_block;
  guint32 key_size;
  PersistFileHeader *header;
  gint key_count, i;

  fd = open(self->commited_filename, O_RDONLY);
  if (fd < 0)
    {
      /* no previous data found */
      return TRUE;
    }

  file_size = lseek(fd, 0, SEEK_END);
  if (file_size > ((1LL << 31) - 1))
    {
      msg_error("Persistent file too large",
                evt_tag_str("filename", self->commited_filename),
                evt_tag_printf("size", "%" G_GINT64_FORMAT, file_size),
                NULL);
      return FALSE;
    }
  map = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);
  close(fd);
  if (map == MAP_FAILED)
    {
      msg_error("Error mapping persistent file into memory",
                evt_tag_str("filename", self->commited_filename),
                evt_tag_errno("error", errno),
                NULL);
      return FALSE;
    }
  header = (PersistFileHeader *) map;

  key_block = ((gchar *) map) + offsetof(PersistFileHeader, initial_key_store);
  key_size = sizeof((((PersistFileHeader *) NULL))->initial_key_store);

  key_count = GUINT32_FROM_BE(header->key_count);
  i = 0;
  while (i < key_count)
    {
      gchar *name;
      guint32 entry_ofs, chain_ofs;
      SerializeArchive *sa;

      sa = serialize_buffer_archive_new(key_block, key_size);
      while (i < key_count)
        {
          if (!serialize_read_cstring(sa, &name, NULL))
            {
              serialize_archive_free(sa);
              msg_error("Persistent file format error, unable to fetch key name",
                        NULL);
              goto free_and_exit;
            }
          if (name[0])
            {
              if (serialize_read_uint32(sa, &entry_ofs))
                {
                  PersistValueHeader *value_header;
                  i++;

                  if (entry_ofs < sizeof(PersistFileHeader) || entry_ofs > file_size)
                    {
                      serialize_archive_free(sa);
                      g_free(name);
                      msg_error("Persistent file format error, entry offset is out of bounds",
                                NULL);
                      goto free_and_exit;
                    }

                  value_header = (PersistValueHeader *) ((gchar *) map + entry_ofs - sizeof(PersistValueHeader));
                  if ((value_header->in_use) || load_all_entries)
                    {
                      gpointer new_block;
                      PersistEntryHandle new_handle;

                      new_handle = _alloc_value(self, GUINT32_FROM_BE(value_header->size), FALSE, value_header->version);
                      new_block = persist_state_map_entry(self, new_handle);
                      memcpy(new_block, value_header + 1, GUINT32_FROM_BE(value_header->size));
                      persist_state_unmap_entry(self, new_handle);
                      /* add key to the current file */
                      _add_key(self, name, new_handle);
                    }
                  g_free(name);
                }
              else
                {
                  /* bad format */
                  serialize_archive_free(sa);
                  g_free(name);
                  msg_error("Persistent file format error, unable to fetch key name",
                            NULL);
                  goto free_and_exit;
                }
            }
          else
            {
              g_free(name);
              if (serialize_read_uint32(sa, &chain_ofs))
                {
                  /* end of block, chain to the next one */
                  if (chain_ofs == 0 || chain_ofs > file_size)
                    {
                      msg_error("Persistent file format error, key block chain offset is too large or zero",
                                evt_tag_printf("key_block", "%08lx", (gulong) ((gchar *) key_block - (gchar *) map)),
                                evt_tag_printf("key_size", "%d", key_size),
                                evt_tag_int("ofs", chain_ofs),
                                NULL);
                      serialize_archive_free(sa);
                      goto free_and_exit;
                    }
                  key_block = ((gchar *) map) + chain_ofs;
                  key_size = GUINT32_FROM_BE(*(guint32 *) (((gchar *) key_block) - sizeof(PersistValueHeader)));
                  if (chain_ofs + key_size > file_size)
                    {
                      msg_error("Persistent file format error, key block size is too large",
                                evt_tag_int("key_size", key_size),
                                NULL);
                      serialize_archive_free(sa);
                      goto free_and_exit;
                    }
                  break;
                }
              else
                {
                  serialize_archive_free(sa);
                  msg_error("Persistent file format error, unable to fetch chained key block offset",
                            NULL);
                  goto free_and_exit;
                }
            }
        }
      serialize_archive_free(sa);
    }
 free_and_exit:
  munmap(map, file_size);
  return TRUE;
}
Пример #25
0
static gboolean
afamqp_is_ok(AMQPDestDriver *self, gchar *context, amqp_rpc_reply_t ret)
{
    switch (ret.reply_type)
    {
    case AMQP_RESPONSE_NORMAL:
        break;

    case AMQP_RESPONSE_NONE:
        msg_error(context,
                  evt_tag_str("driver", self->super.super.super.id),
                  evt_tag_str("error", "missing RPC reply type"),
                  evt_tag_int("time_reopen", self->super.time_reopen),
                  NULL);
        log_threaded_dest_driver_suspend(&self->super);
        return FALSE;

    case AMQP_RESPONSE_LIBRARY_EXCEPTION:
    {
        gchar *errstr = amqp_error_string(ret.library_error);
        msg_error(context,
                  evt_tag_str("driver", self->super.super.super.id),
                  evt_tag_str("error", errstr),
                  evt_tag_int("time_reopen", self->super.time_reopen),
                  NULL);
        g_free (errstr);
        log_threaded_dest_driver_suspend(&self->super);
        return FALSE;
    }

    case AMQP_RESPONSE_SERVER_EXCEPTION:
        switch (ret.reply.id)
        {
        case AMQP_CONNECTION_CLOSE_METHOD:
        {
            amqp_connection_close_t *m =
                (amqp_connection_close_t *) ret.reply.decoded;
            msg_error(context,
                      evt_tag_str("driver", self->super.super.super.id),
                      evt_tag_str("error", "server connection error"),
                      evt_tag_int("code", m->reply_code),
                      evt_tag_str("text", m->reply_text.bytes),
                      evt_tag_int("time_reopen", self->super.time_reopen),
                      NULL);
            log_threaded_dest_driver_suspend(&self->super);
            return FALSE;
        }
        case AMQP_CHANNEL_CLOSE_METHOD:
        {
            amqp_channel_close_t *m =
                (amqp_channel_close_t *) ret.reply.decoded;
            msg_error(context,
                      evt_tag_str("driver", self->super.super.super.id),
                      evt_tag_str("error", "server channel error"),
                      evt_tag_int("code", m->reply_code),
                      evt_tag_str("text", m->reply_text.bytes),
                      evt_tag_int("time_reopen", self->super.time_reopen),
                      NULL);
            log_threaded_dest_driver_suspend(&self->super);
            return FALSE;
        }
        default:
            msg_error(context,
                      evt_tag_str("driver", self->super.super.super.id),
                      evt_tag_str("error", "unknown server error"),
                      evt_tag_printf("method id", "0x%08X", ret.reply.id),
                      evt_tag_int("time_reopen", self->super.time_reopen),
                      NULL);
            log_threaded_dest_driver_suspend(&self->super);
            return FALSE;
        }
        return FALSE;
    }
    return TRUE;
}
Пример #26
0
/**
 * Parse the zoneinfo file structure (see tzfile.h) into a ZoneInfo
 */
static ZoneInfo*
zone_info_parser(unsigned char **input, gboolean is64bitData, gint *version)
{
    gint32 i = 0;
    unsigned char *buf = NULL;
    ZoneInfo *info = NULL;
    gint64 *transition_times = NULL;
    guint8 *transition_types = NULL;
    gint32 *gmt_offsets = NULL;
    gint64 isgmtcnt, isdstcnt, leapcnt, timecnt, typecnt, charcnt;
    gboolean insertInitial = FALSE;

    buf = *input;
    *input += 4;

    if (strncmp((gchar*)buf, TZ_MAGIC, 4) != 0)
    {
        msg_error("Error while processing the time zone file",
                  evt_tag_str("message", TZ_MAGIC" signature is missing"),
                  NULL);
        goto error;
    }

    /* read the version byte */
    buf = *input;
    *input += 1;

    /*
     * if '\0', we have just one copy of data,
     * if '2', there is additional 64 bit version at the end.
     */
    if (buf[0] != 0 && buf[0] != '2' && buf[0] != '3')
    {
        msg_error("Error in the time zone file",
                  evt_tag_str("message", "Bad Olson version info"),
                  NULL);
        goto error;
    }
    else
    {
        if (buf[0] != 0)
            *version = buf[0] - '0';
        else
            *version = 0;
    }

    /* Read reserved bytes */
    *input += 15;

    /* Read array sizes */
    isgmtcnt = readcoded32(input, 0, G_MAXINT64);
    isdstcnt = readcoded32(input, 0, G_MAXINT64);
    leapcnt  = readcoded32(input, 0, G_MAXINT64);
    timecnt  = readcoded32(input, 0, G_MAXINT64);
    typecnt  = readcoded32(input, 0, G_MAXINT64);
    charcnt  = readcoded32(input, 0, G_MAXINT64);

    /*
     * Confirm sizes that we assume to be equal.  These assumptions
     * are drawn from a reading of the zic source (2003a), so they
     * should hold unless the zic source changes.
     */

    if (isgmtcnt != typecnt ||
            isdstcnt != typecnt)
    {
        msg_warning("Error in the time zone file",
                    evt_tag_str("message", "Count mismatch between tzh_ttisgmtcnt, tzh_ttisdstcnt, tth_typecnt"),
                    NULL);
    }

    /*
     * Used temporarily to store transition times and types.  We need
     * to do this because the times and types are stored in two
     * separate arrays.
     */
    transition_times = g_new0(gint64, timecnt);
    transition_types = g_new0(guint8, timecnt);
    gmt_offsets      = g_new0(gint32, typecnt);

    /* Read transition times */
    for (i = 0; i < timecnt; ++i)
    {
        if (is64bitData)
        {
            transition_times[i] = readcoded64(input, G_MININT64, G_MAXINT64);
        }
        else
        {
            transition_times[i] = readcoded32(input, G_MININT64, G_MAXINT64);
        }
    }

    /* Read transition types */
    for (i = 0; i < timecnt; ++i)
    {
        guint8 t = (guint8)readchar(input);
        if (t >= typecnt)
        {
            msg_warning("Error in the time zone file",
                        evt_tag_str("message", "Illegal type number"),
                        evt_tag_printf("val", "%ld", (long) t),
                        evt_tag_printf("expected", "[0, %" G_GINT64_FORMAT "]", typecnt-1),
                        NULL);
            goto error;
        }
        transition_types[i] = t;
    }

    /* Read types (except for the isstd and isgmt flags, which come later (why??)) */
    for (i = 0; i<typecnt; ++i)
    {
        gint offs = 24;

        if (*version == 3)
            offs = 167;

        gmt_offsets[i] = readcoded32(input, G_MININT64, G_MAXINT64);
        if (gmt_offsets[i] > offs * 60 * 60 || gmt_offsets[i] < -1 * offs * 60 * 60)
        {
            msg_warning("Error in the time zone file",
                        evt_tag_str("message", "Illegal gmtoffset number"),
                        evt_tag_int("val", gmt_offsets[i]),
                        evt_tag_printf("expected", "[%d, %d]", -1 * offs * 60 * 60, offs * 60 * 60),
                        NULL);
            goto error;
        }
        /* ignore isdst flag */
        readbool(input);
        /* ignore abbr index */
        readchar(input);
    }

    /* allocate a new ZoneInfo structure */
    if (typecnt > 0 && timecnt == 0)
    {
        /* only one type info is in the time zone file so add it with 1901 */
        info = zone_info_new(1);
        info->transitions[0].time = LOWEST_TIME32;
        info->transitions[0].gmtoffset = gmt_offsets[0];
    }
    else
    {
        info = zone_info_new(timecnt);
    }

    /* Build transitions vector out of corresponding times and types. */
    insertInitial = FALSE;
    if (is64bitData)
    {
        if (timecnt > 0)
        {
            gint32 minidx = -1;
            gint32 last_transition_index = 0;
            for (i = 0; i < timecnt; ++i)
            {
                if (transition_times[i] < LOWEST_TIME32)
                {
                    if (minidx == -1 || transition_times[i] > transition_times[minidx])
                    {
                        /* Preserve the latest transition before the 32bit minimum time */
                        minidx = i;
                    }
                }
                else
                {
                    info->transitions[last_transition_index].time = transition_times[i];
                    info->transitions[last_transition_index].gmtoffset = gmt_offsets[transition_types[i]];
                    last_transition_index++;
                }
            }

            if (minidx != -1)
            {
                /*
                 * If there are any transitions before the 32bit minimum time,
                 * put the type information with the 32bit minimum time
                 */
                memmove(&info->transitions[1], &info->transitions[0], sizeof(Transition) * (timecnt-1));
                info->transitions[0].time = LOWEST_TIME32;
                info->transitions[0].gmtoffset = gmt_offsets[transition_types[minidx]];
                info->timecnt -= minidx;
            }
            else
            {
                /* Otherwise, we need insert the initial type later */
                insertInitial = TRUE;
            }
        }
    }
    else
    {
        for (i = 0; i < timecnt; ++i)
        {
            info->transitions[i].time = transition_times[i];
            info->transitions[i].gmtoffset = gmt_offsets[transition_types[i]];
        }
    }

    if (insertInitial)
    {
        g_assert(timecnt > 0);
        g_assert(typecnt > 0);

        /* reallocate the transitions vector to be able to store a new entry */
        info->timecnt ++;
        timecnt ++;
        info->transitions = g_renew(Transition, info->transitions, timecnt);

        /* Add the initial type associated with the lowest int32 time */
        memmove(&info->transitions[1], &info->transitions[0], sizeof(Transition) * (timecnt-1));
        info->transitions[0].time = LOWEST_TIME32;
        info->transitions[0].gmtoffset = gmt_offsets[0];
    }

    /* ignore the abbreviation string */
    if (charcnt)
        *input += charcnt;

    /* ignore leap second info, if any */
    for (i=0; i<leapcnt; ++i)
    {
        if(is64bitData)
            readcoded64(input, G_MININT64, G_MAXINT64);/* leap second transition time */
        else
            readcoded32(input, G_MININT64, G_MAXINT64);/* leap second transition time */
        readcoded32(input, G_MININT64, G_MAXINT64);/* total correction after above */
    }

    /* http://osdir.com/ml/time.tz/2006-02/msg00041.html */
    /* We dont nead this flags to compute the wall time of the timezone*/

    /* Ignore isstd flags */
    for (i=0; i<typecnt; i++)
        readbool(input);

    /* Ignore isgmt flags */
    for (i=0; i<typecnt; i++)
        readbool(input);

error:
    g_free(transition_times);
    g_free(transition_types);
    g_free(gmt_offsets);
    return info;
}
Пример #27
0
TLSSession *
tls_context_setup_session(TLSContext *self)
{
  SSL *ssl;
  TLSSession *session;
  gint ssl_error;

  if (!self->ssl_ctx)
    {
      gint verify_mode = 0;
      gint verify_flags = X509_V_FLAG_POLICY_CHECK;

      if (self->mode == TM_CLIENT)
        self->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
      else
        self->ssl_ctx = SSL_CTX_new(SSLv23_server_method());

      if (!self->ssl_ctx)
        goto error;
      if (file_exists(self->key_file) && !SSL_CTX_use_PrivateKey_file(self->ssl_ctx, self->key_file, SSL_FILETYPE_PEM))
        goto error;

      if (file_exists(self->cert_file) && !SSL_CTX_use_certificate_chain_file(self->ssl_ctx, self->cert_file))
        goto error;
      if (self->key_file && self->cert_file && !SSL_CTX_check_private_key(self->ssl_ctx))
        goto error;

      if (file_exists(self->ca_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->ca_dir))
        goto error;

      if (file_exists(self->crl_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->crl_dir))
        goto error;

      if (self->crl_dir)
        verify_flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;

      X509_VERIFY_PARAM_set_flags(self->ssl_ctx->param, verify_flags);

      switch (self->verify_mode)
        {
        case TVM_NONE:
          verify_mode = SSL_VERIFY_NONE;
          break;
        case TVM_OPTIONAL | TVM_UNTRUSTED:
          verify_mode = SSL_VERIFY_NONE;
          break;
        case TVM_OPTIONAL | TVM_TRUSTED:
          verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
          break;
        case TVM_REQUIRED | TVM_UNTRUSTED:
          verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
          break;
        case TVM_REQUIRED | TVM_TRUSTED:
          verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
          break;
        default:
          g_assert_not_reached();
        }

      SSL_CTX_set_verify(self->ssl_ctx, verify_mode, tls_session_verify_callback);
      SSL_CTX_set_options(self->ssl_ctx, SSL_OP_NO_SSLv2);
      if (self->cipher_suite)
        {
          if (!SSL_CTX_set_cipher_list(self->ssl_ctx, self->cipher_suite))
            goto error;
        }
    }

  ssl = SSL_new(self->ssl_ctx);

  if (self->mode == TM_CLIENT)
    SSL_set_connect_state(ssl);
  else
    SSL_set_accept_state(ssl);

  session = tls_session_new(ssl, self);
  SSL_set_app_data(ssl, session);
  return session;

 error:
  ssl_error = ERR_get_error();
  msg_error("Error setting up TLS session context",
            evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error)),
            NULL);
  ERR_clear_error();
  if (self->ssl_ctx)
    {
      SSL_CTX_free(self->ssl_ctx);
      self->ssl_ctx = NULL;
    }
  return NULL;
}
Пример #28
0
static gboolean
log_proto_buffered_server_convert_from_raw(LogProtoBufferedServer *self, const guchar *raw_buffer, gsize raw_buffer_len)
{
  /* some data was read */
  gsize avail_in = raw_buffer_len;
  gsize avail_out;
  gchar *out;
  gint  ret = -1;
  gboolean success = FALSE;
  LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self);

  do
    {
      avail_out = state->buffer_size - state->pending_buffer_end;
      out = (gchar *) self->buffer + state->pending_buffer_end;

      ret = g_iconv(self->convert, (gchar **) &raw_buffer, &avail_in, (gchar **) &out, &avail_out);
      if (ret == (gsize) -1)
        {
          switch (errno)
            {
            case EINVAL:
              if (self->stream_based)
                {
                  /* Incomplete text, do not report an error, rather try to read again */
                  state->pending_buffer_end = state->buffer_size - avail_out;

                  if (avail_in > 0)
                    {
                      if (avail_in > sizeof(state->raw_buffer_leftover))
                        {
                          msg_error("Invalid byte sequence, the remaining raw buffer is larger than the supported leftover size",
                                    evt_tag_str("encoding", self->super.options->encoding),
                                    evt_tag_int("avail_in", avail_in),
                                    evt_tag_int("leftover_size", sizeof(state->raw_buffer_leftover)));
                          goto error;
                        }
                      memcpy(state->raw_buffer_leftover, raw_buffer, avail_in);
                      state->raw_buffer_leftover_size = avail_in;
                      state->raw_buffer_size -= avail_in;
                      msg_trace("Leftover characters remained after conversion, delaying message until another chunk arrives",
                                evt_tag_str("encoding", self->super.options->encoding),
                                evt_tag_int("avail_in", avail_in));
                      goto success;
                    }
                }
              else
                {
                  msg_error("Byte sequence too short, cannot convert an individual frame in its entirety",
                            evt_tag_str("encoding", self->super.options->encoding),
                            evt_tag_int("avail_in", avail_in));
                  goto error;
                }
              break;
            case E2BIG:
              state->pending_buffer_end = state->buffer_size - avail_out;
              /* extend the buffer */

              if (state->buffer_size < self->super.options->max_buffer_size)
                {
                  state->buffer_size *= 2;
                  if (state->buffer_size > self->super.options->max_buffer_size)
                    state->buffer_size = self->super.options->max_buffer_size;

                  self->buffer = g_realloc(self->buffer, state->buffer_size);

                  /* recalculate the out pointer, and add what we have now */
                  ret = -1;
                }
              else
                {
                  msg_error("Incoming byte stream requires a too large conversion buffer, probably invalid character sequence",
                            evt_tag_str("encoding", self->super.options->encoding),
                            evt_tag_printf("buffer", "%.*s", (gint) state->pending_buffer_end, self->buffer));
                  goto error;
                }
              break;
            case EILSEQ:
            default:
              msg_notice("Invalid byte sequence or other error while converting input, skipping character",
                         evt_tag_str("encoding", self->super.options->encoding),
                         evt_tag_printf("char", "0x%02x", *(guchar *) raw_buffer));
              goto error;
            }
        }
      else
        {
          state->pending_buffer_end = state->buffer_size - avail_out;
        }
    }
  while (avail_in > 0);

 success:
  success = TRUE;
 error:
  log_proto_buffered_server_put_state(self);
  return success;
}