"Fossies" - the Fresh Open Source Software Archive

Member "zorp-7.0.4/modules/apr/apr.cc" (28 Oct 2019, 10414 Bytes) of package /linux/privat/zorp-7.0.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "apr.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 7.0.1_vs_7.0.2.

    1 /***************************************************************************
    2  *
    3  * Copyright (c) 2000-2015 BalaBit IT Ltd, Budapest, Hungary
    4  * Copyright (c) 2015-2018 BalaSys IT Ltd, Budapest, Hungary
    5  *
    6  * This program is free software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License as published by
    8  * the Free Software Foundation; either version 2 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License along
   17  * with this program; if not, write to the Free Software Foundation, Inc.,
   18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   19  *
   20  *
   21  ***************************************************************************/
   22 
   23 #include <zorp/proxy.h>
   24 #include <zorpll/registry.h>
   25 #include <zorpll/streambuf.h>
   26 
   27 #define APR_DUMP "apr.dump"
   28 #define APR_DEBUG "apr.debug"
   29 #define APR_ERROR "apr.error"
   30 
   31 static const guint stream_buf_size = 65536;
   32 
   33 typedef struct
   34 {
   35   ZProxy super;
   36   ZPoll *poll;
   37   gint timeout;
   38   gboolean need_server_connect;
   39   gint copy_client_data;
   40   gboolean quit;
   41   ZPktBuf *data_buffer[EP_MAX];
   42   /**
   43    * Will pass stream to instance of this proxy class when set.
   44    */
   45   ZPolicyObj *service;
   46   gsize buffer_written_to_client;
   47 } APRProxy;
   48 
   49 static ZStream *
   50 get_stream(APRProxy *self, gint side)
   51 {
   52   return self->super.endpoints[side];
   53 }
   54 
   55 extern ZClass APRProxy__class;
   56 static gboolean apr_read_callback(ZStream *stream, GIOCondition  /* cond */, gpointer user_data);
   57 
   58 static void
   59 apr_setup_stream(APRProxy *self, gint ep)
   60 {
   61   self->super.endpoints[ep] = z_stream_push(self->super.endpoints[ep], z_stream_buf_new(NULL, stream_buf_size, Z_SBF_IMMED_FLUSH));
   62   z_poll_add_stream(self->poll, self->super.endpoints[ep]);
   63   z_stream_set_callback(get_stream(self, ep), G_IO_IN, apr_read_callback, self, NULL);
   64   z_stream_set_cond(get_stream(self, ep), G_IO_IN, TRUE);
   65 }
   66 
   67 static gboolean
   68 apr_config_set_defaults(APRProxy *self)
   69 {
   70   int i;
   71   for (i = 0; i < EP_MAX; ++i)
   72     self->data_buffer[i] = z_pktbuf_new();
   73 
   74   self->poll = z_poll_new();
   75   self->timeout = 600000;
   76   self->buffer_written_to_client = 0;
   77 
   78   return TRUE;
   79 }
   80 
   81 static gboolean
   82 apr_continue_with_proxy(APRProxy *self)
   83 {
   84   gint i;
   85   gboolean called;
   86   ZPolicyObj *pyres;
   87 
   88   for (i = EP_CLIENT; i < EP_MAX; i++)
   89     {
   90       if (self->super.endpoints[i])
   91         {
   92           /* NOTE: we flush out streams as some packets might be stucked */
   93           if (!z_stream_broken(self->super.endpoints[i]))
   94             {
   95               z_stream_buf_flush(self->super.endpoints[i]);
   96               z_stream_set_nonblock(self->super.endpoints[i], FALSE);
   97             }
   98 
   99           /* Prepare stream for passing to other proxy */
  100           z_stream_set_cond(self->super.endpoints[i], G_IO_IN, FALSE);
  101           z_poll_remove_stream(self->poll, self->super.endpoints[i]);
  102 
  103           self->super.endpoints[i] = z_stream_pop(self->super.endpoints[i]);
  104 
  105           gssize len = self->data_buffer[i]->length;
  106           if (i == EP_CLIENT && self->buffer_written_to_client)
  107             len = self->buffer_written_to_client;
  108 
  109           z_stream_unget(self->super.endpoints[i], self->data_buffer[i]->data, len, NULL);
  110         }
  111     }
  112 
  113   z_policy_lock(self->super.thread);
  114   pyres = z_policy_call(self->super.handler, "startService", z_policy_var_build("(O)", self->service), &called, self->super.session_id);
  115   z_policy_var_unref(pyres);
  116   z_policy_unlock(self->super.thread);
  117 
  118   /* release, but don't close fds on success */
  119   for (i = EP_CLIENT; i < EP_MAX; i++)
  120     {
  121       if (self->super.endpoints[i])
  122         {
  123           if (TRUE)
  124             z_stream_unref(self->super.endpoints[i]);
  125           else
  126             z_stream_close(self->super.endpoints[i], NULL);
  127           self->super.endpoints[i] = NULL;
  128         }
  129     }
  130 
  131   return TRUE;
  132 }
  133 
  134 static void
  135 apr_register_vars(APRProxy *self)
  136 {
  137   z_proxy_var_new(&self->super, "timeout",
  138                   Z_VAR_GET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
  139                   Z_VAR_TYPE_INT, &self->timeout);
  140 
  141   z_proxy_var_new(&self->super, "copy_client_data",
  142                   Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
  143                   Z_VAR_TYPE_INT, &self->copy_client_data);
  144 
  145   z_proxy_var_new(&self->super, "need_server_connect",
  146                   Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
  147                   Z_VAR_TYPE_INT, &self->need_server_connect);
  148 
  149   z_proxy_var_new(&self->super, "quit",
  150                   Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
  151                   Z_VAR_TYPE_INT, &self->quit);
  152 }
  153 
  154 static gboolean
  155 apr_config(ZProxy *s)
  156 {
  157   APRProxy *self = (APRProxy *) s;
  158 
  159   z_proxy_enter (self);
  160   apr_config_set_defaults(self);
  161   apr_register_vars(self);
  162   z_proxy_return(self, Z_SUPER(s, ZProxy)->config(s));
  163 }
  164 
  165 /**
  166  * Reads data into packet from stream.
  167  *
  168  * @internal
  169  */
  170 static inline gboolean
  171 apr_read(ZStream *stream, ZPktBuf *packet, gsize length)
  172 {
  173   GIOStatus status;
  174   gsize br;
  175 
  176   if (packet->allocated < packet->length + length)
  177     z_pktbuf_resize(packet, packet->length + length);
  178 
  179   status = z_stream_read(stream, (gchar*) (z_pktbuf_end(packet)), length, &br, NULL);
  180 
  181   if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF)
  182     {
  183       /* error already logged */
  184       return FALSE;
  185     }
  186   else if (status == G_IO_STATUS_NORMAL)
  187     {
  188       packet->length += br;
  189     }
  190 
  191   return TRUE;
  192 }
  193 
  194 static void
  195 apr_detect(APRProxy *self, gint side)
  196 {
  197   ZPktBuf *buf = self->data_buffer[side];
  198 
  199   z_proxy_log_data_dump(self, APR_DUMP, 8, (gchar*) buf->data, buf->length);
  200   z_policy_lock(self->super.thread);
  201   PyObject *data = PyString_FromStringAndSize(reinterpret_cast<char *>(buf->data), buf->length);
  202   if (data)
  203     {
  204       ZPolicyObj *pyres = z_policy_call(self->super.handler, "detect", z_policy_var_build("(iO)", side, data),
  205                                         nullptr, self->super.session_id);
  206       Py_XDECREF(data);
  207       if (pyres)
  208         {
  209           if (pyres != z_policy_none)
  210             {
  211               self->quit = TRUE;
  212               self->service = pyres;
  213             }
  214           else
  215             {
  216               z_policy_var_unref(pyres);
  217             }
  218         }
  219     }
  220   z_policy_unlock(self->super.thread);
  221 }
  222 
  223 static void
  224 connect_server(APRProxy *self)
  225 {
  226   if (get_stream(self, EP_SERVER))
  227     return;
  228   z_proxy_log(self, "APR.debug", 6, "connect server");
  229   if (z_proxy_connect_server(&self->super, NULL, 0))
  230     apr_setup_stream(self, EP_SERVER);
  231 }
  232 
  233 static gboolean
  234 apr_read_callback(ZStream *stream, GIOCondition  /* cond */, gpointer user_data)
  235 {
  236   APRProxy *self = static_cast<APRProxy *>(user_data);
  237   gint side = (stream == get_stream(self, EP_CLIENT)) ? EP_CLIENT : EP_SERVER;
  238   ZPktBuf *incoming_packet = self->data_buffer[side];
  239 
  240   if (!apr_read(stream, incoming_packet, stream_buf_size))
  241     goto error;
  242 
  243   z_proxy_log(self, "APR.debug", 6, "Received data");
  244   apr_detect(self, side);
  245   if (self->need_server_connect)
  246     connect_server(self);
  247   if (self->copy_client_data && get_stream(self, EP_SERVER))
  248     {
  249       gsize written;
  250       gsize length = static_cast<guint>(self->copy_client_data) >
  251                      self->data_buffer[EP_CLIENT]->length ?  self->data_buffer[EP_CLIENT]->length : self->copy_client_data;
  252       self->copy_client_data = 0;
  253       z_stream_write(get_stream(self, EP_SERVER), self->data_buffer[EP_CLIENT]->data, length, &written, NULL);
  254       self->buffer_written_to_client = written;
  255     }
  256   return TRUE;
  257 
  258 error:
  259   self->quit = TRUE;
  260   incoming_packet->length = 0;
  261   return FALSE;
  262 }
  263 
  264 static void
  265 apr_wakeup(ZProxy *s)
  266 {
  267   APRProxy *self = (APRProxy *) s;
  268 
  269   z_poll_wakeup(self->poll);
  270 }
  271 
  272 /*
  273  * Main proxy loop.
  274  *
  275  * @param[in] s APRProxy instance.
  276  */
  277 static void
  278 apr_main(ZProxy *s)
  279 {
  280   APRProxy *self = Z_CAST(s, APRProxy);
  281   guint ep;
  282 
  283   /* construct and initialize */
  284 
  285   /* start */
  286   apr_setup_stream(self, EP_CLIENT);
  287 
  288   if (self->need_server_connect)
  289     connect_server(self);
  290 
  291   /* process packets */
  292   z_proxy_log(self, APR_DEBUG, 6, "Entering main-loop;");
  293   while (!self->quit && z_poll_iter_timeout(self->poll, self->timeout))
  294     {
  295       if (!z_proxy_loop_iteration(s))
  296         self->quit = TRUE;
  297     }
  298 
  299   /* pass streams as neccessary */
  300   if (self->service && !apr_continue_with_proxy(self))
  301     {
  302       //z_proxy_log(self, SOCKS_DEBUG, 6, "Unable to pass streams to stacked proxy;");
  303     }
  304 
  305 
  306   //z_proxy_log(self, SOCKS_DEBUG, 6, "Leaving main-loop;");
  307 
  308   for (ep = EP_CLIENT; ep < EP_MAX; ep++)
  309     {
  310       if (self->super.endpoints[ep])
  311         {
  312           /* NOTE: we flush out streams as some packets might be stucked */
  313           if (!z_stream_broken(self->super.endpoints[ep]))
  314             {
  315               z_stream_buf_flush(self->super.endpoints[ep]);
  316               z_stream_set_nonblock(self->super.endpoints[ep], FALSE);
  317             }
  318 
  319           z_poll_remove_stream(self->poll, self->super.endpoints[ep]);
  320         }
  321     }
  322 }
  323 
  324 /**
  325  * APRProxy constructor. Allocates and initializes a proxy instance,
  326  * starts proxy thread.
  327  */
  328 static ZProxy *
  329 apr_proxy_new(ZProxyParams *params)
  330 {
  331   APRProxy *self;
  332 
  333   z_enter ();
  334   self = Z_CAST(z_proxy_new(Z_CLASS(APRProxy), params), APRProxy);
  335   z_return((ZProxy *) self);
  336 }
  337 
  338 /*
  339  * APRProxy free method.
  340  *
  341  * @param[in] s APRProxy instance.
  342  */
  343 void
  344 apr_proxy_free(ZObject *s)
  345 {
  346   APRProxy *self = Z_CAST(s, APRProxy);
  347 
  348   z_enter();
  349 
  350   for (int i = 0; i < EP_MAX; ++i)
  351     z_pktbuf_unref(self->data_buffer[i]);
  352 
  353   z_poll_unref(self->poll);
  354   if (self->service)
  355     z_policy_var_unref(self->service);
  356   z_proxy_free_method(s);
  357   z_return();
  358 }
  359 
  360 ZProxyFuncs apr_proxy_funcs =
  361   {
  362     {
  363       Z_FUNCS_COUNT (ZProxy),
  364       apr_proxy_free,
  365     },
  366     apr_config,
  367     NULL,
  368     apr_main,
  369     NULL,
  370     NULL,
  371     NULL,
  372     NULL,
  373     apr_wakeup,
  374   };
  375 
  376 Z_CLASS_DEF(APRProxy, ZProxy, apr_proxy_funcs);
  377 
  378 static ZProxyModuleFuncs apr_module_funcs =
  379   {
  380     apr_proxy_new,
  381     NULL
  382   };
  383 
  384 /**
  385  * Module initialization function. Registers the APR proxy type.
  386  *
  387  * @return TRUE if module usage is permitted by the licence.
  388  */
  389 gint
  390 zorp_module_init(void)
  391 {
  392   z_registry_add("apr", ZR_PROXY, &apr_module_funcs);
  393   return TRUE;
  394 }