Пример #1
0
/**
 * http_ftp_initiate_passive_data:
 * @self: HttpProxy instance
 *
 * This function is called to initiate a passive data connection to the FTP
 * server. If it returns FALSE an active connection might still be
 * attempted. (however it is currently unimplemented).
 *
 * It currently creates the ZAttach object only does not start the actual
 * connection, it is done somewhat later in the http_ftp_complete_data()
 * function.
 **/
static gboolean
http_ftp_initiate_passive_data(HttpProxy *self)
{
  gchar response_msg[1024];
  gint status;
  gchar *start, *end;
  gint i;
  gint ftp_pasv_endpoint[6];
  gchar ip[16];
  ZSockAddr *peer;
  ZAttachParams params;

  if (!http_ftp_communicate(self, "PASV", NULL, &status, response_msg, sizeof(response_msg)))
    return FALSE;

  if (status != 227)
    return FALSE;

  start = strchr(response_msg, '(');

  if (!start)
    {
      /* hmm no '(' in PASV response */
      return FALSE;
    }

  start++;

  for (i = 0; i < 6; i++)
    {
      ftp_pasv_endpoint[i] = strtol(start, &end, 10);

      if ((i < 5 && *end != ',') ||
          (i == 5 && *end != ')'))
        {
          g_string_sprintf(self->error_info, "Response to PASV is invalid; response='%s'", response_msg);
          return FALSE;
        }

      start = end + 1;
    }

  g_snprintf(ip, sizeof(ip), "%d.%d.%d.%d", ftp_pasv_endpoint[0], ftp_pasv_endpoint[1], ftp_pasv_endpoint[2], ftp_pasv_endpoint[3]);
  peer = z_sockaddr_inet_new(ip, 256 * ftp_pasv_endpoint[4] + ftp_pasv_endpoint[5]);

  memset(&params, 0, sizeof(params));
  params.timeout = 30000;

  self->ftp_data_attach = z_attach_new(&self->super, ZD_PROTO_TCP, NULL, peer, &params, NULL, NULL, NULL);
  z_sockaddr_unref(peer);
  /* attach not started yet */

  return TRUE;
}
Пример #2
0
/**
 * z_dispatch_bind_unref: 
 * @self: this
 *
 * Decrement reference count for @self and free if that reaches zero.
 *
 **/
void
z_dispatch_bind_unref(ZDispatchBind *self)
{
  if (self && z_refcount_dec(&self->ref_cnt))
    {
      if (self->type == ZD_BIND_SOCKADDR)
        z_sockaddr_unref(self->sa.addr);
      
      g_free(self);
      
    }
}
Пример #3
0
/**
 * z_dispatch_chain_unref:
 * @self this
 *
 * Decrement the chain's reference counter, destroy it when the counter
 * reaches zero.
 */
static inline void
z_dispatch_chain_unref(ZDispatchChain *self)
{
  z_dispatch_chain_lock(self);  
  if (z_decref(&self->ref_cnt) == 0)
    {
      z_dispatch_chain_unlock(self);

      if (self->accept_queue)
        g_async_queue_unref(self->accept_queue);

      z_dispatch_bind_unref(self->registered_key);
      z_sockaddr_unref(self->bound_addr);
      g_free(self->session_id);
      g_free(self);
    }
  else
    z_dispatch_chain_unlock(self);

}
Пример #4
0
/**
 * z_dispatch_accept:
 * @fdstream Socket stream
 * @client Address of remote endpoint
 * @dest Address of original destination
 * @user_data this
 *
 * Internal callback, called when a new incoming connection is established.
 * Creates and initialises a new ZConnection, and dispatches it to the chain
 * either synchronously by z_dispatch_connection or asynchronously by pushing
 * it to the chain's accept queue. 
 *
 * Note: this function runs in the main thread.
 * 
 * Returns: TRUE
 */
static gboolean
z_dispatch_accept(ZStream *fdstream, ZSockAddr *client, ZSockAddr *dest, gpointer user_data)
{
  ZConnection *conn = NULL;
  ZDispatchChain *chain = (ZDispatchChain *) user_data;
    
  z_enter();
  if (fdstream == NULL)
    {
      z_dispatch_connection(chain, NULL);
      z_return(TRUE);
    }
    
  if (chain->params.common.transparent)
    {
      ZSockAddr *listen_addr = NULL;
      gboolean non_transparent = FALSE;
      GList *p;

      switch (chain->registered_key->type)
        {
        case ZD_BIND_SOCKADDR:
          listen_addr = chain->registered_key->sa.addr;
          non_transparent = z_sockaddr_equal(listen_addr, dest);
          break;
        case ZD_BIND_IFACE:
        case ZD_BIND_IFACE_GROUP:

          /* NOTE: we are running in the main thread just like the
           * code that manipulates chain->listeners, thus we don't need to
           * lock here. This is even true for threaded listeners as
           * z_dispatch_accept runs in the main thread in that case too. 
           */

          for (p = chain->listeners; p; p = p->next)
            {
              ZListener *l = ((ZListenerEntry *) p->data)->listener;

              if (z_sockaddr_equal(l->local, dest))
                {
                  non_transparent = TRUE;
                  listen_addr = l->local;
                  break;
                }
            }
          break;
        }

      if (non_transparent)
        {
          gchar buf1[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING];
          /*LOG
            This message indicates that Listener/Receiver was
            configured to be accept transparent connections, but it
            was connected directly.  Configure it either
            non-transparent or deny direct access to it and set up the
            appropriate TPROXY rule.

            @see: Listener 
            @see: Receiver
          */
          z_log(chain->session_id, CORE_ERROR, 1, "Transparent listener connected directly, dropping connection; local='%s', client_local='%s'", 
                z_sockaddr_format(listen_addr, buf1, sizeof(buf1)),
                z_sockaddr_format(dest, buf2, sizeof(buf2)));
          z_stream_close(fdstream, NULL);
          z_stream_unref(fdstream);
          z_sockaddr_unref(client);
          z_sockaddr_unref(dest);
          z_return(TRUE);
        }
    }
      
  conn = z_connection_new();
  conn->remote = client;
  conn->dest = dest;
  conn->local = z_sockaddr_ref(conn->dest);
  conn->dispatch_bind = z_dispatch_bind_ref(chain->registered_key);
  conn->protocol = chain->registered_key->protocol;
  conn->stream = fdstream;
    
  if (chain->threaded)
    g_async_queue_push(chain->accept_queue, conn);
  else
    z_dispatch_connection(chain, conn);
    
  z_return(TRUE);
}