Exemplo n.º 1
0
static gboolean
pop3_transfer_stack(ZTransfer2 *s, ZStackedProxy **stacked)
{
  Pop3Proxy *owner = Z_CAST(s->owner, Pop3Proxy);

  return pop3_policy_stack_hash_do(owner, stacked);
}
Exemplo n.º 2
0
Arquivo: z.c Projeto: Keidan/tk
/**
 * @fn void z_delete(z_t zip)
 * @brief Delete the ZIP context.
 * @param zip The pointer to release.
 */
void z_delete(z_t zip) {
  struct z_s* z = Z_CAST(zip);
  if(!Z_VALID(z)) return;
  z_close(z);
  z->magic = 0;
  free(z);
}
Exemplo n.º 3
0
/**
 * z_transfer2_ps_iface_set_stacked_verdict:
 * @self: ZProxyStackIface instance
 * @verdict: verdict sent by the child proxy
 * @description: additional information about @decision
 *
 * This function is the virtual set_result method in the ZProxyStackIface
 * interface callable by child proxies. It simply stores the verdict sent
 * by the child proxy in self->stack_decision.
 *
 * NOTE: this function runs in the thread of the child proxy and there is no
 * synchronization between this and the main proxy thread except for the fact
 * that the child proxy should call this function before he sends anything
 * and HTTP will make use of this value when it first receives something,
 * thus there must be at least one context switch in between, and the HTTP
 * is possibly sleeping when this function is called.
 **/
static void
z_transfer2_ps_iface_set_stacked_verdict(ZProxyStackIface *s, ZVerdict verdict, const gchar *description)
{
  ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface);

  g_string_assign(self->transfer->stack_info, description ? description : "");
  self->transfer->stack_decision = verdict;
}
Exemplo n.º 4
0
Arquivo: z.c Projeto: Keidan/tk
/**
 * @fn void z_set_dir_delimiter(z_t zip, char delimiter)
 * @brief Change the directory delimiter.
 * @param zip ZIP context.
 * @param delimiter The new deimiter.
 */
void z_set_dir_delimiter(z_t zip, char delimiter) {
  struct z_s* z = Z_CAST(zip);
  if(!Z_VALID(z)) {
    logger(LOG_ERR, "Invalid zip pointer!\n");
    return;
  }
  z->dir_delimiter = delimiter;
}
Exemplo n.º 5
0
void
z_proxy_ssl_host_iface_free_method(ZObject *s)
{
  ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface);

  X509_free(self->server_cert);
  z_object_free_method(s);
}
Exemplo n.º 6
0
/**
 * finger_config:
 **/
static gboolean
finger_config(ZProxy *s)
{
    FingerProxy *self = Z_CAST(s, FingerProxy);
    finger_config_set_defaults(self);
    finger_register_vars(self);
    return Z_SUPER(s, ZProxy)->config(s);
}
Exemplo n.º 7
0
Arquivo: z.c Projeto: Keidan/tk
/**
 * @fn char z_get_dir_delimiter(z_t zip)
 * @brief Get the current directory delimiter.
 * @param zip ZIP context.
 * @return The deimiter.
 */
char z_get_dir_delimiter(z_t zip) {
  struct z_s* z = Z_CAST(zip);
  if(!Z_VALID(z)) {
    logger(LOG_ERR, "Invalid zip pointer!\n");
    return 0;
  }
  return z->dir_delimiter;
}
Exemplo n.º 8
0
/**
 * http_set_content_length:
 * @self: ZProxyStackIface instance
 * @content_length: the length of the content to be transferred
 *
 * This function is the virtual set_content_length method in the
 * ZProxyStackIface interface callable by child proxies. It simply stores
 * the future size of the transferred data blob. This information will then
 * be used by the transfer code to decide whether to include a
 * content-length header. Calling this function is not mandatory by the
 * child proxy, if it is not called chunked mode transfer-encoding will be
 * used.
 */
static void
z_transfer2_ps_iface_set_content_hint(ZProxyStackIface *s, gint64 content_length)
{
  ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface);

  self->transfer->child_content_length_hint = content_length;
  self->transfer->child_content_length_hint_set = TRUE;
}
Exemplo n.º 9
0
static ZProxyIface *
z_transfer2_ps_iface_new(ZTransfer2 *transfer)
{
  ZTransfer2PSIface *self;

  self = Z_CAST(z_proxy_stack_iface_new(Z_CLASS(ZTransfer2PSIface), transfer->owner), ZTransfer2PSIface);
  self->transfer = transfer;
  return &self->super;
}
Exemplo n.º 10
0
/**
 * finger_proxy_new:
 * @params: ZProxyParams structure
 *
 * Finger proxy constructor. Allocates and initializes a proxy instance,
 * starts proxy thread.
 **/
static ZProxy *
finger_proxy_new(ZProxyParams *params)
{
    FingerProxy  *self;

    z_enter();
    self = Z_CAST(z_proxy_new(Z_CLASS(FingerProxy), params), FingerProxy);
    z_return((ZProxy *) self);
}
Exemplo n.º 11
0
Arquivo: z.c Projeto: Keidan/tk
/**
 * @fn int z_get_global_zinfo(z_t zip, unz_global_info *ginfo)
 * @brief Get the global zip info (open must be all).
 * @param zip ZIP context.
 * @param ginfo The result infos.
 * @return -1 on error else 0.
 */
int z_get_global_zinfo(z_t zip, unz_global_info *ginfo) {
  struct z_s* z = Z_CAST(zip);
  if(!Z_VALID_OPEN(z)) {
    logger(LOG_ERR, "Invalid zip pointer!\n");
    return -1;
  }
  memcpy(ginfo, &z->ginfo, sizeof(unz_global_info));
  return 0;
}
Exemplo n.º 12
0
/**
 * anypy_proxy_new:
 * @params: parameters for the AnyPyProxy class constructor
 *
 * This function is called upon startup to create a new AnyPy proxy.
 **/
ZProxy *
anypy_proxy_new(ZProxyParams *params)
{
  AnyPyProxy *self;
  
  z_enter();
  self = Z_CAST(z_proxy_new(Z_CLASS(AnyPyProxy), params), AnyPyProxy);
  z_return(&self->super);
}
Exemplo n.º 13
0
static void
z_certificate_chain_free_method(ZObject *s)
{
  ZCertificateChain *self = Z_CAST(s, ZCertificateChain);
  if (self->cert)
    X509_free(self->cert);
  sk_X509_pop_free(self->chain, X509_free);
  z_object_free_method(s);
}
Exemplo n.º 14
0
ZProxyIface *
z_proxy_ssl_host_iface_new(ZProxy *owner)
{
  ZProxySslHostIface *self;

  self = Z_CAST(z_proxy_iface_new(Z_CLASS(ZProxySslHostIface), owner), ZProxySslHostIface);
  self->server_cert = owner->ssl_opts.peer_cert[EP_SERVER];

  CRYPTO_add(&self->server_cert->references, 1, CRYPTO_LOCK_X509);
  return &self->super;
}
Exemplo n.º 15
0
static gboolean
telnet_client_read(ZStream *stream, GIOCondition cond G_GNUC_UNUSED, gpointer user_data)
{
  TelnetProxy   *self = Z_CAST(user_data, TelnetProxy);
  gboolean      res;

  z_proxy_enter(self);

  res = telnet_read(self, stream, EP_CLIENT);

  z_proxy_return(self, res);
}
Exemplo n.º 16
0
/**
 * anypy_config:
 * @s: AnyPyProxy instance casted to ZProxy
 *
 * This function is called upon startup to configure the proxy.
 * This calls the the __pre_config__, config and __post_config__ events.
 **/
static gboolean
anypy_config(ZProxy *s)
{
  AnyPyProxy *self = Z_CAST(s, AnyPyProxy);
  
  anypy_config_set_defaults(self);
  anypy_register_vars(self);
  if (Z_SUPER(s, ZProxy)->config(s))
    {
      return TRUE;
    }
  return FALSE;
}
Exemplo n.º 17
0
/**
 * z_transfer2_timeout:
 * @user_data: ZTransfer2 instance passed as a generic pointer
 *
 * This function is a timeout-callback registered to terminate the
 * transfer loop when a specified time elapses.
 **/
static gboolean
z_transfer2_timeout(gpointer user_data)
{
  ZTransfer2 *self = Z_CAST(user_data, ZTransfer2);

  z_proxy_enter(self->owner);
  /*LOG
    This message indicates the data transfer timed out.
   */
  z_proxy_log(self->owner, CORE_ERROR, 3, "Data transfer timed out; timeout='%ld'", self->timeout);
  z_transfer2_update_status(self, ZT2S_TIMEDOUT+ZT2S_FAILED+ZT2S_FINISHED, TRUE);
  z_proxy_leave(self->owner);
  return FALSE;
}
Exemplo n.º 18
0
/**
 * http_get_content_hint:
 * @self: ZProxyStackIface instance
 * @content_length: the length of the content to be transferred
 *
 * This function is the virtual get_content_length method in the
 * ZProxyStackIface interface callable by child proxies.
 */
static gboolean
z_transfer2_ps_iface_get_content_hint(ZProxyStackIface *s, gint64 *content_length, const gchar **content_format)
{
  ZTransfer2PSIface *self = Z_CAST(s, ZTransfer2PSIface);

  /* Note: Save it with a mutex because it's only be set in z_transfer2_setup in
   * other thread than this called.
   */
  g_mutex_lock(self->transfer->startup_lock);
  *content_format = self->transfer->content_format;
  if (self->transfer->our_content_length_hint_set)
    *content_length = self->transfer->our_content_length_hint;
  else
    *content_length = -1;
  g_mutex_unlock(self->transfer->startup_lock);

  return TRUE;
}
Exemplo n.º 19
0
Arquivo: z.c Projeto: Keidan/tk
/**
 * @fn int z_open(z_t zip, const z_file_t filename)
 * @brief Open a new ZIP file.
 * @param zip The ZIP context.
 * @param filename ZIP file name.
 * @return 0 on success else -1.
 */
int z_open(z_t zip, const z_file_t filename) {
  struct z_s* z = Z_CAST(zip);
  if(!Z_VALID(z)) return -1;
  strcpy(z->filename, filename);
  /* Open the zip file */
  z->ctx = unzOpen64(z->filename);
  if(!z->ctx) {
    logger(LOG_ERR, "Unable to open the zip file '%s'\n", z->filename);
    z_close(z);
    return -1;
  }
  /* Get info about the zip file */
  if(unzGetGlobalInfo64(z->ctx, &z->ginfo) != UNZ_OK) {
    logger(LOG_ERR, "Unable to read the global info related to the '%s' zip file\n", z->filename);
    z_close(z);
    return -1;
  }
  return 0;
}
Exemplo n.º 20
0
static void
anypy_main(ZProxy * s)
{
  AnyPyProxy *self = Z_CAST(s, AnyPyProxy);
  ZPolicyObj *res;
  gboolean called;

  z_proxy_enter(self);
  if (!z_proxy_connect_server(&self->super, NULL, 0) || !anypy_stream_init(self))
    {
      z_proxy_leave(self);
      return;
    }
  z_policy_lock(self->super.thread);  
  res = z_policy_call(self->super.handler, "proxyThread", NULL, &called, self->super.session_id);
  z_policy_var_unref(res);
  z_policy_unlock(self->super.thread);
  z_proxy_return(self);
}
Exemplo n.º 21
0
/**
 * z_transfer2_timed_progress:
 * @user_data: ZTransfer2 instance passed as a generic pointer
 *
 * This function is the timeout callback registered to be called when the
 * interval specified by the timeout_progress variable elapses.  This is
 * used for example to generate NOOPs in SMTP while transfer is downloading
 * data to the virus checking proxy.
 **/
static gboolean
z_transfer2_timed_progress(gpointer user_data)
{
  ZTransfer2 *self = Z_CAST(user_data, ZTransfer2);

  z_proxy_enter(self->owner);
  if (!z_transfer2_progress(self))
    {
      /*LOG
        This message indicates that the data-transfer is interrupted by a timed
	progress callback and Zorp is closing the date-transfer channels.
       */
      z_proxy_log(self->owner, CORE_ERROR, 3, "Data transfer interrupted by progress;");
      z_transfer2_update_status(self, ZT2S_FAILED+ZT2S_FINISHED, TRUE);
    }
  z_timeout_source_set_timeout(self->progress_source, self->progress_interval);

  z_proxy_leave(self->owner);
  return TRUE;
}
Exemplo n.º 22
0
gboolean
pop3_data_transfer(Pop3Proxy *owner)
{
  Pop3Transfer *t;
  GString *preamble;
  gboolean success;
  gchar buf[256];

  z_proxy_enter(owner);
  preamble = g_string_new(owner->response->str);
  if (owner->response_param->len)
    {
      g_string_append_c(preamble, ' ');
      g_string_append(preamble, owner->response_param->str);
    }
  g_string_append(preamble, "\r\n");
  t = Z_CAST(z_dot_transfer_new(Z_CLASS(Pop3Transfer),
                                &owner->super, owner->poll,
                                owner->super.endpoints[EP_SERVER], owner->super.endpoints[EP_CLIENT],
                                owner->buffer_length,
                                owner->timeout,
                                ZT2F_COMPLETE_COPY | ZT2F_PROXY_STREAMS_POLLED,
                                preamble),
             Pop3Transfer);
  z_transfer2_set_content_format(&t->super.super, "email");

  z_stream_line_set_nul_nonfatal(owner->super.endpoints[EP_SERVER], TRUE);
  if (owner->policy_enable_longline)
    z_stream_line_set_split(owner->super.endpoints[EP_SERVER], TRUE);

  success = z_transfer2_simple_run(&t->super.super);
  z_stream_line_set_split(owner->super.endpoints[EP_SERVER], FALSE);
  z_stream_line_set_nul_nonfatal(owner->super.endpoints[EP_SERVER], FALSE);
  if (t->super.dst_write_state == DOT_DW_PREAMBLE)
    {
      /* nothing was written to destination */
      switch (z_transfer2_get_stack_decision(&t->super.super))
        {
        case ZV_REJECT:
	  /*LOG
	    This message indicates that the stacked proxy rejected the content and Zorp
	    rejects the response.
	   */
          z_proxy_log(owner, POP3_ERROR, 2, "Stacked proxy rejected contents; info='%s'", z_transfer2_get_stack_info(&t->super.super));
          g_snprintf(buf, sizeof(buf), "Content rejected (%s)", z_transfer2_get_stack_info(&t->super.super));
          if (owner->reject_by_mail)
            pop3_error_msg(owner, buf);
          else
            pop3_response_reject(owner, buf);
          break;

        case ZV_ERROR:
          g_snprintf(buf, sizeof(buf), "Error occurred while transferring data (%s)", z_transfer2_get_stack_info(&t->super.super));
          pop3_response_reject(owner, buf);
          owner->pop3_state = POP3_STATE_QUIT;
          break;

        default:
          pop3_response_write(owner);
          pop3_write_client(owner, ".\r\n");
          break;
        }
    }
  else
    {
      pop3_write_client(owner, ".\r\n");
    }

  if (owner->from)
    {
      g_string_free(owner->from, TRUE);
      owner->from = NULL;
    }

  if (owner->to)
    {
      g_string_free(owner->to, TRUE);
      owner->to = NULL;
    }

  if (owner->subject)
    {
      g_string_free(owner->subject, TRUE);
      owner->subject = NULL;
    }

  z_object_unref(&t->super.super.super);
  z_proxy_return(owner, success);
}
Exemplo n.º 23
0
/**
 * finger_main:
 * @s: FingerProxy instance
 *
 * main proxy routine.
 **/
static void
finger_main(ZProxy *s)
{
    FingerProxy *self = Z_CAST(s, FingerProxy);

    z_proxy_enter(self);
    if (!finger_init_client_stream(self))
        z_proxy_return(self);

    /*LOG
      This debug message is about proxy state when start to
      fetching request
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "fetching request;");
    if (!finger_fetch_request(self))
    {
        char *errmsg = "Finger protocol or disallowed protocol element, request denied.\r\n";
        gsize bytes_written;

        z_stream_write(self->super.endpoints[EP_CLIENT],
                       errmsg,
                       strlen(errmsg),
                       &bytes_written,
                       NULL);
        z_proxy_return(self);
    }

    /*LOG
      This debug message is about proxy state when finger
      fetched request and asking policy about it
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "asking policy;");
    if (!finger_query_policy(self))
        z_proxy_return(self);

    /*LOG
      This debug message is about proxy state when finger
      start connect to server.
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "connecting server;");
    /* this sets the server side endpoint if successful */
    if (!z_proxy_connect_server(&self->super, NULL, 0))
        z_proxy_return(self);

    if (!finger_init_server_stream(self))
        z_proxy_return(self);

    /*LOG
      This debug message is about proxy state when finger
      start send the request to server.
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "sending request;");
    if (!finger_send_request(self))
        z_proxy_return(self);

    /*LOG
      This debug message is about proxy state when finger
      start to copy server answer to client.
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "copying response;");
    if (!finger_copy_response(self))
        z_proxy_return(self);

    /*LOG
      This debug message is about proxy state when finger
      stop it's work.
     */
    z_proxy_log(self, FINGER_DEBUG, 6, "everything is done;");
    z_proxy_return(self);

}
Exemplo n.º 24
0
static GIOStatus
http_transfer_src_read(ZTransfer2 *s, ZStream *stream, gchar *buf, gsize count, gsize *bytes_read, GError **err)
{
  HttpTransfer *self = Z_CAST(s, HttpTransfer);
  HttpProxy *owner = Z_CAST(s->owner, HttpProxy);
  GError *local_error = NULL;
  gsize br;
  GIOStatus res = G_IO_STATUS_NORMAL;

  if (self->src_read_state == HTTP_SR_INITIAL)
    self->src_read_state = HTTP_SR_PUSH_HEADERS;

  if (self->src_read_state >= HTTP_SR_PUSH_HEADERS && self->src_read_state <= HTTP_SR_PUSH_HEADERS_MAX)
    {
      if (self->push_mime_headers && self->stacked_preamble->len > 0)
        {
          gint move;

          *bytes_read = 0;

          move = MIN(count, self->stacked_preamble->len - self->stacked_preamble_ofs);
          memmove(buf, self->stacked_preamble->str + self->stacked_preamble_ofs, move);
          self->stacked_preamble_ofs += move;
          *bytes_read = move;

          if (self->stacked_preamble_ofs == self->stacked_preamble->len)
            {
              z_transfer2_set_proxy_out(s, FALSE);
              self->src_read_state = HTTP_SR_READ_INITIAL;
            }

          return G_IO_STATUS_NORMAL;
        }
      else
        {
          self->src_read_state = HTTP_SR_READ_INITIAL;
        }
    }

  *bytes_read = 0;

  if (self->src_chunked)
    {
      /* read as a chunked stream */
      switch (self->src_read_state)
        {
        case HTTP_SR_READ_INITIAL:
          self->src_whole_length = 0;
          self->src_read_state = HTTP_SR_READ_CHUNK_LENGTH;
          z_stream_line_set_poll_partial(stream, FALSE);
          /* fallthrough */
        case HTTP_SR_READ_CHUNK_LENGTH:
          {
            gchar line_buf[32], *line;
            gsize line_length;
            guint32 chunk_length;
            gchar *end;

            res = z_stream_line_get(stream, &line, &line_length, NULL);

            if (res == G_IO_STATUS_NORMAL)
              {
                /* a complete line was read, check if it is a valid chunk length */
                if (line_length >= sizeof(line_buf) - 1)
                  {
                    /*LOG
                      This message indicates that the chunk length line is too long.
                      It is likely caused by a buggy client or server.
                    */
                    z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Chunk length line too long; line='%.*s'", (gint) line_length, line);
                    res = G_IO_STATUS_ERROR;
                    break;
                  }

                /* we already checked that line_buf is large enough */
                memcpy(line_buf, line, line_length);
                line_buf[line_length] = 0;
                chunk_length = strtoul(line_buf, &end, 16);

                if (end == line_buf)
                  {
                    /* hmm... invalid chunk length */
                    /*LOG
                      This message indicates that the chunk length is invalid.
                      It is likely caused by a buggy client or server.
                    */
                    z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Invalid chunk length; line='%s'", line_buf);
                    res = G_IO_STATUS_ERROR;
                    break;
                  }

                /*
                 * NOTE: the string  pointed by end is NUL terminated, thus
                 * we will not overflow our buffer
                 */

                while (*end == ' ')
                  end++;

                if (*end == ';')
                  {
                    /* ignore and strip chunk extensions */
                    *end = 0;
                  }

                if (*end)
                  {
                    /* hmm... invalid chunk length */
                    /*LOG
                      This message indicates that the chunk length is invalid.
                      It is likely caused by a buggy client or server.
                    */
                    z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Invalid chunk length; line='%s'", line_buf);
                    res = G_IO_STATUS_ERROR;
                    break;
                  }

                if ((owner->max_chunk_length && chunk_length > owner->max_chunk_length) ||
                    (chunk_length & 0x80000000))
                  {
                    /*LOG
                      This message indicates that the length of the chunk is larger than allowed
                      or is a negative number. Check the 'max_chunk_length' attribute.
                    */
                    z_proxy_log(self->super.owner, HTTP_POLICY, 2, "Chunk too large; length='%d', max_chunk_length='%d'", chunk_length, owner->max_chunk_length);
                    res = G_IO_STATUS_ERROR;
                    break;
                  }

                if (owner->max_body_length && (guint) self->src_whole_length + chunk_length > owner->max_body_length)
                  {
                    /* this chunk would be over body_length limit */

                    chunk_length = owner->max_body_length - self->src_whole_length;
                    self->src_chunk_left = chunk_length;
                    self->force_nonpersistent_mode = TRUE;
                    self->src_chunk_truncated = TRUE;
                  }

                self->src_chunk_left = chunk_length;
                self->src_last_chunk = chunk_length == 0;
                self->src_read_state = HTTP_SR_READ_CHUNK;
                z_stream_line_set_poll_partial(stream, TRUE);
                /* fall through */
              }
            else
              break;
          }
        case HTTP_SR_READ_CHUNK:

          if (!self->src_last_chunk)
            {
              res = z_stream_read(stream, buf, MIN(self->src_chunk_left, count), &br, &local_error);

              if (res == G_IO_STATUS_NORMAL)
                {
                  self->src_whole_length += br;
                  self->src_chunk_left -= br;
                  *bytes_read = br;
                }
              else if (res == G_IO_STATUS_EOF)
                {
                  /* unexpected eof */
                  /*LOG
                    This message indicates that Zorp unexpectedly got EOF during
                    chunk encoded data transfer. It is likely a caused by a buggy client
                    or server.
                  */
                  z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Unexpected EOF while dechunking stream;");
                  res = G_IO_STATUS_ERROR;
                  break;
                }

              if (self->src_chunk_left == 0)
                {
                  self->src_read_state = HTTP_SR_READ_FOOTER;
                  z_stream_line_set_poll_partial(stream, FALSE);
                }

              break;
            }
          else
            {
              self->src_read_state = HTTP_SR_READ_FOOTER;
              z_stream_line_set_poll_partial(stream, FALSE);
              /* fallthrough */
            }

        case HTTP_SR_READ_FOOTER:
          {
            gchar *line;
            gsize line_length;

            if (!self->src_chunk_truncated)
              {
                res = z_stream_line_get(stream, &line, &line_length, NULL);
              }
            else
              {
                res = G_IO_STATUS_EOF;
              }

            if (res == G_IO_STATUS_NORMAL)
              {
                if (line_length != 0)
                  {
                    /*LOG
                      This message indicates that the chunk footer contains data.
                      It is likely caused by a buggy client or server.
                    */
                    z_proxy_log(self->super.owner, HTTP_VIOLATION, 1, "Chunk footer is not an empty line;");
                    res = G_IO_STATUS_ERROR;
                    break;
                  }

                if (self->src_last_chunk)
                  {
                    res = G_IO_STATUS_EOF;
                  }
                else
                  {
                    self->src_read_state = HTTP_SR_READ_CHUNK_LENGTH;
                    z_stream_line_set_poll_partial(stream, TRUE);
                    /* come back later */
                    res = G_IO_STATUS_AGAIN;
                  }

                break;
              }

            break;
          }
        }
    }
  else
    {
      /* copy until EOF or self->content_length bytes */
      if (self->content_length == HTTP_LENGTH_NONE)
        {
          res = G_IO_STATUS_EOF;
        }
      else
        {
          if (self->src_read_state == HTTP_SR_INITIAL)
            {
              self->src_whole_length = 0;
              self->src_read_state = HTTP_SR_READ_ENTITY;
            }

          if (self->content_length == HTTP_LENGTH_UNKNOWN)
            {
              if (owner->max_body_length && self->src_whole_length + count >= owner->max_body_length)
                {
                  count = owner->max_body_length - self->src_whole_length;
                }

              if (count == 0)
                {
                  self->force_nonpersistent_mode = TRUE;
                  res = G_IO_STATUS_EOF;
                }
              else
                res = z_stream_read(stream, buf, count, &br, &local_error);
            }
          else
            {
              /* for specified content-length, max_body_length has already
                 been processed, and content_length contains the number of
                 bytes to be transferred, but maximum max_body_length */
              if (self->content_length >= 0 && (guint64) self->content_length == self->src_whole_length)
                res = G_IO_STATUS_EOF;
              else
                res = z_stream_read(stream, buf, MIN(count, self->content_length - self->src_whole_length), &br, &local_error);
            }

          if (res == G_IO_STATUS_NORMAL)
            {
              self->src_whole_length += br;
              *bytes_read = br;
            }
        }
    }

  if (local_error)
    g_propagate_error(err, local_error);

  return res;
}
Exemplo n.º 25
0
telnet_client_read(ZStream *stream, GIOCondition cond G_GNUC_UNUSED, gpointer user_data)
{
  TelnetProxy   *self = Z_CAST(user_data, TelnetProxy);
  gboolean      res;

  z_proxy_enter(self);

  res = telnet_read(self, stream, EP_CLIENT);

  z_proxy_return(self, res);
}

static gboolean
telnet_server_read(ZStream *stream G_GNUC_UNUSED, GIOCondition cond G_GNUC_UNUSED, gpointer user_data)
{
  TelnetProxy   *self = Z_CAST(user_data, TelnetProxy);
  gboolean      res;

  z_proxy_enter(self);

  res = telnet_read(self, stream, EP_SERVER);

  z_proxy_return(self, res);
}

static void
telnet_init_stream(TelnetProxy *self, ZEndpoint ep, ZStreamCallback cb, gpointer user_data, GDestroyNotify data_notify)
{
  ZStream *stream = self->super.endpoints[ep] =
    z_stream_push(self->super.endpoints[ep], z_stream_buf_new(NULL, 256 * 1024, Z_SBF_IMMED_FLUSH));
Exemplo n.º 26
0
static GIOStatus
pop3_transfer_src_read(ZTransfer2 *s, ZStream *stream, gchar *buf, gsize count, gsize *bytes_read, GError **err)
{
  GIOStatus ret;
  Pop3Transfer *self = Z_CAST(s, Pop3Transfer);
  Pop3Proxy *owner = Z_CAST(s->owner, Pop3Proxy);

  ret = Z_SUPER(s, ZTransfer2)->src_read(s, stream, buf, count, bytes_read, err);

  if (self->header_state < POP3_HEADER_END &&
       (ret == G_IO_STATUS_NORMAL || (ret == G_IO_STATUS_AGAIN && *bytes_read > 0)))
    {
      if (*bytes_read == 0)
        {
          self->header_state = POP3_HEADER_END;
        }
      else
        {
          gsize bytes_need = *bytes_read;
          if (buf[0] != ' ' && buf[0] != '\t')
            {
              self->header_state = POP3_HEADER_NONE;
              self->actual_header = NULL;
            }

          while (buf[bytes_need - 1] == '\n' || buf[bytes_need - 1] == '\r' || buf[bytes_need - 1] == ' ')
            bytes_need--;

          z_trace(NULL, "Read header line; line='%.*s'", (gint) bytes_need, buf);

          if (self->header_state == POP3_HEADER_NONE)
            {
              if (g_ascii_strncasecmp(buf, FROM, MIN(__builtin_strlen(FROM), bytes_need)) == 0)
                {
                  if (owner->from == NULL)
                    {
                      self->header_state = POP3_HEADER_INSIDE;
                      owner->from = g_string_new_len(buf + __builtin_strlen(FROM), bytes_need - __builtin_strlen(FROM));
                      self->actual_header = owner->from;
                    }
                  else
                    {
                      /* FIXME: Log */
                    }
                }
              else if (g_ascii_strncasecmp(buf, TO, MIN(__builtin_strlen(TO), bytes_need)) == 0)
                {
                  if (owner->to == NULL)
                    {
                      self->header_state = POP3_HEADER_INSIDE;
                      owner->to = g_string_new_len(buf + __builtin_strlen(TO), bytes_need - __builtin_strlen(TO));
                      self->actual_header = owner->to;
                    }
                  else
                    {
                      /* FIXME: Log */
                    }
                }
              else if (g_ascii_strncasecmp(buf, SUBJECT, MIN(__builtin_strlen(SUBJECT), bytes_need)) == 0)
                {
                  if (owner->subject == NULL)
                    {
                      self->header_state = POP3_HEADER_INSIDE;
                      owner->subject = g_string_new_len(buf + __builtin_strlen(SUBJECT), bytes_need - __builtin_strlen(SUBJECT));
                      self->actual_header = owner->subject;
                    }
                  else
                    {
                      /* FIXME: Log */
                    }
                }
            }
          else
            {
              g_string_append(self->actual_header, "\r\n");
              g_string_append_len(self->actual_header, buf, bytes_need);
            }
        }
    }
  return ret;
}
Exemplo n.º 27
0
}

/**
 * z_transfer2_copy_src_to_dst:
 * @s: ZStream instance
 * @cond: condition which triggered this callback
 * @user_data: ZTransfer2 instance passed as a generic pointer
 *
 * This function is registered as the "readable" callback of the client-side
 * stream when no stacking is used, thus data is directly copied to the
 * server-side.
 **/
static gboolean
z_transfer2_copy_src_to_dst(ZStream *s G_GNUC_UNUSED, GIOCondition cond G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED)
{
  ZTransfer2 *self = Z_CAST(user_data, ZTransfer2);

  z_proxy_enter(self->owner);
  z_transfer2_copy_data(self, ZT2E_SOURCE, ZT2E_DEST, NULL);
  z_proxy_leave(self->owner);
  return TRUE;
}

/**
 * z_transfer2_copy_src_to_down:
 * @s: ZStream instance
 * @cond: condition which triggered this callback
 * @user_data: ZTransfer2 instance passed as a generic pointer
 *
 * This function is registered as the "readable" callback of the client-side
 * stream when stacking is used, thus data must be copied to the stacked
Exemplo n.º 28
0
gboolean
z_proxy_ssl_host_iface_check_name_method(ZProxyHostIface *s,
                                         const gchar *host_name,
                                         gchar *reason_buf, gsize reason_len)
{
  ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface);
  gint ext_ndx;
  gboolean found = FALSE, result = FALSE;
  gchar pattern_buf[256];

  if (self->hostname_checked)
    return self->hostname_check_result;

  pattern_buf[0] = 0;
  ext_ndx = X509_get_ext_by_NID(self->server_cert, NID_subject_alt_name, -1);
  if (ext_ndx >= 0)
    {
      /* ok, there's a subjectAltName extension, check that */
      X509_EXTENSION *ext;
      STACK_OF(GENERAL_NAME) *alt_names;
      GENERAL_NAME *gen_name;

      ext = X509_get_ext(self->server_cert, ext_ndx);
      alt_names = X509V3_EXT_d2i(ext);
      if (alt_names)
        {
          gint num, i;

          num = sk_GENERAL_NAME_num(alt_names);

          for (i = 0; i < num; i++)
            {
              gen_name = sk_GENERAL_NAME_value(alt_names, i);
              if (gen_name->type == GEN_DNS)
                {
                  guchar *dnsname = ASN1_STRING_data(gen_name->d.dNSName);
                  guint dnsname_len = ASN1_STRING_length(gen_name->d.dNSName);

                  if (dnsname_len > sizeof(pattern_buf) - 1)
                    {
                      found = TRUE;
                      result = FALSE;
                      break;
                    }

                  memcpy(pattern_buf, dnsname, dnsname_len);
                  pattern_buf[dnsname_len] = 0;
                  /* we have found a DNS name as alternative subject name */
                  found = TRUE;
                  result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf);
                  break;
                }
              else if (gen_name->type == GEN_IPADD)
                {
                  z_inet_ntoa(pattern_buf, sizeof(pattern_buf), *(struct in_addr *) gen_name->d.iPAddress->data);

                  found = TRUE;
                  result = strcmp(host_name, pattern_buf) == 0;
                  break;
                }
            }
          sk_GENERAL_NAME_free(alt_names);
        }
    }

  if (!found)
    {
      /* hmm. there was no subjectAltName (this is deprecated, but still
       * widely used), look up the Subject, most specific CN */
      X509_NAME *name;

      name = X509_get_subject_name(self->server_cert);
      if (X509_NAME_get_text_by_NID(name, NID_commonName, pattern_buf, sizeof(pattern_buf)) != -1)
        {
          result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf);
        }
    }

  if (!result && reason_buf)
    {
      g_snprintf(reason_buf, reason_len, "Certificate does not belong to target host (certificate: %s, host %s)",
                 pattern_buf, host_name);
    }
  self->hostname_checked = TRUE;
  self->hostname_check_result = result;
  return result;

}
Exemplo n.º 29
0
 * smtp_transfer_src_read:
 * @s: ZTransfer instance
 * @stream: stream to read from
 * @buf: buffer to read into
 * @buf_len: size of the buffer
 * @bytes_read: the number of read bytes is returned here
 * @err: GLib error code
 *
 * Reads the incoming data stream, checks for EOF (a single '.' on its own),
 * removes '.' escaping and handles lines longer than the buffer size of ZStreamLine.
 * 
 **/
static GIOStatus
smtp_transfer_src_read(ZTransfer2 *s G_GNUC_UNUSED, ZStream *stream, gchar *buf, gsize buf_len, gsize *bytes_read, GError **err)
{
  SmtpTransfer *self = Z_CAST(s, SmtpTransfer);
  SmtpProxy *owner = Z_CAST(self->super.owner, SmtpProxy);
  GIOStatus res;
  gsize line_len = buf_len - 2; /* to make space to closing CR LF */

  if (G_UNLIKELY(self->src_read_state == SMTP_SR_INITIAL))
    {
      if (owner->add_received_header)
        {
          if (self->received_line == NULL)
            {
              if (!smtp_generate_received(owner, &self->received_line))
                self->src_read_state = SMTP_SR_DATA;
            }
          
          if (self->received_line)
Exemplo n.º 30
0
 **/
typedef struct _ZStreamBlob
{
  ZStream       super;

  gint64        pos;
  ZBlob         *blob;
  GIOCondition  poll_cond;
} ZStreamBlob;

extern ZClass ZStreamBlob__class;

static gboolean
z_stream_blob_watch_prepare(ZStream *s, GSource *src G_GNUC_UNUSED, gint *timeout)
{
  ZStreamBlob   *self = Z_CAST(s, ZStreamBlob);
  gboolean      res;

  z_enter();
  if (timeout)
    *timeout = -1;
  res = FALSE;
  self->poll_cond = 0;
  if (self->super.want_read)
    {
      self->poll_cond |= G_IO_IN;
      res = TRUE;
    }
  if (self->super.want_write)
    {
      self->poll_cond |= G_IO_OUT;