Compare commits

...

5 Commits

Author SHA1 Message Date
Vladimir Dubrovin
f5ff81d0bc remove dead code
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-08-08 21:10:57 +03:00
Vladimir Dubrovin
8c2ad56665 Use memmove for overlapping region 2026-08-08 20:46:52 +03:00
Vladimir Dubrovin
a986ed7a07 Add linger timeout 2026-08-08 19:13:02 +03:00
Vladimir Dubrovin
eceb5a22df Add outsize parameter to en64 2026-08-08 17:58:49 +03:00
Vladimir Dubrovin
7eba73fc8f
Create SECURITY.md 2026-08-08 17:29:57 +03:00
13 changed files with 84 additions and 36 deletions

14
SECURITY.md Normal file
View File

@ -0,0 +1,14 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 0.9.8 | :white_check_mark: |
| < 0.9.8 | :x: |
## Reporting a Vulnerability
Report to 3proxy@3proxy.org or via [GitHub security reporting](https://github.com/3proxy/3proxy/security)
For High/Critical patched version is released within 2 weeks

View File

@ -199,6 +199,13 @@ is disabled even when built, because current Linux does not implement
SPLICE_F_MOVE, so no real zero-copy takes place and the read/write path is faster SPLICE_F_MOVE, so no real zero-copy takes place and the read/write path is faster
for most traffic. Rebuild with -DWITHSPLICE to make -s available, -s0 disables it for most traffic. Rebuild with -DWITHSPLICE to make -s available, -s0 disables it
explicitly. explicitly.
.br
.B -C
(for TCP services) keep the session until both sides close the connection
(TCP half-close). By default a connection closed by any of the sides terminates
the session, buffered data is delivered before the sockets are closed. Half-close
is required for the protocols where one of the sides closes its sending side and
expects the answer, it may cause the sockets to be kept in CLOSE_WAIT state.
.br .br
(for dnspr) simple, do not use resolver and 3proxy cache, always use external DNS server. (for dnspr) simple, do not use resolver and 3proxy cache, always use external DNS server.
.br .br
@ -427,9 +434,9 @@ can use %A as produced archive name and %F as filename.
.br .br
.BR timeouts .BR timeouts
\fI<BYTE_SHORT>\fR \fI<BYTE_LONG>\fR \fI<STRING_SHORT>\fR \fI<STRING_LONG>\fR \fI<CONNECTION_SHORT>\fR \fI<CONNECTION_LONG>\fR \fI<DNS>\fR \fI<CHAIN>\fR \fI<CONNECT>\fR \fI<CONNECTBACK>\fR \fI<BYTE_SHORT>\fR \fI<BYTE_LONG>\fR \fI<STRING_SHORT>\fR \fI<STRING_LONG>\fR \fI<CONNECTION_SHORT>\fR \fI<CONNECTION_LONG>\fR \fI<DNS>\fR \fI<CHAIN>\fR \fI<CONNECT>\fR \fI<CONNECTBACK>\fR \fI<LINGER>\fR
.br .br
Sets timeout values, defaults 1, 5, 30, 60, 180, 1800, 15, 60, 15, 5. Sets timeout values, defaults 1, 5, 30, 60, 180, 1800, 15, 60, 15, 5, 5.
.br .br
\fBBYTE_SHORT\fR short timeout for single byte, is usually used for receiving single byte from stream. \fBBYTE_SHORT\fR short timeout for single byte, is usually used for receiving single byte from stream.
.br .br
@ -447,7 +454,12 @@ can use %A as produced archive name and %F as filename.
.br .br
\fBCHAIN\fR timeout for reading data from chained connection \fBCHAIN\fR timeout for reading data from chained connection
.br .br
default timeouts 1 5 30 60 180 1800 15 60 15 5 \fBLINGER\fR timeout to deliver buffered data after one of the sides has closed
its sending side, also used as SO_LINGER value on outgoing connections. Too small
value may cause the tail of the data to be lost on slow connections, too large one
delays release of the sockets.
.br
default timeouts 1 5 30 60 180 1800 15 60 15 5 5
.br .br
.BR maxseg .BR maxseg

View File

@ -6,6 +6,7 @@
*/ */
#include <string.h> #include <string.h>
#include <limits.h>
static const unsigned char base64digits[] = static const unsigned char base64digits[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@ -23,8 +24,10 @@ static const unsigned char base64val[] = {
}; };
#define DECODE64(c) ((c > 32 && c<127)? base64val[(int)c] : BAD) #define DECODE64(c) ((c > 32 && c<127)? base64val[(int)c] : BAD)
unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen) unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen, int outsize)
{ {
if (inlen < 0 || inlen > (INT_MAX - 2) || outsize < 1) return NULL;
if (((inlen + 2) / 3) > ((outsize - 1) / 4)) return NULL;
for (; inlen > 0; inlen -= 3, in+=3) for (; inlen > 0; inlen -= 3, in+=3)
{ {
@ -42,6 +45,7 @@ int de64 (const char *in, char *out, int maxlen)
int len = 0; int len = 0;
register unsigned char digit1, digit2, digit3, digit4; register unsigned char digit1, digit2, digit3, digit4;
if (maxlen < 0) return(-1);
if (in[0] == '+' && in[1] == ' ') if (in[0] == '+' && in[1] == ' ')
in += 2; in += 2;
if (*in == '\r') if (*in == '\r')
@ -61,20 +65,23 @@ int de64 (const char *in, char *out, int maxlen)
if (digit4 != '=' && DECODE64(digit4) == BAD) if (digit4 != '=' && DECODE64(digit4) == BAD)
return(-1); return(-1);
in += 4; in += 4;
if (len >= maxlen) return (len);
*out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
++len; ++len;
if (digit3 != '=') if (digit3 != '=')
{ {
if (len >= maxlen) return (len);
*out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
++len; ++len;
if (digit4 != '=') if (digit4 != '=')
{ {
if (len >= maxlen) return (len);
*out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
++len; ++len;
} }
} }
} while } while
(*in && *in != '\r' && digit4 != '=' && (maxlen-=4) >= 4); (*in && *in != '\r' && digit4 != '=');
return (len); return (len);
} }

View File

@ -130,7 +130,7 @@ int timeouts[12] = {
60, /* CHAIN_TO */ 60, /* CHAIN_TO */
15, /* CONNECT_TO */ 15, /* CONNECT_TO */
5, /* CONNBACK_TO */ 5, /* CONNBACK_TO */
0, 5, /* LINGER_TO */
0 0
}; };
@ -650,7 +650,7 @@ int doconnect(struct clientparam * param){
if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);} if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);}
} }
else { else {
struct linger lg = {1,conf.timeouts[SINGLEBYTE_S]}; struct linger lg = {1,conf.timeouts[LINGER_TO]};
if(SAISNULL(&param->sinsr)){ if(SAISNULL(&param->sinsr)){
if(SAISNULL(&param->req)) { if(SAISNULL(&param->req)) {

View File

@ -182,12 +182,12 @@ void * imappchild(struct clientparam* param) {
if(method == CL_PLAIN){ if(method == CL_PLAIN){
i = (int)strlen((char *)param->extusername); i = (int)strlen((char *)param->extusername);
res = (int)strlen((char *)pb); res = (int)strlen((char *)pb);
if(((i + res + 4) / 3) * 4 + 1 > (int)sizeof(srvbuf)) {RETURN(693);} if(i + res + 2 > (int)sizeof(ibuf)) {RETURN(693);}
ibuf[0] = 0; ibuf[0] = 0;
memcpy(ibuf + 1, param->extusername, i); memcpy(ibuf + 1, param->extusername, i);
ibuf[i + 1] = 0; ibuf[i + 1] = 0;
memcpy(ibuf + i + 2, pb, res); memcpy(ibuf + i + 2, pb, res);
en64(ibuf, srvbuf, i + res + 2); if(!en64(ibuf, srvbuf, i + res + 2, (int)sizeof(srvbuf))) {RETURN(693);}
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 || if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE PLAIN ", 20, conf.timeouts[STRING_S])!= 20 || socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE PLAIN ", 20, conf.timeouts[STRING_S])!= 20 ||
socksend(param, param->remsock, srvbuf, (int)strlen((char *)srvbuf), conf.timeouts[STRING_S]) <= 0 || socksend(param, param->remsock, srvbuf, (int)strlen((char *)srvbuf), conf.timeouts[STRING_S]) <= 0 ||
@ -200,15 +200,13 @@ void * imappchild(struct clientparam* param) {
{RETURN(699);} {RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]); i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);} if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)param->extusername) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);} if(!en64(param->extusername, ibuf, (int)strlen((char *)param->extusername), (int)sizeof(ibuf))) {RETURN(693);}
en64(param->extusername, ibuf, (int)strlen((char *)param->extusername));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 || if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2) socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);} {RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]); i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);} if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)pb) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);} if(!en64(pb, ibuf, (int)strlen((char *)pb), (int)sizeof(ibuf))) {RETURN(693);}
en64(pb, ibuf, (int)strlen((char *)pb));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 || if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2) socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);} {RETURN(699);}

View File

@ -929,7 +929,8 @@ for(;;){
if(param->extusername){ if(param->extusername){
hlen += sprintf((char*)buf + hlen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization"); hlen += sprintf((char*)buf + hlen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization");
sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)""); sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
hlen = (int)(en64(username, buf + hlen, (int)strlen((char *)username)) - buf); if(!(sb = en64(username, buf + hlen, (int)strlen((char *)username), bufsize - hlen))) {RETURN(21);}
hlen = (int)(sb - buf);
hlen += sprintf((char*)buf + hlen, "\r\n"); hlen += sprintf((char*)buf + hlen, "\r\n");
} }
hlen += sprintf((char*)buf + hlen, "\r\n"); hlen += sprintf((char*)buf + hlen, "\r\n");

View File

@ -271,7 +271,7 @@ extern int demon;
unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf); unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf);
unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int tohex); unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int tohex);
int de64 (const unsigned char *in, unsigned char *out, int maxlen); int de64 (const unsigned char *in, unsigned char *out, int maxlen);
unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen); unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen, int outsize);
void tohex(unsigned char *in, unsigned char *out, int len); void tohex(unsigned char *in, unsigned char *out, int len);
void fromhex(unsigned char *in, unsigned char *out, int len); void fromhex(unsigned char *in, unsigned char *out, int len);

View File

@ -329,6 +329,8 @@ int MODULEMAINFUNC (int argc, char** argv){
#endif #endif
#ifdef WITHSPLICE #ifdef WITHSPLICE
" -s Use splice() - no filtering for data, off by default\n" " -s Use splice() - no filtering for data, off by default\n"
" -C keep the session until both sides close the connection (TCP half-close),\n"
" by default connection closed by any of the sides terminates the session\n"
#endif #endif
"-g(GRACE_TRAFF,GRACE_NUM,GRACE_DELAY) - delay GRACE_DELAY milliseconds before polling if average polling size below GRACE_TRAFF bytes and GRACE_NUM read operations in single directions are detected within 1 second to minimize polling\n" "-g(GRACE_TRAFF,GRACE_NUM,GRACE_DELAY) - delay GRACE_DELAY milliseconds before polling if average polling size below GRACE_TRAFF bytes and GRACE_NUM read operations in single directions are detected within 1 second to minimize polling\n"
" -fFORMAT logging format (see documentation)\n" " -fFORMAT logging format (see documentation)\n"
@ -596,6 +598,9 @@ int MODULEMAINFUNC (int argc, char** argv){
case 'g': case 'g':
sscanf(argv[i]+2, "%d,%d,%d", &srv.gracetraf, &srv.gracenum, &srv.gracedelay); sscanf(argv[i]+2, "%d,%d,%d", &srv.gracetraf, &srv.gracenum, &srv.gracedelay);
break; break;
case 'C':
srv.halfclose = *(argv[i]+2)? atoi(argv[i]+2) : 1;
break;
case 's': case 's':
#ifdef WITHSPLICE #ifdef WITHSPLICE
if(isudp || srv.service == S_ADMIN) if(isudp || srv.service == S_ADMIN)
@ -1247,6 +1252,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
#ifdef WITHSPLICE #ifdef WITHSPLICE
srv->usesplice = 0; srv->usesplice = 0;
#endif #endif
srv->halfclose = 0;
memset(param, 0, sizeof(struct clientparam)); memset(param, 0, sizeof(struct clientparam));
param->srv = srv; param->srv = srv;
param->version = srv->version; param->version = srv->version;

View File

@ -70,7 +70,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
if(user){ if(user){
len += sprintf((char *)buf + len, "Proxy-Authorization: Basic "); len += sprintf((char *)buf + len, "Proxy-Authorization: Basic ");
sprintf((char *)username, "%.128s:%.128s", user, pass?pass:(unsigned char *)""); sprintf((char *)username, "%.128s:%.128s", user, pass?pass:(unsigned char *)"");
en64(username, buf+len, (int)strlen((char *)username)); if(!en64(username, buf+len, (int)strlen((char *)username), 2048 - len)) return 21;
len = (int)strlen((char *)buf); len = (int)strlen((char *)buf);
len += sprintf((char *)buf + len, "\r\n"); len += sprintf((char *)buf + len, "\r\n");
} }
@ -270,8 +270,6 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
int r2; int r2;
int saved = 0; int saved = 0;
if(param->remsock != INVALID_SOCKET && param->operation != UDPASSOC) {
}
if((SAISNULL(&param->req) || !*SAPORT(&param->req)) && param->operation != UDPASSOC) { if((SAISNULL(&param->req) || !*SAPORT(&param->req)) && param->operation != UDPASSOC) {
return 100; return 100;
} }

View File

@ -237,14 +237,14 @@ void * smtppchild(struct clientparam* param) {
param->nwrites++; param->nwrites++;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(680);} if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(680);}
en64(param->extusername, buf, (int)strlen((char *)param->extusername)); if(!en64(param->extusername, buf, (int)strlen((char *)param->extusername), (int)sizeof(buf))) {RETURN(683);}
socksend(param, param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]); socksend(param, param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);
param->statscli64+=(i+2); param->statscli64+=(i+2);
param->nwrites+=2; param->nwrites+=2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(681);} if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(681);}
en64(param->extpassword, buf, (int)strlen((char *)param->extpassword)); if(!en64(param->extpassword, buf, (int)strlen((char *)param->extpassword), (int)sizeof(buf))) {RETURN(683);}
socksend(param, param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]); socksend(param, param->remsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);
param->statscli64+=(i+2); param->statscli64+=(i+2);
@ -259,12 +259,12 @@ void * smtppchild(struct clientparam* param) {
*username = 0; *username = 0;
i = (int)strlen((char *)param->extusername) + 1; i = (int)strlen((char *)param->extusername) + 1;
res = (int)strlen((char *)param->extpassword); res = (int)strlen((char *)param->extpassword);
if(i + 1 + res >= (int)sizeof(username) || ((i + 1 + res + 2) / 3) * 4 + 1 > (int)sizeof(buf)) {RETURN(683);} if(i + 1 + res >= (int)sizeof(username)) {RETURN(683);}
memcpy(username+1, param->extusername, i); memcpy(username+1, param->extusername, i);
i++; i++;
memcpy(username + i, param->extpassword, res); memcpy(username + i, param->extpassword, res);
i+=res; i+=res;
en64(username, buf, i); if(!en64(username, buf, i, (int)sizeof(buf))) {RETURN(683);}
i = (int)strlen((char *)buf); i = (int)strlen((char *)buf);
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]); socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]);

View File

@ -171,12 +171,13 @@ int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char *
if(delim != EOF){ if(delim != EOF){
unsigned char *d = (unsigned char *)memchr(base + *offp, delim, n); unsigned char *d = (unsigned char *)memchr(base + *offp, delim, n);
if(d) n = (int)(d - (base + *offp)) + 1; if(d) n = (int)(d - (base + *offp)) + 1;
memcpy(buf + i, base + *offp, n); /* caller may use param->srvbuf / param->clibuf as buf */
memmove(buf + i, base + *offp, n);
i += n; *offp += n; i += n; *offp += n;
if(d || i >= bufsize) return i; if(d || i >= bufsize) return i;
} }
else { else {
memcpy(buf + i, base + *offp, n); memmove(buf + i, base + *offp, n);
i += n; *offp += n; i += n; *offp += n;
if(i >= bufsize) return i; if(i >= bufsize) return i;
} }

View File

@ -44,7 +44,13 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
#define MIN(a,b) ((a>b)?b:a) #define MIN(a,b) ((a>b)?b:a)
#define RETURN(xxx) { res = xxx; goto CLEANRET; } #define RETURN(xxx) { res = xxx; goto CLEANRET; }
/* Unless half-close is requested for the service, a connection closed by any
of the sides terminates the session, remaining buffered data is delivered
before the sockets are closed. */
#define SESSIONEND (!halfclose && (CLIENTTERMREAD || SERVERTERMREAD))
int sockmap(struct clientparam * param, int timeo, int usesplice){ int sockmap(struct clientparam * param, int timeo, int usesplice){
int halfclose = param->srv->halfclose;
uint64_t fromclient=0x7fffffffffffffff, fromserver =0x7fffffffffffffff; uint64_t fromclient=0x7fffffffffffffff, fromserver =0x7fffffffffffffff;
uint64_t inclientbuf = 0, inserverbuf = 0; uint64_t inclientbuf = 0, inserverbuf = 0;
int FROMCLIENT = 1, TOCLIENTBUF = 1, TOSERVER = 1, int FROMCLIENT = 1, TOCLIENTBUF = 1, TOSERVER = 1,
@ -129,13 +135,13 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
#ifdef WITHSPLICE #ifdef WITHSPLICE
|| inserverpipe || inserverpipe
#endif #endif
|| (!SERVERTERMREAD ))) || (!SERVERTERMREAD && !SESSIONEND)))
|| ||
((!SERVERTERMWRITE) && fromclient && (inclientbuf ((!SERVERTERMWRITE) && fromclient && (inclientbuf
#ifdef WITHSPLICE #ifdef WITHSPLICE
|| inclientpipe || inclientpipe
#endif #endif
|| (!CLIENTTERMREAD ))) || (!CLIENTTERMREAD && !SESSIONEND)))
){ ){
@ -354,7 +360,7 @@ log(logbuf);
} }
} }
} }
if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE){ if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE && !SESSIONEND){
int error; int error;
socklen_t len=sizeof(error); socklen_t len=sizeof(error);
#ifdef WITHLOG #ifdef WITHLOG
@ -396,7 +402,7 @@ log("done read from client to pipe");
continue; continue;
} }
} }
if(fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE){ if(fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE && !SESSIONEND){
int error; int error;
socklen_t len=sizeof(error); socklen_t len=sizeof(error);
errno = 0; errno = 0;
@ -449,7 +455,7 @@ log("done read from server to pipe\n");
else else
#endif #endif
{ {
if(fromclient > inclientbuf && FROMCLIENT && TOCLIENTBUF){ if(fromclient > inclientbuf && FROMCLIENT && TOCLIENTBUF && !SESSIONEND){
#ifdef WITHLOG #ifdef WITHLOG
log("read from client to buf"); log("read from client to buf");
#endif #endif
@ -482,7 +488,7 @@ log("done read from client to buf");
} }
} }
if(fromserver > inserverbuf && FROMSERVER && TOSERVERBUF){ if(fromserver > inserverbuf && FROMSERVER && TOSERVERBUF && !SESSIONEND){
#ifdef WITHLOG #ifdef WITHLOG
log("read from server to buf"); log("read from server to buf");
#endif #endif
@ -547,7 +553,7 @@ log("done read from server to buf");
// if(!CLIENTTERMREAD || !CLIENTTERMWRITE){ // if(!CLIENTTERMREAD || !CLIENTTERMWRITE){
if(!after){ if(!after){
fds[fdsc].fd = param->clisock; fds[fdsc].fd = param->clisock;
if(fromclient && !CLIENTTERMREAD && !FROMCLIENT && (( if(fromclient && !CLIENTTERMREAD && !FROMCLIENT && !SESSIONEND && ((
#ifdef WITHSPLICE #ifdef WITHSPLICE
!usesplice && !usesplice &&
#endif #endif
@ -607,7 +613,7 @@ log("ready to write to client");
// if(!SERVERTERMREAD || !SERVERTERMWRITE){ // if(!SERVERTERMREAD || !SERVERTERMWRITE){
if(!after){ if(!after){
fds[fdsc].fd = param->remsock; fds[fdsc].fd = param->remsock;
if(fromserver && !SERVERTERMREAD && !FROMSERVER && (( if(fromserver && !SERVERTERMREAD && !FROMSERVER && !SESSIONEND && ((
#ifdef WITHSPLICE #ifdef WITHSPLICE
!usesplice && !usesplice &&
#endif #endif
@ -780,7 +786,9 @@ log("ready reading from server pipe");
#ifdef WITHLOG #ifdef WITHLOG
log("entering poll"); log("entering poll");
#endif #endif
res = param->srv->so._poll(param->sostate, fds, fdsc, timeo*1000); res = param->srv->so._poll(param->sostate, fds, fdsc,
((CLIENTTERMREAD || SERVERTERMREAD)?
MIN(timeo, conf.timeouts[LINGER_TO]) : timeo) * 1000);
#ifdef WITHLOG #ifdef WITHLOG
log("leaving poll"); log("leaving poll");
#endif #endif
@ -825,3 +833,4 @@ CLEANRET:
return res; return res;
} }
#undef SESSIONEND

View File

@ -551,6 +551,7 @@ struct srvparam {
#ifdef WITHSPLICE #ifdef WITHSPLICE
int usesplice; int usesplice;
#endif #endif
int halfclose;
unsigned bufsize; unsigned bufsize;
unsigned authcachetype, authcachetime; unsigned authcachetype, authcachetime;
unsigned logdumpsrv, logdumpcli; unsigned logdumpsrv, logdumpcli;
@ -832,7 +833,7 @@ struct pluginlink {
int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*ACLMatches)(struct ace* acentry, struct clientparam * param);
int (*alwaysauth)(struct clientparam * param); int (*alwaysauth)(struct clientparam * param);
int (*checkACL)(struct clientparam * param); int (*checkACL)(struct clientparam * param);
unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen); unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen, int outsize);
int (*de64)(const unsigned char *in, unsigned char *out, int maxlen); int (*de64)(const unsigned char *in, unsigned char *out, int maxlen);
void (*tohex)(unsigned char *in, unsigned char *out, int len); void (*tohex)(unsigned char *in, unsigned char *out, int len);
void (*fromhex)(unsigned char *in, unsigned char *out, int len); void (*fromhex)(unsigned char *in, unsigned char *out, int len);
@ -882,7 +883,8 @@ typedef enum {
DNS_TO, DNS_TO,
CHAIN_TO, CHAIN_TO,
CONNECT_TO, CONNECT_TO,
CONNBACK_TO CONNBACK_TO,
LINGER_TO
}TIMEOUT; }TIMEOUT;
typedef enum { typedef enum {