From eceb5a22df1e10dcad94ea743b9f7cb1ec80aaad Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Sat, 8 Aug 2026 17:58:49 +0300 Subject: [PATCH] Add outsize parameter to en64 --- src/base64.c | 13 ++++++++++--- src/imapp.c | 10 ++++------ src/proxy.c | 3 ++- src/proxy.h | 2 +- src/redirect.c | 2 +- src/smtpp.c | 8 ++++---- src/structures.h | 2 +- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/base64.c b/src/base64.c index e1cfd4f..eee6b50 100644 --- a/src/base64.c +++ b/src/base64.c @@ -6,6 +6,7 @@ */ #include +#include static const unsigned char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -23,8 +24,10 @@ static const unsigned char base64val[] = { }; #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) { @@ -42,6 +45,7 @@ int de64 (const char *in, char *out, int maxlen) int len = 0; register unsigned char digit1, digit2, digit3, digit4; + if (maxlen < 0) return(-1); if (in[0] == '+' && in[1] == ' ') in += 2; if (*in == '\r') @@ -61,20 +65,23 @@ int de64 (const char *in, char *out, int maxlen) if (digit4 != '=' && DECODE64(digit4) == BAD) return(-1); in += 4; + if (len >= maxlen) return (len); *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); ++len; if (digit3 != '=') { + if (len >= maxlen) return (len); *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); ++len; if (digit4 != '=') { + if (len >= maxlen) return (len); *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); ++len; } } - } while - (*in && *in != '\r' && digit4 != '=' && (maxlen-=4) >= 4); + } while + (*in && *in != '\r' && digit4 != '='); return (len); } diff --git a/src/imapp.c b/src/imapp.c index f589251..2d1e0db 100644 --- a/src/imapp.c +++ b/src/imapp.c @@ -182,12 +182,12 @@ void * imappchild(struct clientparam* param) { if(method == CL_PLAIN){ i = (int)strlen((char *)param->extusername); 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; memcpy(ibuf + 1, param->extusername, i); ibuf[i + 1] = 0; 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 || 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 || @@ -200,15 +200,13 @@ void * imappchild(struct clientparam* param) { {RETURN(699);} i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]); if(i < 1 || *srvbuf != '+') {RETURN(699);} - if(((int)strlen((char *)param->extusername) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);} - en64(param->extusername, ibuf, (int)strlen((char *)param->extusername)); + if(!en64(param->extusername, ibuf, (int)strlen((char *)param->extusername), (int)sizeof(ibuf))) {RETURN(693);} 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) {RETURN(699);} i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]); if(i < 1 || *srvbuf != '+') {RETURN(699);} - if(((int)strlen((char *)pb) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);} - en64(pb, ibuf, (int)strlen((char *)pb)); + if(!en64(pb, ibuf, (int)strlen((char *)pb), (int)sizeof(ibuf))) {RETURN(693);} 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) {RETURN(699);} diff --git a/src/proxy.c b/src/proxy.c index 2412486..922b362 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -929,7 +929,8 @@ for(;;){ if(param->extusername){ hlen += sprintf((char*)buf + hlen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization"); 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"); diff --git a/src/proxy.h b/src/proxy.h index 878c6d6..d5b1ec9 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -271,7 +271,7 @@ extern int demon; 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); 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 fromhex(unsigned char *in, unsigned char *out, int len); diff --git a/src/redirect.c b/src/redirect.c index a796bae..9654492 100644 --- a/src/redirect.c +++ b/src/redirect.c @@ -70,7 +70,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc if(user){ len += sprintf((char *)buf + len, "Proxy-Authorization: Basic "); 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 += sprintf((char *)buf + len, "\r\n"); } diff --git a/src/smtpp.c b/src/smtpp.c index a2f449d..e82200e 100644 --- a/src/smtpp.c +++ b/src/smtpp.c @@ -237,14 +237,14 @@ void * smtppchild(struct clientparam* param) { param->nwrites++; i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); 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, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); param->statscli64+=(i+2); param->nwrites+=2; i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); 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, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); param->statscli64+=(i+2); @@ -259,12 +259,12 @@ void * smtppchild(struct clientparam* param) { *username = 0; i = (int)strlen((char *)param->extusername) + 1; 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); i++; memcpy(username + i, param->extpassword, res); i+=res; - en64(username, buf, i); + if(!en64(username, buf, i, (int)sizeof(buf))) {RETURN(683);} i = (int)strlen((char *)buf); socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]); socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S]); diff --git a/src/structures.h b/src/structures.h index 3ebbabe..69e9740 100644 --- a/src/structures.h +++ b/src/structures.h @@ -832,7 +832,7 @@ struct pluginlink { int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*alwaysauth)(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); void (*tohex)(unsigned char *in, unsigned char *out, int len); void (*fromhex)(unsigned char *in, unsigned char *out, int len);