From: Adam Dickmeiss Date: Thu, 24 Aug 2006 13:25:44 +0000 (+0000) Subject: Make a facility for COMSTACK to reject too large packages. The maximum X-Git-Tag: YAZ.2.1.28~26 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=32687c1504015e0675d49983707576f8db9b7bfc Make a facility for COMSTACK to reject too large packages. The maximum 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. --- diff --git a/include/yaz/comstack.h b/include/yaz/comstack.h index b335c86..5a264f1 100644 --- a/include/yaz/comstack.h +++ b/include/yaz/comstack.h @@ -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 diff --git a/src/comstack.c b/src/comstack.c index 68aeb67..12b5218 100644 --- a/src/comstack.c +++ b/src/comstack.c @@ -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 #include +#include #include #include #include @@ -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 diff --git a/src/seshigh.c b/src/seshigh.c index 261b617..2a3fc2f 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -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, diff --git a/src/tcpip.c b/src/tcpip.c index 02353c9..a55d67c 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -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));