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.
  *
  * 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 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
     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 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.
                                           
 /*
  * 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 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
 
 /* 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.
  *
  * 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 <ctype.h>
 #include <errno.h>
 
+#include <yaz/log.h>
 #include <yaz/comstack.h>
 #include <yaz/tcpip.h>
 #include <yaz/unix.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",
     "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)
 };
 
 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;
     {
         /* 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))
         /* 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);
 }
     }
     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
 /*
  * 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.
  *
  * 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
  */
 /**
  * \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->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);
             {
                 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;
             }
                 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)
             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);
                     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
                 {
                 }
                 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));
 
                 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,
     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.
  *
  * 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
  */
 /**
  * \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->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;
 
     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)))
         if (!*bufsize)
         {
             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
+            {
+                h->cerrno = CSYSERR;
                 return -1;
                 return -1;
+            }
         }
         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
         }
         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
+            {
+                h->cerrno = CSYSERR;
                 return -1;
                 return -1;
+            }
 #ifdef __sun__
         yaz_set_errno( 0 );
         /* unfortunatly, sun sometimes forgets to set errno in recv
 #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;
         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));
     }
     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
                   hasread, berlen));