mirror of
https://github.com/3proxy/3proxy.git
synced 2026-07-23 12:10:11 +08:00
Multiple fixes, including security-related ones (in smtpp and LDAP plugin)
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
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
This commit is contained in:
parent
afb2ec0696
commit
d60ac723a5
26
src/auth.c
26
src/auth.c
@ -216,6 +216,24 @@ int dnsauth(struct clientparam * param){
|
||||
return param->username? 0:3;
|
||||
}
|
||||
|
||||
static int ctmemcmp(const void *a, const void *b, size_t len){
|
||||
const unsigned char *pa = (const unsigned char *)a, *pb = (const unsigned char *)b;
|
||||
unsigned char diff = 0;
|
||||
size_t i;
|
||||
for(i = 0; i < len; i++) diff |= (unsigned char)(pa[i] ^ pb[i]);
|
||||
return diff;
|
||||
}
|
||||
|
||||
static int ctstrcmp(const char *a, const char *b, size_t maxlen){
|
||||
unsigned char diff = 0;
|
||||
size_t i;
|
||||
for(i = 0; i < maxlen; i++){
|
||||
diff |= (unsigned char)((unsigned char)a[i] ^ (unsigned char)b[i]);
|
||||
if(!a[i] && !b[i]) break;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
int strongauth(struct clientparam * param){
|
||||
static char dummy;
|
||||
unsigned char buf[256];
|
||||
@ -229,7 +247,7 @@ int strongauth(struct clientparam * param){
|
||||
int pwlen = strlen((char *)param->password);
|
||||
if(pwlen > 255) pwlen = 255;
|
||||
if((unsigned)pwlen < pwl_table.recsize) {
|
||||
if(!strncmp(pass + 1, (char *)param->password, pwl_table.recsize - 1)) return 0;
|
||||
if(strlen(pass + 1) == strlen((char *)param->password) && !ctmemcmp(pass + 1, param->password, pwl_table.recsize - 1)) return 0;
|
||||
} else {
|
||||
mdh_ctx *bctx;
|
||||
unsigned hashsz;
|
||||
@ -242,18 +260,18 @@ int strongauth(struct clientparam * param){
|
||||
blen = hashsz;
|
||||
mdh_final(bctx, buf, &blen);
|
||||
mdh_free(bctx);
|
||||
if(!memcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0;
|
||||
if(!ctmemcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
case CR:
|
||||
if (mycrypt(param->password, (unsigned char *)pass + 1, buf) &&
|
||||
!strcmp(pass + 1, (char *)buf))
|
||||
!ctstrcmp(pass + 1, (char *)buf, sizeof(pass) - 1))
|
||||
return 0;
|
||||
else return 7;
|
||||
#ifdef WITH_SSL
|
||||
case NT:
|
||||
if(ntpwdhash(buf, param->password, 1) && !strcmp(pass + 1, (char *)buf)) return 0;
|
||||
if(ntpwdhash(buf, param->password, 1) && !ctstrcmp(pass + 1, (char *)buf, sizeof(pass) - 1)) return 0;
|
||||
else return 8;
|
||||
#endif
|
||||
default:
|
||||
|
||||
32
src/pcre.c
32
src/pcre.c
@ -214,6 +214,7 @@ struct pcre_filter_data {
|
||||
int users;
|
||||
pcre2_code * re;
|
||||
pcre2_match_data * match_data;
|
||||
pcre2_match_context * match_context;
|
||||
int action;
|
||||
char * replace;
|
||||
struct ace *acl;
|
||||
@ -223,6 +224,7 @@ static void pcre_data_free(struct pcre_filter_data *pcrefd){
|
||||
_3proxy_mutex_lock(&pcre_mutex);
|
||||
pcrefd->users--;
|
||||
if(!pcrefd->users){
|
||||
if(pcrefd->match_context) pcre2_match_context_free(pcrefd->match_context);
|
||||
if(pcrefd->match_data) pcre2_match_data_free(pcrefd->match_data);
|
||||
if(pcrefd->re) pcre2_code_free(pcrefd->re);
|
||||
if(pcrefd->acl) pl->freeacl(pcrefd->acl);
|
||||
@ -283,10 +285,12 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
if(!match) return CONTINUE;
|
||||
if(!pcrefd->re) return pcrefd->action;
|
||||
for(; offset < *length_p; nreplaces++){
|
||||
int repsz;
|
||||
|
||||
count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcrefd->match_data, NULL);
|
||||
count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcrefd->match_data, pcrefd->match_context);
|
||||
if(count <= 0) break;
|
||||
ovector = pcre2_get_ovector_pointer(pcrefd->match_data);
|
||||
if(ovector[0] > (PCRE2_SIZE)*length_p || ovector[1] > (PCRE2_SIZE)*length_p || ovector[1] < ovector[0]) break;
|
||||
if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action;
|
||||
|
||||
replen = *length_p - ovector[1];
|
||||
@ -300,6 +304,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
num = atoi(replace);
|
||||
while(isnumber(*replace)) replace++;
|
||||
if(num > (count - 1)) continue;
|
||||
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
|
||||
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
|
||||
replen += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
||||
}
|
||||
else {
|
||||
@ -319,6 +325,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
replace ++;
|
||||
num = atoi(replace);
|
||||
if(num > (count - 1)) continue;
|
||||
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
|
||||
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
|
||||
memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
||||
target += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
||||
while(isnumber(*replace)) replace++;
|
||||
@ -327,6 +335,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
*target++ = *replace++;
|
||||
}
|
||||
}
|
||||
repsz = (int)(target - tmpbuf);
|
||||
memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]);
|
||||
if((ovector[0] + replen + 1) > *bufsize_p){
|
||||
newbuf = pl->mallocfunc(ovector[0] + replen + 1);
|
||||
@ -343,10 +352,11 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
pl->freefunc(tmpbuf);
|
||||
(*buf_p)[ovector[0] + replen] = 0;
|
||||
*length_p = ovector[0] + replen;
|
||||
if(ovector[0] + replen <= offset){
|
||||
break;
|
||||
offset = ovector[0] + repsz;
|
||||
if(ovector[1] == ovector[0] && offset <= (int)ovector[0]){
|
||||
/* zero-width match with empty replacement: force progress */
|
||||
offset = ovector[1] + 1;
|
||||
}
|
||||
offset = ovector[0] + (int)strlen(pcrefd->replace);
|
||||
}
|
||||
return nreplaces? pcrefd->action : CONTINUE;
|
||||
#undef pcrefd
|
||||
@ -442,6 +452,13 @@ static int h_pcre(int argc, unsigned char **argv){
|
||||
flt->acl = acl;
|
||||
flt->replace = replace;
|
||||
flt->users = 1;
|
||||
if(re){
|
||||
flt->match_context = pcre2_match_context_create(NULL);
|
||||
if(flt->match_context){
|
||||
pcre2_set_match_limit(flt->match_context, 1000000);
|
||||
pcre2_set_depth_limit(flt->match_context, 10000);
|
||||
}
|
||||
}
|
||||
newf->instance = "pcre";
|
||||
newf->data = flt;
|
||||
newf->filter_open = pcre_filter_open;
|
||||
@ -549,6 +566,13 @@ static int h_pcre_rewrite(int argc, unsigned char **argv){
|
||||
flt->acl = acl;
|
||||
flt->replace = replace;
|
||||
flt->users = 1;
|
||||
if(re){
|
||||
flt->match_context = pcre2_match_context_create(NULL);
|
||||
if(flt->match_context){
|
||||
pcre2_set_match_limit(flt->match_context, 1000000);
|
||||
pcre2_set_depth_limit(flt->match_context, 10000);
|
||||
}
|
||||
}
|
||||
newf->instance = "pcre";
|
||||
newf->data = flt;
|
||||
newf->filter_open = pcre_filter_open;
|
||||
|
||||
@ -51,8 +51,56 @@ void lower (char *string)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RFC 4514 escaping for DN attribute values. Returns dst, NULL on overflow. */
|
||||
static char * ldap_escape_dn(const char *src, char *dst, int dstlen)
|
||||
{
|
||||
int j = 0;
|
||||
unsigned char c;
|
||||
for (; *src; src++){
|
||||
c = (unsigned char)*src;
|
||||
if(c == ',' || c == '+' || c == '"' || c == '\\' || c == '<' || c == '>' || c == ';' || c == '=' || c < 0x20 || c == 0x7f){
|
||||
if(j + 3 >= dstlen) return NULL;
|
||||
sprintf(dst + j, "\\%02X", c);
|
||||
j += 3;
|
||||
}
|
||||
else {
|
||||
if(j + 1 >= dstlen) return NULL;
|
||||
dst[j++] = (char)c;
|
||||
}
|
||||
}
|
||||
dst[j] = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* RFC 4515 escaping for search filter values. Returns dst, NULL on overflow. */
|
||||
static char * ldap_escape_filter(const char *src, char *dst, int dstlen)
|
||||
{
|
||||
int j = 0;
|
||||
unsigned char c;
|
||||
for (; *src; src++){
|
||||
c = (unsigned char)*src;
|
||||
if(c == '*' || c == '(' || c == ')' || c == '\\' || c == 0 || c < 0x20 || c >= 0x7f){
|
||||
if(j + 3 >= dstlen) return NULL;
|
||||
sprintf(dst + j, "\\%02X", c);
|
||||
j += 3;
|
||||
}
|
||||
else {
|
||||
if(j + 1 >= dstlen) return NULL;
|
||||
dst[j++] = (char)c;
|
||||
}
|
||||
}
|
||||
dst[j] = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* reject names unsafe for use in filesystem paths */
|
||||
static int unsafe_filename(const char *name)
|
||||
{
|
||||
return (strchr(name, '/') || strchr(name, '\\') || strstr(name, "..") || !*name);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
int savecounters(void)
|
||||
int savecounters(void *v)
|
||||
{
|
||||
struct trafcount *tc=mypluginlink->conf->trafcounter;
|
||||
struct trafcount *tcd;
|
||||
@ -67,8 +115,8 @@ int savecounters(void)
|
||||
tcd = tc;
|
||||
tc = tc->next;
|
||||
f=NULL;
|
||||
if(strcmp(tcd->comment,"ldapcounters")==0) {
|
||||
tmpbuf=malloc(strlen(pat_file)+strlen(ldap_dircount)+strlen(tcd->ace->users->user));
|
||||
if(strcmp(tcd->comment,"ldapcounters")==0 && !unsafe_filename(tcd->ace->users->user)) {
|
||||
tmpbuf=malloc(strlen(ldap_dircount)+strlen(tcd->ace->users->user)+sizeof(".lc"));
|
||||
sprintf(tmpbuf,pat_file,ldap_dircount,tcd->ace->users->user);
|
||||
f=fopen(tmpbuf,"w+b");
|
||||
fseek(f,0,SEEK_SET);
|
||||
@ -100,6 +148,7 @@ static int ldapfunc(struct clientparam *param)
|
||||
LDAPMessage *res = NULL;
|
||||
int rc = -1;
|
||||
char tmpbuf[1024];
|
||||
char escuser[512];
|
||||
|
||||
/* test proxy user auth ------------------------*/
|
||||
if(!param->username || !param->password) return 4;
|
||||
@ -126,7 +175,12 @@ static int ldapfunc(struct clientparam *param)
|
||||
|
||||
|
||||
/* create user for test auth */
|
||||
sprintf(tmpbuf,"%.200s=%.200s,%.200s",attrs[0],param->username,ldap_userenv);
|
||||
if(!ldap_escape_dn(param->username, escuser, sizeof(escuser)))
|
||||
{
|
||||
ldap_unbind_s(ld);
|
||||
return 5;
|
||||
}
|
||||
snprintf(tmpbuf, sizeof(tmpbuf), "%.200s=%.510s,%.200s",attrs[0],escuser,ldap_userenv);
|
||||
|
||||
rc = ldap_bind_s( ld, tmpbuf, param->password, LDAP_AUTH_SIMPLE );
|
||||
|
||||
@ -162,7 +216,12 @@ static int ldapfunc(struct clientparam *param)
|
||||
/* test enter user in filter ------------------------------
|
||||
create filter for search*/
|
||||
|
||||
sprintf(tmpbuf,"(&(%.200s=%.200s)(%.200s=%.200s))",attrs[0],param->username,
|
||||
if(!ldap_escape_filter(param->username, escuser, sizeof(escuser)))
|
||||
{
|
||||
ldap_unbind_s(ld);
|
||||
return 5;
|
||||
}
|
||||
snprintf(tmpbuf, sizeof(tmpbuf), "(&(%.200s=%.510s)(%.200s=%.200s))",attrs[0],escuser,
|
||||
ldap_group_attr,ldap_access);
|
||||
|
||||
|
||||
@ -326,7 +385,7 @@ int h_trafgroup(int argc, unsigned char ** argv)
|
||||
while (rc > 0)
|
||||
{
|
||||
vals=ldap_get_values(ld, msg, getattr);
|
||||
if (vals != NULL && vals[0] != NULL )
|
||||
if (vals != NULL && vals[0] != NULL && !unsafe_filename(vals[0]) )
|
||||
{
|
||||
|
||||
/* -------------bandlim----------
|
||||
@ -378,7 +437,7 @@ int h_trafgroup(int argc, unsigned char ** argv)
|
||||
newtrafcount->traflim64 = traflimit;
|
||||
newtrafcount->comment=(*mypluginlink->strdupfunc)("ldapcounters");
|
||||
newtrafcount->number=0;
|
||||
tmpbuf=malloc(strlen(pat_file)+strlen(ldap_dircount)+strlen(vals[0]));
|
||||
tmpbuf=malloc(strlen(ldap_dircount)+strlen(vals[0])+sizeof(".lc"));
|
||||
sprintf(tmpbuf,pat_file,ldap_dircount,vals[0]);
|
||||
f=NULL;
|
||||
f=fopen(tmpbuf,"rb");
|
||||
|
||||
@ -49,9 +49,13 @@ char **load_string(FILE *f,int max_count_str, int *countloadstr,
|
||||
|
||||
/*load from file new strings */
|
||||
i=0;
|
||||
while ( !feof(f) || i< max_count_str)
|
||||
while ( !feof(f) && i < max_count_str)
|
||||
{
|
||||
if(!fgets(tmpbuf1, 1023,f)) return NULL;
|
||||
if(!fgets(tmpbuf1, 1023,f)){
|
||||
if(pt) free(pt);
|
||||
free(old_table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((strstr(tmpbuf1,stop))!=NULL) { break; }
|
||||
|
||||
|
||||
25
src/proxy.c
25
src/proxy.c
@ -240,6 +240,7 @@ void * proxychild(struct clientparam* param) {
|
||||
int keepalive = 0;
|
||||
uint64_t contentlength64 = 0;
|
||||
int hascontent =0;
|
||||
int clhdrofs = -1;
|
||||
int isconnect = 0;
|
||||
int redirect = 0;
|
||||
int prefix = 0, ckeepalive=0;
|
||||
@ -413,6 +414,10 @@ for(;;){
|
||||
param->password = (unsigned char *)strdup((char *)sb+1);
|
||||
param->pwtype = 0;
|
||||
}
|
||||
else if(param->password){
|
||||
free(param->password);
|
||||
param->password = NULL;
|
||||
}
|
||||
if(param->username)free(param->username);
|
||||
param->username = (unsigned char *)strdup((char *)username);
|
||||
continue;
|
||||
@ -458,13 +463,14 @@ for(;;){
|
||||
if(parsehostname((char *)sb, param, 80)) RETURN(100);
|
||||
}
|
||||
newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
|
||||
if(newbuf){
|
||||
sp = (unsigned char *)strchr((char *)req+1, '/');
|
||||
if(newbuf && sp){
|
||||
memcpy(newbuf, req, (sp - req));
|
||||
sprintf((char*)newbuf + (sp - req), "http://%s%s",sb,sp);
|
||||
free(req);
|
||||
req = newbuf;
|
||||
}
|
||||
else if(newbuf) free(newbuf);
|
||||
if(se)*se = c;
|
||||
}
|
||||
if(ftp && i > 13 && (!strncasecmp((char *)(buf+inbuf), "authorization", 13))){
|
||||
@ -485,6 +491,10 @@ for(;;){
|
||||
if(param->extpassword)free(param->extpassword);
|
||||
param->extpassword = (unsigned char *)strdup((char *)sb+1);
|
||||
}
|
||||
else if(param->extpassword){
|
||||
free(param->extpassword);
|
||||
param->extpassword = NULL;
|
||||
}
|
||||
if(param->extusername)free(param->extusername);
|
||||
param->extusername = (unsigned char *)strdup((char *)username);
|
||||
continue;
|
||||
@ -565,7 +575,7 @@ for(;;){
|
||||
if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) {
|
||||
param->nolongdatfilter = 1;
|
||||
}
|
||||
else if(param->ndatfilterscli > 0 && contentlength64 > 0){
|
||||
else if(param->ndatfilterscli > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64){
|
||||
uint64_t newlen64;
|
||||
newlen64 = (uint64_t) sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S);
|
||||
if(newlen64 == contentlength64) {
|
||||
@ -921,6 +931,7 @@ for(;;){
|
||||
authenticate = 0;
|
||||
param->chunked = 0;
|
||||
hascontent = 0;
|
||||
clhdrofs = -1;
|
||||
|
||||
while( (i = sockgetlinebuf(param, SERVER, buf + inbuf, LINESIZE - 1, '\n', conf.timeouts[(res)?STRING_S:STRING_L])) > 2) {
|
||||
if(!res && i>9)param->status = res = atoi((char *)buf + inbuf + 9);
|
||||
@ -942,6 +953,7 @@ for(;;){
|
||||
authenticate = 1;
|
||||
}
|
||||
else if(i > 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){
|
||||
if(param->chunked) continue;
|
||||
buf[inbuf+i]=0;
|
||||
sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
|
||||
if(!sb)continue;
|
||||
@ -949,6 +961,7 @@ for(;;){
|
||||
while(isspace(*sb))sb++;
|
||||
sscanf((char *)sb, "%"SCNu64"", &contentlength64);
|
||||
hascontent = 1;
|
||||
clhdrofs = inbuf;
|
||||
if(param->unsafefilter && param->ndatfilterssrv > 0) {
|
||||
hascontent = 2;
|
||||
continue;
|
||||
@ -965,6 +978,12 @@ for(;;){
|
||||
while(isspace(*sb))sb++;
|
||||
if(!strncasecmp((char *)sb, "chunked", 7)){
|
||||
param->chunked = 1;
|
||||
if(clhdrofs >= 0){
|
||||
buf[clhdrofs] = 'X';
|
||||
clhdrofs = -1;
|
||||
contentlength64 = 0;
|
||||
hascontent = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inbuf += i;
|
||||
@ -1009,7 +1028,7 @@ for(;;){
|
||||
if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) {
|
||||
param->nolongdatfilter = 1;
|
||||
}
|
||||
else if(param->ndatfilterssrv > 0 && contentlength64 > 0 && param->operation != HTTP_HEAD && res != 204 && res != 304){
|
||||
else if(param->ndatfilterssrv > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64 && param->operation != HTTP_HEAD && res != 204 && res != 304){
|
||||
uint64_t newlen;
|
||||
newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S);
|
||||
if(newlen == contentlength64) {
|
||||
|
||||
@ -233,9 +233,10 @@ void * smtppchild(struct clientparam* param) {
|
||||
if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(682);}
|
||||
*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);}
|
||||
memcpy(username+1, param->extusername, i);
|
||||
i++;
|
||||
res = (int)strlen((char *)param->extpassword);
|
||||
memcpy(username + i, param->extpassword, res);
|
||||
i+=res;
|
||||
en64(username, buf, i);
|
||||
|
||||
@ -69,7 +69,7 @@ int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * sn
|
||||
elen = size16(hello+offset);
|
||||
offset += 2;
|
||||
if(elen+offset != len) return -9;
|
||||
while(elen > 1){
|
||||
while(elen > 3){
|
||||
unsigned xlen;
|
||||
xlen = size16(hello+offset+2);
|
||||
if(xlen+4 > elen) return -10;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user