Make a facility for COMSTACK to reject too large packages. The maximum
authorAdam Dickmeiss <adam@indexdata.dk>
Thu, 24 Aug 2006 13:25:44 +0000 (13:25 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Thu, 24 Aug 2006 13:25:44 +0000 (13:25 +0000)
size can be set with cs_ste_max_recv_bytes. By default, maximum is
5000000 (approx 5 MB). If max size is received error comstack error
CSBUFSIZE is returned. The generic frontend server checks for this error
and sends a close + logs if this condition occur.

include/yaz/comstack.h
src/comstack.c
src/seshigh.c
src/tcpip.c

index b335c86..5a264f1 100644 (file)
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: comstack.h,v 1.21 2005-06-25 15:46:01 adam Exp $
+ * $Id: comstack.h,v 1.22 2006-08-24 13:25:44 adam Exp $
  */
 
 /** 
@@ -54,7 +54,7 @@ struct comstack
     int iofile;    /* UNIX file descriptor for iochannel */
     int timeout;   /* how long to wait for trailing blocks (ignored for now) */
     void *cprivate;/* state info for lower stack */
-    int more;      /* connection has extra data in buffer */
+    int max_recv_bytes;      /* max size of incoming package */
     int state;     /* current state */
 #define CS_ST_UNBND      0
 #define CS_ST_IDLE       1
@@ -131,6 +131,7 @@ YAZ_EXPORT void *cs_get_ssl(COMSTACK cs);
 YAZ_EXPORT int cs_set_ssl_ctx(COMSTACK cs, void *ctx);
 YAZ_EXPORT int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname);
 YAZ_EXPORT int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len);
+YAZ_EXPORT void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes);
                                           
 /*
  * error management.
@@ -143,7 +144,8 @@ YAZ_EXPORT int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len);
 #define CSWRONGBUF 4
 #define CSDENY     5
 #define CSERRORSSL 6
-#define CSLASTERROR CSERRORSSL  /* must be the value of last CS error */
+#define CSBUFSIZE  7
+#define CSLASTERROR CSBUFSIZE  /* must be the value of last CS error */
 
 /* backwards compatibility */
 #define CS_SR     PROTO_SR
index 68aeb67..12b5218 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 1995-2005, Index Data ApS
+ * Copyright (C) 1995-2006, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: comstack.c,v 1.15 2005-06-25 15:46:03 adam Exp $
+ * $Id: comstack.c,v 1.16 2006-08-24 13:25:45 adam Exp $
  */
 
 /** 
@@ -14,6 +14,7 @@
 #include <ctype.h>
 #include <errno.h>
 
+#include <yaz/log.h>
 #include <yaz/comstack.h>
 #include <yaz/tcpip.h>
 #include <yaz/unix.h>
@@ -31,7 +32,8 @@ static const char *cs_errlist[] =
     "No data (operation would block)",
     "New data while half of old buffer is on the line (flow control)",
     "Permission denied",
-    "SSL error"
+    "SSL error",
+    "Too large incoming buffer"
 };
 
 const char *cs_errmsg(int n)
@@ -153,7 +155,7 @@ int cs_complete_auto(const unsigned char *buf, int len)
     {
         /* deal with HTTP request/response */
         int i = 2, content_len = 0, chunked = 0;
-        
+
         /* if dealing with HTTP responses - then default
            content length is unlimited (socket close) */
         if (!memcmp(buf, "HTTP/", 5))
@@ -289,6 +291,12 @@ int cs_complete_auto(const unsigned char *buf, int len)
     }
     return completeBER(buf, len);
 }
+
+void cs_set_max_recv_bytes(COMSTACK cs, int max_recv_bytes)
+{
+    cs->max_recv_bytes = max_recv_bytes;
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
index 261b617..2a3fc2f 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: seshigh.c,v 1.95 2006-07-31 12:15:02 adam Exp $
+ * $Id: seshigh.c,v 1.96 2006-08-24 13:25:45 adam Exp $
  */
 /**
  * \file seshigh.c
@@ -340,7 +340,7 @@ void ir_session(IOCHAN h, int event)
             }
             assoc->cs_get_mask = EVENT_INPUT;
             if ((res = cs_get(conn, &assoc->input_buffer,
-                &assoc->input_buffer_len)) <= 0)
+                &assoc->input_buffer_len)) == 0)
             {
                 yaz_log(log_sessiondetail, "Connection closed by client");
                 cs_close(conn);
@@ -348,6 +348,15 @@ void ir_session(IOCHAN h, int event)
                 iochan_destroy(h);
                 return;
             }
+            else if (res < 0)
+            {
+                yaz_log(log_session, "Connection error: %s",
+                        cs_errmsg(cs_errno(conn)));
+                req = request_get(&assoc->incoming); /* get a new request */
+                do_close_req(assoc, Z_Close_protocolError, 
+                             "Incoming package too large", req);
+                return;
+            }
             else if (res == 1) /* incomplete read - wait for more  */
             {
                 if (conn->io_pending & CS_WANT_WRITE)
@@ -378,7 +387,7 @@ void ir_session(IOCHAN h, int event)
                     yaz_log(YLOG_WARN, "PDU dump:");
                     odr_dumpBER(yaz_log_file(), assoc->input_buffer, res);
                     request_release(req);
-                    do_close(assoc, Z_Close_protocolError,"Malformed package");
+                    do_close(assoc, Z_Close_protocolError, "Malformed package");
                 }
                 else
                 {
@@ -2317,7 +2326,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb)
                 assoc->init->implementation_name,
                 odr_prepend(assoc->encode, "GFS", resp->implementationName));
 
-    version = odr_strdup(assoc->encode, "$Revision: 1.95 $");
+    version = odr_strdup(assoc->encode, "$Revision: 1.96 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     resp->implementationVersion = odr_prepend(assoc->encode,
index 02353c9..a55d67c 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: tcpip.c,v 1.18 2006-06-09 12:40:53 adam Exp $
+ * $Id: tcpip.c,v 1.19 2006-08-24 13:25:45 adam Exp $
  */
 /**
  * \file tcpip.c
@@ -187,6 +187,7 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
     p->f_addrstr = tcpip_addrstr;
     p->f_straddr = tcpip_straddr;
     p->f_set_blocking = tcpip_set_blocking;
+    p->max_recv_bytes = 5000000;
 
     p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
     p->event = CS_NONE;
@@ -751,11 +752,17 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize)
         if (!*bufsize)
         {
             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
+            {
+                h->cerrno = CSYSERR;
                 return -1;
+            }
         }
         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
+            {
+                h->cerrno = CSYSERR;
                 return -1;
+            }
 #ifdef __sun__
         yaz_set_errno( 0 );
         /* unfortunatly, sun sometimes forgets to set errno in recv
@@ -800,6 +807,11 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize)
         else if (!res)
             return hasread;
         hasread += res;
+        if (hasread > h->max_recv_bytes)
+        {
+            h->cerrno = CSBUFSIZE;
+            return -1;
+        }
     }
     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
                   hasread, berlen));