Add outsize parameter to en64

This commit is contained in:
Vladimir Dubrovin 2026-08-08 17:58:49 +03:00
parent 7eba73fc8f
commit eceb5a22df
7 changed files with 23 additions and 17 deletions

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

@ -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

@ -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");
} }

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

@ -832,7 +832,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);