mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 10:35:40 +08:00
Communicate SOCKS error states properly
This used to look pretty random :( Try to keep the last decimal digits of internal errors sensible for v5 error codes. For most cases we can't really do much better than using the value of one. One specific code paths where we can return something more useful is the authentication, where we not communicate the underlying error code or signal an ACL denial. As for v4, there's not really much space to be too smart as only the code of 91 is meaningful. Therefore we limit the last digit to zero and one now.
This commit is contained in:
parent
8a57314bc6
commit
9bdb4d56f8
66
src/socks.c
66
src/socks.c
@ -48,29 +48,29 @@ void * sockschild(struct clientparam* param) {
|
||||
if(ver == 5){
|
||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
|
||||
for (; i; i--) {
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
if (res == 2 && !param->srv->nouser) {
|
||||
havepass = res;
|
||||
}
|
||||
}
|
||||
buf[0] = 5;
|
||||
buf[1] = havepass;
|
||||
if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
|
||||
if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);}
|
||||
if (havepass) {
|
||||
if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
|
||||
RETURN(412);
|
||||
}
|
||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);}
|
||||
if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);};
|
||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
|
||||
if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
|
||||
buf[i] = 0;
|
||||
if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
|
||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
|
||||
if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);};
|
||||
if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
|
||||
buf[i] = 0;
|
||||
if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
|
||||
buf[0] = 1;
|
||||
buf[1] = 0;
|
||||
if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
|
||||
if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);}
|
||||
}
|
||||
if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
|
||||
RETURN(421);
|
||||
@ -82,9 +82,9 @@ void * sockschild(struct clientparam* param) {
|
||||
c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
|
||||
}
|
||||
else {
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[0] = (unsigned char) res;
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[1] = (unsigned char) res;
|
||||
param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
|
||||
c = 1;
|
||||
@ -93,19 +93,19 @@ void * sockschild(struct clientparam* param) {
|
||||
switch(c) {
|
||||
case 1:
|
||||
for (i = 0; i<4; i++){
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[i] = (unsigned char)res;
|
||||
}
|
||||
param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf;
|
||||
if(command==1 && !param->req.sin_addr.s_addr) {
|
||||
RETURN(422);
|
||||
RETURN(421);
|
||||
}
|
||||
myinet_ntop(*SAFAMILY(¶m->sins), SAADDR(¶m->sins), (char *)buf, 64);
|
||||
break;
|
||||
case 3:
|
||||
if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
|
||||
for (i=0; i<size; i++){ /* size < 256 */
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
|
||||
buf[i] = (unsigned char)res;
|
||||
}
|
||||
buf[i] = 0;
|
||||
@ -115,14 +115,14 @@ void * sockschild(struct clientparam* param) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
RETURN(998);
|
||||
RETURN(997);
|
||||
}
|
||||
if(param->hostname)myfree(param->hostname);
|
||||
param->hostname = (unsigned char *)mystrdup((char *)buf);
|
||||
if (ver == 5) {
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[0] = (unsigned char) res;
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);}
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[1] = (unsigned char) res;
|
||||
param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
|
||||
}
|
||||
@ -139,7 +139,7 @@ void * sockschild(struct clientparam* param) {
|
||||
param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
|
||||
}
|
||||
}
|
||||
if(command == 1 && !param->req.sin_port) {RETURN(424);}
|
||||
if(command == 1 && !param->req.sin_port) {RETURN(421);}
|
||||
param->sins.sin_family = AF_INET;
|
||||
switch(command) {
|
||||
case 1:
|
||||
@ -161,12 +161,38 @@ void * sockschild(struct clientparam* param) {
|
||||
RETURN(997);
|
||||
}
|
||||
|
||||
if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
|
||||
errno = 0;
|
||||
if((res = (*param->srv->authfunc)(param))) {
|
||||
res *= 10;
|
||||
switch (errno) {
|
||||
/* If authfunc failed but errno stays intacts we assume ACL denied the access,
|
||||
* otherwise we do our best to pick a good error code for SOCKSv5. */
|
||||
case 0:
|
||||
res += 2; /* connection not allowed by ruleset */
|
||||
break;
|
||||
case ENETUNREACH:
|
||||
res += 3; /* Network unreachable */
|
||||
break;
|
||||
case EHOSTUNREACH:
|
||||
res += 4; /* Host unreachable */
|
||||
break;
|
||||
case ECONNREFUSED:
|
||||
res += 5; /* Connection refused */
|
||||
break;
|
||||
case EPFNOSUPPORT:
|
||||
case EAFNOSUPPORT:
|
||||
res += 8; /* Address type not supported */
|
||||
break;
|
||||
default:
|
||||
res += 1;
|
||||
}
|
||||
RETURN(res);
|
||||
}
|
||||
|
||||
if(command > 1) {
|
||||
if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) {
|
||||
param->sins.sin_port = 0;
|
||||
if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (12);
|
||||
if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (11);
|
||||
#if SOCKSTRACE > 0
|
||||
fprintf(stderr, "%s:%hu binded to communicate with server\n",
|
||||
inet_ntoa(param->sins.sin_addr),
|
||||
@ -183,7 +209,7 @@ fflush(stderr);
|
||||
if(param->clisock == INVALID_SOCKET) {RETURN(11);}
|
||||
memcpy(&sin, ¶m->sincl, sizeof(&sin));
|
||||
*SAPORT(&sin) = htons(0);
|
||||
if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(sin))) {RETURN (12);}
|
||||
if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(sin))) {RETURN (11);}
|
||||
#if SOCKSTRACE > 0
|
||||
fprintf(stderr, "%hu binded to communicate with client\n",
|
||||
ntohs(*SAPORT(&sin))
|
||||
@ -220,7 +246,7 @@ fflush(stderr);
|
||||
}
|
||||
else{
|
||||
buf[0] = 0;
|
||||
buf[1] = 90 + (param->res%10);
|
||||
buf[1] = 90 + !!(param->res%10);
|
||||
memcpy(buf+2, SAPORT(&sin), 2);
|
||||
memcpy(buf+4, SAADDR(&sin), 4);
|
||||
socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
|
||||
@ -329,7 +355,7 @@ fflush(stderr);
|
||||
param->sins.sin_addr.s_addr = getip(buf+4);
|
||||
break;
|
||||
default:
|
||||
RETURN(996);
|
||||
RETURN(997);
|
||||
}
|
||||
|
||||
memcpy(¶m->sins.sin_port, buf+i, 2);
|
||||
|
Loading…
Reference in New Issue
Block a user