mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-15 16:15:49 +08:00
Pre-allocate client/server/tmp/etc buffers with client structure
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
b9297dc4cf
commit
a20f646169
@ -233,7 +233,7 @@ struct filter {
|
|||||||
<p><code>filter_open</code> must always be defined, if you want filter to be ever used. It's called then new service is created and is given "data" from struct filter and struct srvparam (parsed service configuration). If filter_open for some filter returns NULL, filter will not be used for this service. Non-NULL return value will be used as "fo" parameter for every call to filter_client.</p>
|
<p><code>filter_open</code> must always be defined, if you want filter to be ever used. It's called then new service is created and is given "data" from struct filter and struct srvparam (parsed service configuration). If filter_open for some filter returns NULL, filter will not be used for this service. Non-NULL return value will be used as "fo" parameter for every call to filter_client.</p>
|
||||||
<p><code>filter_client</code> is called upon client connect (before any data is sent/received). It's good place to filter client by IP (and is not good place to filter it by hostname, because this operation takes a long time, 3proxy will not be able to accept new connection). fo is a data pointer received from filter_open, param – newly created clientparam structure, fc is return parameter filter_open must initialize, it will be used as an argument to FILTER_BUFFER functions. PASS return value means this filter will be used for this client request. CONTINUE says to install filters. On different values client connection is closed and no client thread is created.</p>
|
<p><code>filter_client</code> is called upon client connect (before any data is sent/received). It's good place to filter client by IP (and is not good place to filter it by hostname, because this operation takes a long time, 3proxy will not be able to accept new connection). fo is a data pointer received from filter_open, param – newly created clientparam structure, fc is return parameter filter_open must initialize, it will be used as an argument to FILTER_BUFFER functions. PASS return value means this filter will be used for this client request. CONTINUE says to install filters. On different values client connection is closed and no client thread is created.</p>
|
||||||
<p><code>filter_request, filter_header_cli, filter_header_srv, filter_data_cli, filter_data_srv</code> are used to process request and data received from client and server.</p>
|
<p><code>filter_request, filter_header_cli, filter_header_srv, filter_data_cli, filter_data_srv</code> are used to process request and data received from client and server.</p>
|
||||||
<p><code>char ** buf_p</code> is a pointer to current buffer, <code>int * bufsize_p</code> is a pointer to it's size. In case you change some data and it doesn't fit to current buffer, you may allocate new buffer (with <code>pluginlink->myalloc</code>), copy data from old buffer, free old buffer (with <code>pluginlink->myfree</code>) and set new values for <code>*buf_p</code> and <code>*bufsize_p</code>.</p>
|
<p><code>char ** buf_p</code> is a pointer to current buffer, <code>int * bufsize_p</code> is a pointer to it's size. In case you change some data and it doesn't fit to current buffer, you may allocate new buffer (with <code>pluginlink->mallocfunc</code>), copy data from old buffer and set new values for <code>*buf_p</code> and <code>*bufsize_p</code>. Do not free the buffer you were given: it may not be heap memory, and 3proxy frees it itself when it was. A buffer you allocated and then replaced again within the same call is yours to free (with <code>pluginlink->freefunc</code>).</p>
|
||||||
<p><code>int offset</code> offset of the new data in the buffer, <code>int * length_p</code> length of all data in the buffer. You should filter only <code>(*length_p - *offset_p)</code> characters starting from <code>(*buf_p + *offset_p)</code>.</p>
|
<p><code>int offset</code> offset of the new data in the buffer, <code>int * length_p</code> length of all data in the buffer. You should filter only <code>(*length_p - *offset_p)</code> characters starting from <code>(*buf_p + *offset_p)</code>.</p>
|
||||||
<p><code>filter_clear</code> is called for each successfule filter_client and should be used to free allocated resources</p>
|
<p><code>filter_clear</code> is called for each successfule filter_client and should be used to free allocated resources</p>
|
||||||
<p><code>filter_close</code> is called for each successful filter_open for the same reason</p>
|
<p><code>filter_close</code> is called for each successful filter_open for the same reason</p>
|
||||||
|
|||||||
@ -1436,7 +1436,10 @@ as
|
|||||||
.br
|
.br
|
||||||
If Content-length (or another data length) is greater than the given value, no
|
If Content-length (or another data length) is greater than the given value, no
|
||||||
data filtering will be performed through filtering plugins to avoid data
|
data filtering will be performed through filtering plugins to avoid data
|
||||||
corruption and/or Content-Length changing. Default is 1MB (1048576).
|
corruption and/or Content-Length changing. A body up to this size is read
|
||||||
|
whole into memory and filtered at once. 0 removes the limit, but then a body
|
||||||
|
is only filtered whole if it fits in the connection's 16K buffer.
|
||||||
|
Default is 1MB (1048576).
|
||||||
|
|
||||||
.SH SSL/TLS SUPPORT
|
.SH SSL/TLS SUPPORT
|
||||||
SSL/TLS support is built into 3proxy (since 0.9.7) when compiled with OpenSSL
|
SSL/TLS support is built into 3proxy (since 0.9.7) when compiled with OpenSSL
|
||||||
|
|||||||
@ -280,7 +280,7 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
|
|||||||
int dstdep = 0;
|
int dstdep = 0;
|
||||||
int preauth = (param->preauth == 1 && acentry->action <= REDIRECT);
|
int preauth = (param->preauth == 1 && acentry->action <= REDIRECT);
|
||||||
|
|
||||||
username = param->username?param->username:(unsigned char *)"-";
|
username = *param->username?param->username:(unsigned char *)"-";
|
||||||
if(acentry->src) {
|
if(acentry->src) {
|
||||||
for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
|
for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
|
||||||
if(IPInentry((struct sockaddr *)¶m->sincr, ipentry)) {
|
if(IPInentry((struct sockaddr *)¶m->sincr, ipentry)) {
|
||||||
@ -291,13 +291,13 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
|
|||||||
if(preauth && (acentry->dst || acentry->dstnames)) {
|
if(preauth && (acentry->dst || acentry->dstnames)) {
|
||||||
dstdep = 1;
|
dstdep = 1;
|
||||||
}
|
}
|
||||||
else if((acentry->dst && (!SAISNULL(¶m->req) || param->operation==BIND)) || (acentry->dstnames && param->hostname)) {
|
else if((acentry->dst && (!SAISNULL(¶m->req) || param->operation==BIND)) || (acentry->dstnames && *param->hostname)) {
|
||||||
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
|
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
|
||||||
if(IPInentry((struct sockaddr *)¶m->req, ipentry)) {
|
if(IPInentry((struct sockaddr *)¶m->req, ipentry)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!ipentry) {
|
if(!ipentry) {
|
||||||
if(acentry->dstnames && param->hostname){
|
if(acentry->dstnames && *param->hostname){
|
||||||
for(i=0; param->hostname[i]; i++){
|
for(i=0; param->hostname[i]; i++){
|
||||||
param->hostname[i] = tolower(param->hostname[i]);
|
param->hostname[i] = tolower(param->hostname[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
37
src/auth.c
37
src/auth.c
@ -83,8 +83,8 @@ int cacheauth(struct clientparam * param){
|
|||||||
|
|
||||||
|
|
||||||
if(
|
if(
|
||||||
((type & 2) && !param->username) ||
|
((type & 2) && !*param->username) ||
|
||||||
((type & 4) && !param->password) ||
|
((type & 4) && !*param->password) ||
|
||||||
(
|
(
|
||||||
(type & 1) && *SAFAMILY(¶m->sincr) != AF_INET
|
(type & 1) && *SAFAMILY(¶m->sincr) != AF_INET
|
||||||
#ifndef NOIPV6
|
#ifndef NOIPV6
|
||||||
@ -100,10 +100,7 @@ int cacheauth(struct clientparam * param){
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(type&2) && *ac.username){
|
if(!(type&2) && *ac.username && PARAMSTR(param, username, ac.username)) return 4;
|
||||||
if(param->username) free(param->username);
|
|
||||||
param->username = (unsigned char *)strdup((char *)ac.username);
|
|
||||||
}
|
|
||||||
if((type & 32)){
|
if((type & 32)){
|
||||||
memset(¶m->sinsl, 0, sizeof(param->sinsl));
|
memset(¶m->sinsl, 0, sizeof(param->sinsl));
|
||||||
*(SAFAMILY(¶m->sinsl)) = ac.sinsl_family;
|
*(SAFAMILY(¶m->sinsl)) = ac.sinsl_family;
|
||||||
@ -125,13 +122,11 @@ int doauth(struct clientparam * param){
|
|||||||
if(authfuncs->authorize &&
|
if(authfuncs->authorize &&
|
||||||
(res = (*authfuncs->authorize)(param)))
|
(res = (*authfuncs->authorize)(param)))
|
||||||
return res;
|
return res;
|
||||||
if(param->srv->authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(param->srv->authcachetype&4) || (!param->pwtype && param->password))){
|
if(param->srv->authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && *param->username && (!(param->srv->authcachetype&4) || (!param->pwtype && *param->password))){
|
||||||
struct authcache ac={.username=""};
|
struct authcache ac={.username=""};
|
||||||
|
|
||||||
if(param->username) {
|
strncpy((char *)ac.username, (char *)param->username, 64);
|
||||||
strncpy((char *)ac.username, (char *)param->username, 64);
|
ac.username[63] = 0;
|
||||||
ac.username[63] = 0;
|
|
||||||
}
|
|
||||||
if(*SAFAMILY(¶m->sincr) == AF_INET
|
if(*SAFAMILY(¶m->sincr) == AF_INET
|
||||||
#ifndef NOIPV6
|
#ifndef NOIPV6
|
||||||
|| *SAFAMILY(¶m->sincr) == AF_INET6
|
|| *SAFAMILY(¶m->sincr) == AF_INET6
|
||||||
@ -158,7 +153,7 @@ int doauth(struct clientparam * param){
|
|||||||
}
|
}
|
||||||
if(!res){
|
if(!res){
|
||||||
ret = (param->preauth == 2)? 0 : alwaysauth(param);
|
ret = (param->preauth == 2)? 0 : alwaysauth(param);
|
||||||
if (param->afterauthfilters){
|
if (param->nafterauthfilters){
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
|
|
||||||
action = handleafterauthflt(param);
|
action = handleafterauthflt(param);
|
||||||
@ -173,16 +168,18 @@ int doauth(struct clientparam * param){
|
|||||||
|
|
||||||
int ipauth(struct clientparam * param){
|
int ipauth(struct clientparam * param){
|
||||||
int res;
|
int res;
|
||||||
unsigned char *username;
|
unsigned char c;
|
||||||
username = param->username;
|
|
||||||
param->username = NULL;
|
/* the rules are matched as if no name had been given */
|
||||||
|
c = *param->username;
|
||||||
|
*param->username = 0;
|
||||||
res = checkACL(param);
|
res = checkACL(param);
|
||||||
param->username = username;
|
*param->username = c;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int userauth(struct clientparam * param){
|
int userauth(struct clientparam * param){
|
||||||
return (param->username)? 0:4;
|
return (*param->username)? 0:4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dnsauth(struct clientparam * param){
|
int dnsauth(struct clientparam * param){
|
||||||
@ -221,7 +218,7 @@ int dnsauth(struct clientparam * param){
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return param->username? 0:3;
|
return *param->username? 0:3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctmemcmp(const void *a, const void *b, size_t len){
|
static int ctmemcmp(const void *a, const void *b, size_t len){
|
||||||
@ -246,8 +243,8 @@ int strongauth(struct clientparam * param){
|
|||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
char pass[256] = {0};
|
char pass[256] = {0};
|
||||||
|
|
||||||
if (!param->username) return 4;
|
if (!*param->username) return 4;
|
||||||
if (!param->pwtype && param->password) {
|
if (!param->pwtype && *param->password) {
|
||||||
if (pwl_table.ihashtable && hashresolv(&pwl_table, param->username, pass, NULL)) {
|
if (pwl_table.ihashtable && hashresolv(&pwl_table, param->username, pass, NULL)) {
|
||||||
switch(pass[0]){
|
switch(pass[0]){
|
||||||
case CL: {
|
case CL: {
|
||||||
|
|||||||
@ -401,7 +401,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
|||||||
total_length += (2+len);
|
total_length += (2+len);
|
||||||
|
|
||||||
/* Called-Station-ID */
|
/* Called-Station-ID */
|
||||||
if(param->hostname){
|
if(*param->hostname){
|
||||||
*ptr++ = PW_CALLED_STATION_ID;
|
*ptr++ = PW_CALLED_STATION_ID;
|
||||||
len = strlen((char *)param->hostname);
|
len = strlen((char *)param->hostname);
|
||||||
if(len > 253) len = 253;
|
if(len > 253) len = 253;
|
||||||
@ -443,7 +443,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
|||||||
|
|
||||||
|
|
||||||
/* Username */
|
/* Username */
|
||||||
if(param->username){
|
if(*param->username){
|
||||||
len = strlen((char *)param->username);
|
len = strlen((char *)param->username);
|
||||||
if(len>128)len=128;
|
if(len>128)len=128;
|
||||||
*ptr++ = PW_USER_NAME;
|
*ptr++ = PW_USER_NAME;
|
||||||
@ -502,7 +502,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
|||||||
total_length+=6;
|
total_length+=6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auth && param->password){
|
if(auth && *param->password){
|
||||||
len = strlen((char *)param->password);
|
len = strlen((char *)param->password);
|
||||||
if(len > 128) len = 128;
|
if(len > 128) len = 128;
|
||||||
*ptr++ = PW_PASSWORD;
|
*ptr++ = PW_PASSWORD;
|
||||||
|
|||||||
@ -12,12 +12,7 @@
|
|||||||
void * autochild(struct clientparam* param) {
|
void * autochild(struct clientparam* param) {
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if(!param->clibuf){
|
len = sockfillbuf(param, CLIENT, 1, CONNECTION_S);
|
||||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return 0;
|
|
||||||
param->clibufsize = SRVBUFSIZE;
|
|
||||||
param->clioffset = param->cliinbuf = 0;
|
|
||||||
}
|
|
||||||
len = sockfillbuffcli(param, 1, CONNECTION_S);
|
|
||||||
if (len != 1){
|
if (len != 1){
|
||||||
param->res = 801;
|
param->res = 801;
|
||||||
dolog(param, (unsigned char *)"");
|
dolog(param, (unsigned char *)"");
|
||||||
|
|||||||
48
src/common.c
48
src/common.c
@ -561,9 +561,10 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
|
|||||||
if(sp) *sp = ':';
|
if(sp) *sp = ':';
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(hostname != (char *)param->hostname){
|
if(PARAMSTR(param, hostname, hostname + (se!=0))){
|
||||||
if(param->hostname) free(param->hostname);
|
if(se) *se = ']';
|
||||||
param->hostname = (unsigned char *)strdup(hostname + (se!=0));
|
if(sp) *sp = ':';
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
if(sp){
|
if(sp){
|
||||||
port = atoi(sp+1);
|
port = atoi(sp+1);
|
||||||
@ -576,6 +577,22 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copies a string into one of a connection's fixed fields. One too long for
|
||||||
|
it is refused rather than cut short, which could name another host or
|
||||||
|
another user; NULL empties it. The string may be part of the field. */
|
||||||
|
int paramstr(unsigned char *field, size_t size, const unsigned char *s){
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if(!s){
|
||||||
|
*field = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = strlen((const char *)s);
|
||||||
|
if(len >= size) return 1;
|
||||||
|
memmove(field, s, len + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parseusername(char *username, struct clientparam *param, int extpasswd){
|
int parseusername(char *username, struct clientparam *param, int extpasswd){
|
||||||
char *sb = NULL, *se = NULL, *sp = NULL;
|
char *sb = NULL, *se = NULL, *sp = NULL;
|
||||||
|
|
||||||
@ -584,13 +601,12 @@ int parseusername(char *username, struct clientparam *param, int extpasswd){
|
|||||||
*sb = 0;
|
*sb = 0;
|
||||||
*se = 0;
|
*se = 0;
|
||||||
if(sp) *sp = 0;
|
if(sp) *sp = 0;
|
||||||
if(*(sb+1)) {
|
if((*(sb+1) && PARAMSTR(param, password, sb+1)) ||
|
||||||
if(param->password) free(param->password);
|
(*username && PARAMSTR(param, username, username))){
|
||||||
param->password = (unsigned char *)strdup(sb+1);
|
*sb = ':';
|
||||||
}
|
*se = ':';
|
||||||
if(*username) {
|
if(sp) *sp = ':';
|
||||||
if(param->username) free(param->username);
|
return 1;
|
||||||
param->username = (unsigned char *)strdup(username);
|
|
||||||
}
|
}
|
||||||
username = se+1;
|
username = se+1;
|
||||||
}
|
}
|
||||||
@ -598,24 +614,22 @@ int parseusername(char *username, struct clientparam *param, int extpasswd){
|
|||||||
if(!sp) sp = strchr(username, ':');
|
if(!sp) sp = strchr(username, ':');
|
||||||
if(sp){
|
if(sp){
|
||||||
*sp = 0;
|
*sp = 0;
|
||||||
if(param->extpassword) free(param->extpassword);
|
if(PARAMSTR(param, extpassword, sp+1)) extpasswd = -1;
|
||||||
param->extpassword = (unsigned char *) strdup(sp+1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(param->extusername) free(param->extusername);
|
if(extpasswd < 0 || PARAMSTR(param, extusername, username)) extpasswd = -1;
|
||||||
param->extusername = (unsigned char *)strdup(username);
|
|
||||||
if(sb) *sb = ':';
|
if(sb) *sb = ':';
|
||||||
if(se) *se = ':';
|
if(se) *se = ':';
|
||||||
if(sp) *sp = ':';
|
if(sp) *sp = ':';
|
||||||
return 0;
|
return extpasswd < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parseconnusername(char *username, struct clientparam *param, int extpasswd, uint16_t port){
|
int parseconnusername(char *username, struct clientparam *param, int extpasswd, uint16_t port){
|
||||||
char *sb, *se;
|
char *sb, *se;
|
||||||
if(!username || !*username) return 1;
|
if(!username || !*username) return 1;
|
||||||
if ((sb=strchr(username, conf.delimchar)) == NULL){
|
if ((sb=strchr(username, conf.delimchar)) == NULL){
|
||||||
if(!param->hostname && param->remsock == INVALID_SOCKET) return 2;
|
if(!*param->hostname && param->remsock == INVALID_SOCKET) return 2;
|
||||||
if(param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(¶m->req)? ntohs(*SAPORT(¶m->req)) : port);
|
if(*param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(¶m->req)? ntohs(*SAPORT(¶m->req)) : port);
|
||||||
return parseusername(username, param, extpasswd);
|
return parseusername(username, param, extpasswd);
|
||||||
}
|
}
|
||||||
while ((se=strchr(sb+1, conf.delimchar)))sb=se;
|
while ((se=strchr(sb+1, conf.delimchar)))sb=se;
|
||||||
|
|||||||
@ -162,7 +162,7 @@ int start_proxy_thread(struct child * chp){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if((res = mainprepare(chp->argc, (char **)chp->argv, &service))) {
|
if((res = mainprepare(chp->argc, (char **)chp->argv, &service))) {
|
||||||
fprintf(stderr, "Service not started on line: %d%s\n", linenum, res == 2? ": insufficient memory":"");
|
fprintf(stderr, "Service not started on line: %d%s\n", linenum, res == 2? ": insufficient memory": res == 3? ": too many filters":"");
|
||||||
return(40);
|
return(40);
|
||||||
}
|
}
|
||||||
_3proxy_mutex_lock(&runningservices_mutex);
|
_3proxy_mutex_lock(&runningservices_mutex);
|
||||||
|
|||||||
@ -41,7 +41,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
|
|||||||
*innbuf = i;
|
*innbuf = i;
|
||||||
return 702;
|
return 702;
|
||||||
}
|
}
|
||||||
sprintf(buf, "USER %.128s\r\n", param->extusername?param->extusername:(unsigned char *)"anonymous");
|
sprintf(buf, "USER %.128s\r\n", *param->extusername?param->extusername:(unsigned char *)"anonymous");
|
||||||
if((int)socksend(param, param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
|
if((int)socksend(param, param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
|
||||||
return 703;
|
return 703;
|
||||||
}
|
}
|
||||||
@ -53,10 +53,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
|
|||||||
res = atoi(buf)/100;
|
res = atoi(buf)/100;
|
||||||
if(res == 3){
|
if(res == 3){
|
||||||
sprintf(buf, "PASS %.128s\r\n",
|
sprintf(buf, "PASS %.128s\r\n",
|
||||||
param->extusername?
|
*param->extusername? param->extpassword : (unsigned char *)"3proxy@");
|
||||||
(param->extpassword?
|
|
||||||
param->extpassword:(unsigned char *)"")
|
|
||||||
:(unsigned char *)"3proxy@");
|
|
||||||
res = (int)strlen(buf);
|
res = (int)strlen(buf);
|
||||||
if((int)socksend(param, param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
|
if((int)socksend(param, param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
|
||||||
return 705;
|
return 705;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
#endif
|
#endif
|
||||||
struct pollfd fds;
|
struct pollfd fds;
|
||||||
|
|
||||||
if(!(buf = malloc(BUFSIZE))) RETURN(876);
|
buf = param->tmpbuf; /* a filter may replace it with one of its own */
|
||||||
param->ctrlsock = param->clisock;
|
param->ctrlsock = param->clisock;
|
||||||
param->operation = CONNECT;
|
param->operation = CONNECT;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@ -73,11 +73,11 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
/* The user name carries the server to log in to, and it arrives
|
/* The user name carries the server to log in to, and it arrives
|
||||||
with USER. Without it there is nothing to log in to, and what
|
with USER. Without it there is nothing to log in to, and what
|
||||||
follows would read the name and the host as if there were. */
|
follows would read the name and the host as if there were. */
|
||||||
if(!param->hostname || !param->extusername){
|
if(!*param->hostname || !*param->extusername){
|
||||||
socksend(param, param->ctrlsock, (unsigned char *)"503 Login with USER first\r\n", 27, conf.timeouts[STRING_S]);
|
socksend(param, param->ctrlsock, (unsigned char *)"503 Login with USER first\r\n", 27, conf.timeouts[STRING_S]);
|
||||||
RETURN(805);
|
RETURN(805);
|
||||||
}
|
}
|
||||||
param->extpassword = (unsigned char *)strdup((char *)buf+5);
|
if(PARAMSTR(param, extpassword, buf+5)){RETURN(806);}
|
||||||
inbuf = BUFSIZE;
|
inbuf = BUFSIZE;
|
||||||
res = ftplogin(param, (char *)buf, &inbuf);
|
res = ftplogin(param, (char *)buf, &inbuf);
|
||||||
param->res = res;
|
param->res = res;
|
||||||
@ -341,7 +341,7 @@ CLEANRET:
|
|||||||
dolog(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
|
dolog(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
|
||||||
}
|
}
|
||||||
if(req) free(req);
|
if(req) free(req);
|
||||||
if(buf) free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,13 +31,13 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
|
|||||||
int oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0;
|
int oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0;
|
||||||
|
|
||||||
|
|
||||||
if((type & 2) && param->username) ulen = strlen((const char *)param->username) + 1;
|
if((type & 2) && *param->username) ulen = strlen((const char *)param->username) + 1;
|
||||||
if((type & 4) && param->password) plen = strlen((const char *)param->password) + 1;
|
if((type & 4) && *param->password) plen = strlen((const char *)param->password) + 1;
|
||||||
if((type & 1) && !(type & 8)) a1len = SAADDRLEN(¶m->sincr);
|
if((type & 1) && !(type & 8)) a1len = SAADDRLEN(¶m->sincr);
|
||||||
if((type & 16)) acllen = sizeof(param->srv->acl);
|
if((type & 16)) acllen = sizeof(param->srv->acl);
|
||||||
if((type & 64)) a2len = SAADDRLEN(¶m->req);
|
if((type & 64)) a2len = SAADDRLEN(¶m->req);
|
||||||
if((type & 128)) p1len = 2 ;
|
if((type & 128)) p1len = 2 ;
|
||||||
if((type & 256) && param->hostname) hlen = strlen((const char *)param->hostname) + 1;
|
if((type & 256) && *param->hostname) hlen = strlen((const char *)param->hostname) + 1;
|
||||||
if((type & 512)) oplen = sizeof(param->operation);
|
if((type & 512)) oplen = sizeof(param->operation);
|
||||||
if((type & 1024)) a3len = SAADDRLEN(¶m->srv->intsa);
|
if((type & 1024)) a3len = SAADDRLEN(¶m->srv->intsa);
|
||||||
if((type & 2048)) p2len = 2;
|
if((type & 2048)) p2len = 2;
|
||||||
@ -45,13 +45,13 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
|
|||||||
memset(hash, 0, ht->hash_size);
|
memset(hash, 0, ht->hash_size);
|
||||||
if(ulen + plen + a1len + acllen + a2len + p1len + hlen + oplen + a3len + p2len <= ht->hash_size){
|
if(ulen + plen + a1len + acllen + a2len + p1len + hlen + oplen + a3len + p2len <= ht->hash_size){
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if((type & 2) && param->username){ memcpy(hash + offset, param->username, ulen); offset += ulen; }
|
if((type & 2) && *param->username){ memcpy(hash + offset, param->username, ulen); offset += ulen; }
|
||||||
if((type & 4) && param->password){ memcpy(hash + offset, param->password, plen); offset += plen; }
|
if((type & 4) && *param->password){ memcpy(hash + offset, param->password, plen); offset += plen; }
|
||||||
if((type & 1) && !(type & 8)){ memcpy(hash + offset, SAADDR(¶m->sincr), a1len); offset += a1len; }
|
if((type & 1) && !(type & 8)){ memcpy(hash + offset, SAADDR(¶m->sincr), a1len); offset += a1len; }
|
||||||
if((type & 16)){ memcpy(hash + offset, ¶m->srv->acl, acllen); offset += acllen; }
|
if((type & 16)){ memcpy(hash + offset, ¶m->srv->acl, acllen); offset += acllen; }
|
||||||
if((type & 64)){ memcpy(hash + offset, SAADDR(¶m->req), a2len); offset += a2len; }
|
if((type & 64)){ memcpy(hash + offset, SAADDR(¶m->req), a2len); offset += a2len; }
|
||||||
if((type & 128)){ memcpy(hash + offset, SAPORT(¶m->req), p1len); offset += 2; }
|
if((type & 128)){ memcpy(hash + offset, SAPORT(¶m->req), p1len); offset += 2; }
|
||||||
if((type & 256) && param->hostname){ memcpy(hash + offset, param->hostname, hlen); offset += hlen; }
|
if((type & 256) && *param->hostname){ memcpy(hash + offset, param->hostname, hlen); offset += hlen; }
|
||||||
if((type & 512)){ memcpy(hash + offset, ¶m->operation, oplen); offset += oplen; }
|
if((type & 512)){ memcpy(hash + offset, ¶m->operation, oplen); offset += oplen; }
|
||||||
if((type & 1024)){ memcpy(hash + offset, SAADDR(¶m->srv->intsa), a3len); offset += a3len; }
|
if((type & 1024)){ memcpy(hash + offset, SAADDR(¶m->srv->intsa), a3len); offset += a3len; }
|
||||||
if((type & 2048)){ memcpy(hash + offset, SAPORT(¶m->srv->intsa), p2len); offset += 2; }
|
if((type & 2048)){ memcpy(hash + offset, SAPORT(¶m->srv->intsa), p2len); offset += 2; }
|
||||||
@ -60,13 +60,13 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
|
|||||||
mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
|
mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
|
||||||
unsigned int blen = ht->hash_size;
|
unsigned int blen = ht->hash_size;
|
||||||
if(!bctx) { memcpy(param->hash, hash, ht->hash_size); return; }
|
if(!bctx) { memcpy(param->hash, hash, ht->hash_size); return; }
|
||||||
if((type & 2) && param->username)mdh_update(bctx, param->username, ulen);
|
if((type & 2) && *param->username)mdh_update(bctx, param->username, ulen);
|
||||||
if((type & 4) && param->password)mdh_update(bctx, param->password, plen);
|
if((type & 4) && *param->password)mdh_update(bctx, param->password, plen);
|
||||||
if((type & 1) && !(type & 8))mdh_update(bctx, SAADDR(¶m->sincr), a1len);
|
if((type & 1) && !(type & 8))mdh_update(bctx, SAADDR(¶m->sincr), a1len);
|
||||||
if((type & 16))mdh_update(bctx, ¶m->srv->acl, acllen);
|
if((type & 16))mdh_update(bctx, ¶m->srv->acl, acllen);
|
||||||
if((type & 64))mdh_update(bctx, SAADDR(¶m->req), a2len);
|
if((type & 64))mdh_update(bctx, SAADDR(¶m->req), a2len);
|
||||||
if((type & 128))mdh_update(bctx, SAPORT(¶m->req), 2);
|
if((type & 128))mdh_update(bctx, SAPORT(¶m->req), 2);
|
||||||
if((type & 256) && param->hostname)mdh_update(bctx, param->hostname, hlen);
|
if((type & 256) && *param->hostname)mdh_update(bctx, param->hostname, hlen);
|
||||||
if((type & 512))mdh_update(bctx, ¶m->operation, sizeof(param->operation));
|
if((type & 512))mdh_update(bctx, ¶m->operation, sizeof(param->operation));
|
||||||
if((type & 1024))mdh_update(bctx, SAADDR(¶m->srv->intsa), a3len);
|
if((type & 1024))mdh_update(bctx, SAADDR(¶m->srv->intsa), a3len);
|
||||||
if((type & 2048))mdh_update(bctx, SAPORT(¶m->srv->intsa), 2);
|
if((type & 2048))mdh_update(bctx, SAPORT(¶m->srv->intsa), 2);
|
||||||
|
|||||||
@ -54,8 +54,6 @@
|
|||||||
after it should be tried again. */
|
after it should be tried again. */
|
||||||
#define HTTPSRV_REWRITTEN 2
|
#define HTTPSRV_REWRITTEN 2
|
||||||
#define HTTPSRV_MAXBODY 1048576
|
#define HTTPSRV_MAXBODY 1048576
|
||||||
/* the most of a request this server keeps in case it hands it on */
|
|
||||||
#define HTTPSRV_MAXRAW 65536
|
|
||||||
/* lengths a reply is written with: a count, or one of these */
|
/* lengths a reply is written with: a count, or one of these */
|
||||||
#define HTTPSRV_LEN_CHUNKED (-1)
|
#define HTTPSRV_LEN_CHUNKED (-1)
|
||||||
#define HTTPSRV_LEN_NONE (-2)
|
#define HTTPSRV_LEN_NONE (-2)
|
||||||
@ -582,7 +580,7 @@ static const char * contenttype(const char *path)
|
|||||||
static int sendfilecontent(struct httpreq *r, int fd, uint64_t size)
|
static int sendfilecontent(struct httpreq *r, int fd, uint64_t size)
|
||||||
{
|
{
|
||||||
struct clientparam *param = r->param;
|
struct clientparam *param = r->param;
|
||||||
char buf[HTTPSRV_BLOCK];
|
char *buf = (char *)param->tmpbuf;
|
||||||
uint64_t sent = 0;
|
uint64_t sent = 0;
|
||||||
|
|
||||||
#ifdef HTTPSRV_SENDFILE
|
#ifdef HTTPSRV_SENDFILE
|
||||||
@ -627,7 +625,7 @@ static int sendfilecontent(struct httpreq *r, int fd, uint64_t size)
|
|||||||
if(lseek(fd, (off_t)sent, SEEK_SET) == (off_t)-1) return 1;
|
if(lseek(fd, (off_t)sent, SEEK_SET) == (off_t)-1) return 1;
|
||||||
while(sent < size){
|
while(sent < size){
|
||||||
uint64_t left = size - sent;
|
uint64_t left = size - sent;
|
||||||
int want = left > (uint64_t)sizeof(buf)? (int)sizeof(buf) : (int)left;
|
int want = left > (uint64_t)HTTPSRV_BLOCK? (int)HTTPSRV_BLOCK : (int)left;
|
||||||
int got;
|
int got;
|
||||||
|
|
||||||
got = (int)read(fd, buf, want);
|
got = (int)read(fd, buf, want);
|
||||||
@ -988,7 +986,7 @@ static int op_echo(struct httpreq *r, const unsigned char *params)
|
|||||||
Produces exactly N bytes of body. */
|
Produces exactly N bytes of body. */
|
||||||
static int op_data(struct httpreq *r, const unsigned char *params)
|
static int op_data(struct httpreq *r, const unsigned char *params)
|
||||||
{
|
{
|
||||||
char buf[HTTPSRV_BLOCK];
|
char *buf = (char *)r->param->tmpbuf;
|
||||||
int64_t size, block, delay, status;
|
int64_t size, block, delay, status;
|
||||||
int chunked;
|
int chunked;
|
||||||
uint64_t sent = 0;
|
uint64_t sent = 0;
|
||||||
@ -1141,11 +1139,12 @@ int httpopbyname(const unsigned char *name)
|
|||||||
*/
|
*/
|
||||||
static void httpsrv_drain(struct clientparam *param, uint64_t len)
|
static void httpsrv_drain(struct clientparam *param, uint64_t len)
|
||||||
{
|
{
|
||||||
char buf[HTTPSRV_BLOCK];
|
char *buf = (char *)param->tmpbuf;
|
||||||
|
|
||||||
|
param->climark = -1; /* answered here: the request is not needed again */
|
||||||
if(len > HTTPSRV_MAXBODY) len = HTTPSRV_MAXBODY;
|
if(len > HTTPSRV_MAXBODY) len = HTTPSRV_MAXBODY;
|
||||||
while(len){
|
while(len){
|
||||||
int want = (len > (uint64_t)sizeof(buf))? (int)sizeof(buf) : (int)len;
|
int want = (len > (uint64_t)HTTPSRV_BLOCK)? (int)HTTPSRV_BLOCK : (int)len;
|
||||||
int got = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, want, EOF,
|
int got = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, want, EOF,
|
||||||
conf.timeouts[STRING_S]);
|
conf.timeouts[STRING_S]);
|
||||||
|
|
||||||
@ -1162,7 +1161,7 @@ static void httpsrv_drain(struct clientparam *param, uint64_t len)
|
|||||||
and amount, which is what lets the answer be read. */
|
and amount, which is what lets the answer be read. */
|
||||||
static void httpsrv_linger(struct clientparam *param)
|
static void httpsrv_linger(struct clientparam *param)
|
||||||
{
|
{
|
||||||
char buf[HTTPSRV_BLOCK];
|
char *buf = (char *)param->tmpbuf;
|
||||||
struct pollfd fd;
|
struct pollfd fd;
|
||||||
uint64_t left = HTTPSRV_MAXBODY;
|
uint64_t left = HTTPSRV_MAXBODY;
|
||||||
time_t deadline = time(NULL) + conf.timeouts[LINGER_TO];
|
time_t deadline = time(NULL) + conf.timeouts[LINGER_TO];
|
||||||
@ -1179,33 +1178,12 @@ static void httpsrv_linger(struct clientparam *param)
|
|||||||
fd.events = POLLIN;
|
fd.events = POLLIN;
|
||||||
if(param->srv->so._poll(param->sostate, &fd, 1, timeo * 1000) <= 0) break;
|
if(param->srv->so._poll(param->sostate, &fd, 1, timeo * 1000) <= 0) break;
|
||||||
got = (int)param->srv->so._recv(param->sostate, param->clisock, buf,
|
got = (int)param->srv->so._recv(param->sostate, param->clisock, buf,
|
||||||
(left > sizeof(buf))? (int)sizeof(buf) : (int)left, 0);
|
(left > HTTPSRV_BLOCK)? (int)HTTPSRV_BLOCK : (int)left, 0);
|
||||||
if(got <= 0) break;
|
if(got <= 0) break;
|
||||||
left -= (uint64_t)got;
|
left -= (uint64_t)got;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keeps the request as the client wrote it. Only what a handoff needs: the
|
|
||||||
request line and the headers, exactly as they came, since the proxy code
|
|
||||||
reads them again from the beginning. */
|
|
||||||
static int rawkeep(struct httpreq *r, const char *line, int len)
|
|
||||||
{
|
|
||||||
if(r->rawlen + len + 3 > r->rawsize){
|
|
||||||
int want = r->rawsize? r->rawsize * 2 : 2048;
|
|
||||||
unsigned char *grown;
|
|
||||||
|
|
||||||
while(want < r->rawlen + len + 3) want *= 2;
|
|
||||||
if(want > HTTPSRV_MAXRAW) return 1;
|
|
||||||
grown = realloc(r->raw, (size_t)want);
|
|
||||||
if(!grown) return 1;
|
|
||||||
r->raw = grown;
|
|
||||||
r->rawsize = want;
|
|
||||||
}
|
|
||||||
memcpy(r->raw + r->rawlen, line, (size_t)len);
|
|
||||||
r->rawlen += len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hands the request to the proxy code, which reads it again from the client
|
/* Hands the request to the proxy code, which reads it again from the client
|
||||||
buffer and answers it as a proxy would, asking for its own credentials if
|
buffer and answers it as a proxy would, asking for its own credentials if
|
||||||
the configuration wants them. The connection stays with this service. */
|
the configuration wants them. The connection stays with this service. */
|
||||||
@ -1220,7 +1198,7 @@ static int proxypass(struct clientparam *param, struct httpreq *r)
|
|||||||
a request already being answered on behalf of another child is never
|
a request already being answered on behalf of another child is never
|
||||||
handed on again. */
|
handed on again. */
|
||||||
if(param->onerequest) return 1;
|
if(param->onerequest) return 1;
|
||||||
if(!r->raw || rawkeep(r, "\r\n", 2)) return 1; /* the end of the headers */
|
if(param->climark < 0) return 1; /* the request is no longer there */
|
||||||
|
|
||||||
/* What is open towards the server belongs to the request before this
|
/* What is open towards the server belongs to the request before this
|
||||||
one. It is no use for this request if it went somewhere else, and no
|
one. It is no use for this request if it went somewhere else, and no
|
||||||
@ -1255,7 +1233,9 @@ static int proxypass(struct clientparam *param, struct httpreq *r)
|
|||||||
r->lasthost[255] = 0;
|
r->lasthost[255] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pushbackcli(param, r->raw, r->rawlen)) return 1;
|
/* the proxy reads the request from where it began */
|
||||||
|
param->clioffset = (unsigned)param->climark;
|
||||||
|
param->climark = -1;
|
||||||
|
|
||||||
param->onerequest = 1;
|
param->onerequest = 1;
|
||||||
next = proxychild(param);
|
next = proxychild(param);
|
||||||
@ -1283,11 +1263,15 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
struct httprule *rule;
|
struct httprule *rule;
|
||||||
int i, hdrs = 0;
|
int i, hdrs = 0;
|
||||||
|
|
||||||
|
/* The request is kept in the client buffer as it is read, so that one
|
||||||
|
handed to the proxy can be read there again from the start. One which
|
||||||
|
does not fit in the buffer is not answered. */
|
||||||
|
param->climark = (int)param->clioffset;
|
||||||
i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, sizeof(buf) - 1, '\n',
|
i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, sizeof(buf) - 1, '\n',
|
||||||
conf.timeouts[STRING_S]);
|
conf.timeouts[STRING_S]);
|
||||||
if(i <= 0 && !r->first) return 0; /* the client is done with us */
|
if(i <= 0 && !r->first) return 0; /* the client is done with us */
|
||||||
|
if(param->climark == -2) RETURN(710);
|
||||||
if(i < 5) RETURN(701);
|
if(i < 5) RETURN(701);
|
||||||
if(rawkeep(r, buf, i)) RETURN(710);
|
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
|
|
||||||
sp = strchr(buf, ' ');
|
sp = strchr(buf, ' ');
|
||||||
@ -1368,7 +1352,6 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
(i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, sizeof(buf) - 1,
|
(i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, sizeof(buf) - 1,
|
||||||
'\n', conf.timeouts[STRING_S])) > 2){
|
'\n', conf.timeouts[STRING_S])) > 2){
|
||||||
hdrs++;
|
hdrs++;
|
||||||
if(rawkeep(r, buf, i)) RETURN(710);
|
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
if(!strncasecmp(buf, "host:", 5) && !r->proxy){
|
if(!strncasecmp(buf, "host:", 5) && !r->proxy){
|
||||||
sp = buf + 5;
|
sp = buf + 5;
|
||||||
@ -1393,13 +1376,10 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
creds[clen] = 0;
|
creds[clen] = 0;
|
||||||
|
|
||||||
q = strchr(creds, ':');
|
q = strchr(creds, ':');
|
||||||
if(q){
|
if(q) *q = 0;
|
||||||
*q = 0;
|
/* credentials too long to keep are no credentials */
|
||||||
if(param->password) free(param->password);
|
if((q && PARAMSTR(param, password, q + 1)) || PARAMSTR(param, username, creds))
|
||||||
param->password = (unsigned char *)strdup(q + 1);
|
*param->username = *param->password = 0;
|
||||||
}
|
|
||||||
if(param->username) free(param->username);
|
|
||||||
param->username = (unsigned char *)strdup(creds);
|
|
||||||
}
|
}
|
||||||
else if(!strncasecmp(buf, "connection:", 11)){
|
else if(!strncasecmp(buf, "connection:", 11)){
|
||||||
sp = buf + 11;
|
sp = buf + 11;
|
||||||
@ -1422,6 +1402,7 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(param->climark == -2) RETURN(710);
|
||||||
/* The headers ran past what this server reads, so the rest of the request
|
/* The headers ran past what this server reads, so the rest of the request
|
||||||
is still in the stream and there is no answering it: what follows would
|
is still in the stream and there is no answering it: what follows would
|
||||||
be read as the request after this one. */
|
be read as the request after this one. */
|
||||||
@ -1453,8 +1434,7 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
if(colon) *colon = 0;
|
if(colon) *colon = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(param->hostname) free(param->hostname);
|
if(PARAMSTR(param, hostname, host)) RETURN(706);
|
||||||
param->hostname = (unsigned char *)strdup(host);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The request is answered here, so the address it was sent to is the
|
/* The request is answered here, so the address it was sent to is the
|
||||||
@ -1594,7 +1574,7 @@ void * httpsrvchild(struct clientparam *param)
|
|||||||
|
|
||||||
answered = httpsrv_request(param, &r);
|
answered = httpsrv_request(param, &r);
|
||||||
handoff = r.handoff;
|
handoff = r.handoff;
|
||||||
if(r.raw) free(r.raw);
|
param->climark = -1;
|
||||||
if(!answered) break;
|
if(!answered) break;
|
||||||
|
|
||||||
/* Log the request the way the proxy does: the parameters decide
|
/* Log the request the way the proxy does: the parameters decide
|
||||||
|
|||||||
@ -152,7 +152,7 @@ void * imappchild(struct clientparam* param) {
|
|||||||
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
|
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
|
||||||
}
|
}
|
||||||
if(parseconnusername((char *)ub, param, 0, 143)){RETURN(694);}
|
if(parseconnusername((char *)ub, param, 0, 143)){RETURN(694);}
|
||||||
if(*pb && !param->password) param->password = (unsigned char *)strdup((char *)pb);
|
if(*pb && !*param->password && PARAMSTR(param, password, pb)){RETURN(694);}
|
||||||
param->operation = CONNECT;
|
param->operation = CONNECT;
|
||||||
res = (*param->srv->authfunc)(param);
|
res = (*param->srv->authfunc)(param);
|
||||||
if(res) {RETURN(res);}
|
if(res) {RETURN(res);}
|
||||||
@ -227,7 +227,7 @@ void * imappchild(struct clientparam* param) {
|
|||||||
RETURN (mapsocket(param, 180));
|
RETURN (mapsocket(param, 180));
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
if(param->hostname&¶m->extusername) {
|
if(*param->hostname&&*param->extusername) {
|
||||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==143)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==143)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
||||||
dolog(param, buf);
|
dolog(param, buf);
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/log.c
16
src/log.c
@ -155,7 +155,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
|
|||||||
i+=5;
|
i+=5;
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
if(param->username && *param->username){
|
if(*param->username){
|
||||||
for(len = 0; i< 4000 && param->username[len]; len++){
|
for(len = 0; i< 4000 && param->username[len]; len++){
|
||||||
buf[i] = param->username[len];
|
buf[i] = param->username[len];
|
||||||
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
||||||
@ -171,7 +171,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
len = param->hostname? (int)strlen((char *)param->hostname) : 0;
|
len = (int)strlen((char *)param->hostname);
|
||||||
if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < 4000; len++, i++){
|
if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < 4000; len++, i++){
|
||||||
buf[i] = param->hostname[len];
|
buf[i] = param->hostname[len];
|
||||||
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
||||||
@ -338,10 +338,12 @@ void lognone(struct clientparam * param, const unsigned char *s) {
|
|||||||
clearstat(param);
|
clearstat(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||||
FILE *log;
|
FILE *log;
|
||||||
unsigned char tmpbuf[8192];
|
unsigned char *tmpbuf;
|
||||||
|
|
||||||
|
/* with no connection, an error from the main thread */
|
||||||
|
tmpbuf = param? param->tmpbuf : logparam.tmpbuf;
|
||||||
dobuf(param, tmpbuf, s, NULL);
|
dobuf(param, tmpbuf, s, NULL);
|
||||||
log = (param && param->srv && param->srv->stdlog)?param->srv->stdlog:conf.stdlog?conf.stdlog:stdout;
|
log = (param && param->srv && param->srv->stdlog)?param->srv->stdlog:conf.stdlog?conf.stdlog:stdout;
|
||||||
if(!param || !param->nolog)if(fprintf(log, "%s\n", tmpbuf) < 0) {
|
if(!param || !param->nolog)if(fprintf(log, "%s\n", tmpbuf) < 0) {
|
||||||
@ -351,10 +353,8 @@ NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
|||||||
}
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
void logsyslog(struct clientparam * param, const unsigned char *s) {
|
void logsyslog(struct clientparam * param, const unsigned char *s) {
|
||||||
|
dobuf(param, param->tmpbuf, s, NULL);
|
||||||
unsigned char tmpbuf[8192];
|
if(!param->nolog)syslog(LOG_INFO, "%s", param->tmpbuf);
|
||||||
dobuf(param, tmpbuf, s, NULL);
|
|
||||||
if(!param->nolog)syslog(LOG_INFO, "%s", tmpbuf);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -276,6 +276,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
int replen, num;
|
int replen, num;
|
||||||
char * replace;
|
char * replace;
|
||||||
char * tmpbuf, *target, *newbuf;
|
char * tmpbuf, *target, *newbuf;
|
||||||
|
unsigned char *given = *buf_p;
|
||||||
int nreplaces=0;
|
int nreplaces=0;
|
||||||
#define pcrefd ((struct pcre_filter_data *)fc)
|
#define pcrefd ((struct pcre_filter_data *)fc)
|
||||||
|
|
||||||
@ -358,7 +359,9 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
memcpy(newbuf, *buf_p, ovector[0]);
|
memcpy(newbuf, *buf_p, ovector[0]);
|
||||||
pl->freefunc(*buf_p);
|
/* The buffer given is the caller's to free; only one
|
||||||
|
made by an earlier replacement here is ours. */
|
||||||
|
if(*buf_p != given) pl->freefunc(*buf_p);
|
||||||
*buf_p = (unsigned char *)newbuf;
|
*buf_p = (unsigned char *)newbuf;
|
||||||
*bufsize_p = newsize;
|
*bufsize_p = newsize;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -151,7 +151,7 @@ static int ldapfunc(struct clientparam *param)
|
|||||||
char escuser[512];
|
char escuser[512];
|
||||||
|
|
||||||
/* test proxy user auth ------------------------*/
|
/* test proxy user auth ------------------------*/
|
||||||
if(!param->username || !param->password) return 4;
|
if(!*param->username || !*param->password) return 4;
|
||||||
if(strlen(param->password)==0) return 4;
|
if(strlen(param->password)==0) return 4;
|
||||||
|
|
||||||
/* init ldap ---------------------- */
|
/* init ldap ---------------------- */
|
||||||
|
|||||||
@ -78,7 +78,7 @@ static int pamfunc(struct clientparam *param)
|
|||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
/* test proxy user auth ------------------------*/
|
/* test proxy user auth ------------------------*/
|
||||||
if(!param->username || !param->password) return 4;
|
if(!*param->username || !*param->password) return 4;
|
||||||
/*if(strlen(param->password)==0) return 4;*/
|
/*if(strlen(param->password)==0) return 4;*/
|
||||||
|
|
||||||
#ifdef USERCASE
|
#ifdef USERCASE
|
||||||
|
|||||||
@ -31,7 +31,7 @@ extern "C" {
|
|||||||
PTOKEN_GROUPS ptg = (PTOKEN_GROUPS)tokenbuf;
|
PTOKEN_GROUPS ptg = (PTOKEN_GROUPS)tokenbuf;
|
||||||
|
|
||||||
|
|
||||||
if(!param->username || !param->password || param->pwtype != 0) return 4;
|
if(!*param->username || !*param->password || param->pwtype != 0) return 4;
|
||||||
dom = strchr((char *)param->username, '\\');
|
dom = strchr((char *)param->username, '\\');
|
||||||
if(dom)*dom++=0;
|
if(dom)*dom++=0;
|
||||||
if(!LogonUser( dom?dom:(char *)param->username,
|
if(!LogonUser( dom?dom:(char *)param->username,
|
||||||
|
|||||||
@ -54,7 +54,7 @@ unsigned char * conv_utf8_to_cp1251(unsigned char *s){
|
|||||||
|
|
||||||
|
|
||||||
static int aufunc(struct clientparam *param){
|
static int aufunc(struct clientparam *param){
|
||||||
if(!param->username || !param->password || param->pwtype != 0) return 4;
|
if(!*param->username || !*param->password || param->pwtype != 0) return 4;
|
||||||
conv_utf8_to_cp1251(param->username);
|
conv_utf8_to_cp1251(param->username);
|
||||||
conv_utf8_to_cp1251(param->password);
|
conv_utf8_to_cp1251(param->password);
|
||||||
return 4;
|
return 4;
|
||||||
|
|||||||
@ -68,7 +68,7 @@ void * pop3pchild(struct clientparam* param) {
|
|||||||
RETURN (mapsocket(param, 180));
|
RETURN (mapsocket(param, 180));
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
if(param->hostname&¶m->extusername) {
|
if(*param->hostname&&*param->extusername) {
|
||||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
||||||
dolog(param, buf);
|
dolog(param, buf);
|
||||||
}
|
}
|
||||||
|
|||||||
56
src/proxy.c
56
src/proxy.c
@ -157,9 +157,11 @@ static int send_st(struct clientparam *param, int idx){
|
|||||||
return socksend(param, param->clisock, (unsigned char *)proxy_stringtable[idx], pst_len(idx), conf.timeouts[STRING_S]);
|
return socksend(param, param->clisock, (unsigned char *)proxy_stringtable[idx], pst_len(idx), conf.timeouts[STRING_S]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WITHMAIN
|
||||||
/* Makes room in a buffer whose size is tracked. A filter may hand back one
|
/* Makes room in a buffer whose size is tracked. A filter may hand back one
|
||||||
holding exactly what it produced, so nothing may be added to it without
|
holding exactly what it produced, so nothing may be added to it without
|
||||||
asking for the room first. Returns 1 when the room cannot be had. */
|
asking for the room first; without filters, as in a proxy built on its
|
||||||
|
own, there is nothing to ask. Returns 1 when the room cannot be had. */
|
||||||
static int growbuf(unsigned char **buf, int *bufsize, int need){
|
static int growbuf(unsigned char **buf, int *bufsize, int need){
|
||||||
unsigned char *newbuf;
|
unsigned char *newbuf;
|
||||||
|
|
||||||
@ -171,6 +173,16 @@ static int growbuf(unsigned char **buf, int *bufsize, int need){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reads a body of a known length into one buffer, to be filtered whole.
|
||||||
|
One bigger than the connection's own is had for it, up to filtermaxsize;
|
||||||
|
with no limit set a body is only read whole if it fits the buffer.
|
||||||
|
Returns how much is there, less than len if the body did not all come. */
|
||||||
|
static uint64_t fillwhole(struct clientparam *param, DIRECTION which, uint64_t len){
|
||||||
|
if(conf.filtermaxsize && bufroom(param, which, (unsigned long)len)) return 0;
|
||||||
|
return sockfillbuf(param, which, (unsigned long)len, CONNECTION_S);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void freeptr(void *p){
|
static void freeptr(void *p){
|
||||||
void **pp = (void **)p;
|
void **pp = (void **)p;
|
||||||
if(*pp) { free(*pp); *pp = NULL; }
|
if(*pp) { free(*pp); *pp = NULL; }
|
||||||
@ -467,16 +479,11 @@ for(;;){
|
|||||||
sb = (unsigned char *)strchr((char *)username, ':');
|
sb = (unsigned char *)strchr((char *)username, ':');
|
||||||
if(sb){
|
if(sb){
|
||||||
*sb = 0;
|
*sb = 0;
|
||||||
if(param->password)free(param->password);
|
|
||||||
param->password = (unsigned char *)strdup((char *)sb+1);
|
|
||||||
param->pwtype = 0;
|
param->pwtype = 0;
|
||||||
}
|
}
|
||||||
else if(param->password){
|
/* credentials too long to keep are no credentials */
|
||||||
free(param->password);
|
if(PARAMSTR(param, password, sb? sb+1 : NULL) || PARAMSTR(param, username, username))
|
||||||
param->password = NULL;
|
*param->username = *param->password = 0;
|
||||||
}
|
|
||||||
if(param->username)free(param->username);
|
|
||||||
param->username = (unsigned char *)strdup((char *)username);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,11 +519,10 @@ for(;;){
|
|||||||
c = *se;
|
c = *se;
|
||||||
*se = 0;
|
*se = 0;
|
||||||
}
|
}
|
||||||
if(param->hostname && (!*param->hostname || isnumber(param->hostname[strlen((char *)param->hostname) - 1]))){
|
if(*param->hostname && isnumber(param->hostname[strlen((char *)param->hostname) - 1])){
|
||||||
free(param->hostname);
|
*param->hostname = 0;
|
||||||
param->hostname = NULL;
|
|
||||||
}
|
}
|
||||||
if(!param->hostname){
|
if(!*param->hostname){
|
||||||
if(parsehostname((char *)sb, param, 80)) RETURN(100);
|
if(parsehostname((char *)sb, param, 80)) RETURN(100);
|
||||||
}
|
}
|
||||||
newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
|
newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
|
||||||
@ -543,17 +549,9 @@ for(;;){
|
|||||||
if(i<=0)continue;
|
if(i<=0)continue;
|
||||||
username[i] = 0;
|
username[i] = 0;
|
||||||
sb = (unsigned char *)strchr((char *)username, ':');
|
sb = (unsigned char *)strchr((char *)username, ':');
|
||||||
if(sb){
|
if(sb) *sb = 0;
|
||||||
*sb = 0;
|
if(PARAMSTR(param, extpassword, sb? sb+1 : NULL) || PARAMSTR(param, extusername, username))
|
||||||
if(param->extpassword)free(param->extpassword);
|
*param->extusername = *param->extpassword = 0;
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -606,7 +604,7 @@ for(;;){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if(param->srv->needuser > 1 && !param->username) {RETURN(4);}
|
if(param->srv->needuser > 1 && !*param->username) {RETURN(4);}
|
||||||
if((res = (*param->srv->authfunc)(param))) {
|
if((res = (*param->srv->authfunc)(param))) {
|
||||||
if (res <= 10 || haveconnection || param->transparent) RETURN(res);
|
if (res <= 10 || haveconnection || param->transparent) RETURN(res);
|
||||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||||
@ -698,7 +696,7 @@ for(;;){
|
|||||||
}
|
}
|
||||||
else if(param->ndatfilterscli > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64){
|
else if(param->ndatfilterscli > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64){
|
||||||
uint64_t newlen64;
|
uint64_t newlen64;
|
||||||
newlen64 = (uint64_t) sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S);
|
newlen64 = fillwhole(param, CLIENT, contentlength64);
|
||||||
if(newlen64 == contentlength64) {
|
if(newlen64 == contentlength64) {
|
||||||
action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, 0, (int *)¶m->cliinbuf);
|
action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, 0, (int *)¶m->cliinbuf);
|
||||||
if(action == HANDLED){
|
if(action == HANDLED){
|
||||||
@ -1025,9 +1023,9 @@ for(;;){
|
|||||||
if(keepalive <= 1) {
|
if(keepalive <= 1) {
|
||||||
hlen += sprintf((char*)buf + hlen, "Connection: %s\r\n", keepalive? "keep-alive":"close");
|
hlen += sprintf((char*)buf + hlen, "Connection: %s\r\n", keepalive? "keep-alive":"close");
|
||||||
}
|
}
|
||||||
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);
|
||||||
if(!(sb = en64(username, buf + hlen, (int)strlen((char *)username), bufsize - hlen))) {RETURN(21);}
|
if(!(sb = en64(username, buf + hlen, (int)strlen((char *)username), bufsize - hlen))) {RETURN(21);}
|
||||||
hlen = (int)(sb - buf);
|
hlen = (int)(sb - buf);
|
||||||
hlen += sprintf((char*)buf + hlen, "\r\n");
|
hlen += sprintf((char*)buf + hlen, "\r\n");
|
||||||
@ -1198,7 +1196,7 @@ for(;;){
|
|||||||
}
|
}
|
||||||
else if(param->ndatfilterssrv > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64 && 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;
|
uint64_t newlen;
|
||||||
newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S);
|
newlen = fillwhole(param, SERVER, contentlength64);
|
||||||
if(newlen == contentlength64) {
|
if(newlen == contentlength64) {
|
||||||
action = handlepredatflt(param);
|
action = handlepredatflt(param);
|
||||||
if(action == HANDLED){
|
if(action == HANDLED){
|
||||||
|
|||||||
30
src/proxy.h
30
src/proxy.h
@ -22,6 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -36,8 +37,9 @@
|
|||||||
#define MAXNSERVERS 5
|
#define MAXNSERVERS 5
|
||||||
#define DEFAULT_MAXCHILD 500
|
#define DEFAULT_MAXCHILD 500
|
||||||
|
|
||||||
#define TCPBUFSIZE 65536
|
/* How much of a connection's buffer is read into at once: all of it, or
|
||||||
#define SRVBUFSIZE (param->srv->bufsize?param->srv->bufsize:((param->service == S_UDPPM)?UDPBUFSIZE:TCPBUFSIZE))
|
less if the service was told so with -b. */
|
||||||
|
#define SRVBUFSIZE(srv) (((srv)->bufsize > 0 && (srv)->bufsize < CLIENTBUFSIZE)? (unsigned)(srv)->bufsize : CLIENTBUFSIZE)
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -116,17 +118,6 @@ void daemonize(void);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Keeps a callee with a large frame out of the caller's frame, e.g. the
|
|
||||||
8K log buffer of logstdout() out of dolog(), which calls it in a branch
|
|
||||||
taken only when there is no service.
|
|
||||||
*/
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define NOINLINE __attribute__((noinline))
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#define NOINLINE __declspec(noinline)
|
|
||||||
#else
|
|
||||||
#define NOINLINE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Thread stack size, stacksize command value is added to it. BSD libc uses
|
/* Thread stack size, stacksize command value is added to it. BSD libc uses
|
||||||
significantly more stack, e.g. in vfprintf() called by syslog().
|
significantly more stack, e.g. in vfprintf() called by syslog().
|
||||||
@ -258,8 +249,12 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
|||||||
|
|
||||||
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec);
|
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec);
|
||||||
int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec);
|
int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec);
|
||||||
unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, int timeosec);
|
unsigned long sockfillbuf(struct clientparam * param, DIRECTION which, unsigned long size, int timeosec);
|
||||||
unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec);
|
int bufroom(struct clientparam * param, DIRECTION which, unsigned long size);
|
||||||
|
int paramstr(unsigned char *field, size_t size, const unsigned char *s);
|
||||||
|
/* sets one of a connection's names or credentials; 1 if it is too long */
|
||||||
|
#define PARAMSTR(p, f, s) paramstr((p)->f, sizeof((p)->f), (const unsigned char *)(s))
|
||||||
|
void bufrelease(struct clientparam * param, DIRECTION which);
|
||||||
|
|
||||||
int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
|
int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
|
||||||
int getmultiline(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, const char *cap, int *found);
|
int getmultiline(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, const char *cap, int *found);
|
||||||
@ -272,7 +267,7 @@ void dolog(struct clientparam * param, const unsigned char *s);
|
|||||||
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
|
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
|
||||||
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
|
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
|
||||||
extern FILE * stdlog;
|
extern FILE * stdlog;
|
||||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s);
|
void logstdout(struct clientparam * param, const unsigned char *s);
|
||||||
void logsyslog(struct clientparam * param, const unsigned char *s);
|
void logsyslog(struct clientparam * param, const unsigned char *s);
|
||||||
void lognone(struct clientparam * param, const unsigned char *s);
|
void lognone(struct clientparam * param, const unsigned char *s);
|
||||||
void logradius(struct clientparam * param, const unsigned char *s);
|
void logradius(struct clientparam * param, const unsigned char *s);
|
||||||
@ -387,7 +382,7 @@ void freefilter(struct filter *filter);
|
|||||||
void freeconf(struct extparam *confp);
|
void freeconf(struct extparam *confp);
|
||||||
struct passwords * copypwl (struct passwords *pwl);
|
struct passwords * copypwl (struct passwords *pwl);
|
||||||
void freepwl(struct passwords *pw);
|
void freepwl(struct passwords *pw);
|
||||||
void copyfilter(struct filter *, struct srvparam *srv);
|
int copyfilter(struct filter *, struct srvparam *srv);
|
||||||
FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param);
|
FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param);
|
||||||
FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p);
|
FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p);
|
||||||
FILTER_ACTION handleconnectflt(struct clientparam *param);
|
FILTER_ACTION handleconnectflt(struct clientparam *param);
|
||||||
@ -417,7 +412,6 @@ void pcre_pattern_free(void *re);
|
|||||||
int pcre_pattern_match(void *re, const unsigned char *subject, struct capture *caps, int maxcaps);
|
int pcre_pattern_match(void *re, const unsigned char *subject, struct capture *caps, int maxcaps);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int pushbackcli(struct clientparam * param, const unsigned char * data, int len);
|
|
||||||
int parsepattern(struct hostname *h, unsigned char *arg);
|
int parsepattern(struct hostname *h, unsigned char *arg);
|
||||||
int parsepathpattern(struct hostname *h, unsigned char *arg);
|
int parsepathpattern(struct hostname *h, unsigned char *arg);
|
||||||
int patternmatchcaps(const struct hostname *h, const unsigned char *str,
|
int patternmatchcaps(const struct hostname *h, const unsigned char *str,
|
||||||
|
|||||||
@ -312,7 +312,6 @@ struct srvstart {
|
|||||||
/* Releases what the preparation and the run took, s itself excepted. */
|
/* Releases what the preparation and the run took, s itself excepted. */
|
||||||
static void srvdiscard(struct srvstart *s){
|
static void srvdiscard(struct srvstart *s){
|
||||||
srvfree(&s->srv);
|
srvfree(&s->srv);
|
||||||
if(s->defparam.hostname) free(s->defparam.hostname);
|
|
||||||
if(s->cbc_string) free(s->cbc_string);
|
if(s->cbc_string) free(s->cbc_string);
|
||||||
if(s->cbl_string) free(s->cbl_string);
|
if(s->cbl_string) free(s->cbl_string);
|
||||||
if(s->fp) fclose(s->fp);
|
if(s->fp) fclose(s->fp);
|
||||||
@ -751,7 +750,7 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
|||||||
|
|
||||||
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
copyfilter(conf.filters, srv);
|
if((error = copyfilter(conf.filters, srv))) return error;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1055,8 +1054,10 @@ static int srvspawn(struct srvstart *s, SOCKET client_sock){
|
|||||||
usleep(SLEEPTIME);
|
usleep(SLEEPTIME);
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
*newparam = *defparam;
|
memcpy(newparam, defparam, offsetof(struct clientparam, filters));
|
||||||
if(defparam->hostname)newparam->hostname=(unsigned char *)strdup((char *)defparam->hostname);
|
newparam->clibuf = newparam->clibufdata;
|
||||||
|
newparam->srvbuf = newparam->srvbufdata;
|
||||||
|
newparam->clibufsize = newparam->srvbufsize = SRVBUFSIZE(srv);
|
||||||
clearstat(newparam);
|
clearstat(newparam);
|
||||||
if(!s->isudp) newparam->clisock = client_sock;
|
if(!s->isudp) newparam->clisock = client_sock;
|
||||||
newparam->prev = newparam->next = NULL;
|
newparam->prev = newparam->next = NULL;
|
||||||
@ -1431,6 +1432,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
|||||||
param->paused = srv->paused;
|
param->paused = srv->paused;
|
||||||
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
||||||
param->pipecli[0] = param->pipecli[1] = param->pipesrv[0] = param->pipesrv[1] = -1;
|
param->pipecli[0] = param->pipecli[1] = param->pipesrv[0] = param->pipesrv[1] = -1;
|
||||||
|
param->climark = -1;
|
||||||
*SAFAMILY(¶m->req) = *SAFAMILY(¶m->sinsl) = *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->sincr) = *SAFAMILY(¶m->sincl) = AF_INET;
|
*SAFAMILY(¶m->req) = *SAFAMILY(¶m->sinsl) = *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->sincr) = *SAFAMILY(¶m->sincl) = AF_INET;
|
||||||
_3proxy_mutex_init(&srv->counter_mutex);
|
_3proxy_mutex_init(&srv->counter_mutex);
|
||||||
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
||||||
@ -1551,8 +1553,8 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if(param->clibuf) free(param->clibuf);
|
if(param->clibuf != param->clibufdata) free(param->clibuf);
|
||||||
if(param->srvbuf) free(param->srvbuf);
|
if(param->srvbuf != param->srvbufdata) free(param->srvbuf);
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
if(param->pipecli[0] >= 0) close(param->pipecli[0]);
|
if(param->pipecli[0] >= 0) close(param->pipecli[0]);
|
||||||
if(param->pipecli[1] >= 0) close(param->pipecli[1]);
|
if(param->pipecli[1] >= 0) close(param->pipecli[1]);
|
||||||
@ -1590,21 +1592,11 @@ void freeparam(struct clientparam * param) {
|
|||||||
param->srv->so._closesocket(param->sostate, param->clisock);
|
param->srv->so._closesocket(param->sostate, param->clisock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(param->datfilterssrv) free(param->datfilterssrv);
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(param->reqfilters) free(param->reqfilters);
|
while(param->nfilters > 0){
|
||||||
if(param->connectfilters) free(param->connectfilters);
|
param->nfilters--;
|
||||||
if(param->afterauthfilters) free(param->afterauthfilters);
|
if(param->filters[param->nfilters].filter->filter_clear)
|
||||||
if(param->hdrfilterscli) free(param->hdrfilterscli);
|
(*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data);
|
||||||
if(param->hdrfilterssrv) free(param->hdrfilterssrv);
|
|
||||||
if(param->predatfilters) free(param->predatfilters);
|
|
||||||
if(param->datfilterscli) free(param->datfilterscli);
|
|
||||||
if(param->filters){
|
|
||||||
if(param->nfilters)while(param->nfilters--){
|
|
||||||
if(param->filters[param->nfilters].filter->filter_clear)
|
|
||||||
(*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data);
|
|
||||||
}
|
|
||||||
free(param->filters);
|
|
||||||
}
|
}
|
||||||
if(param->connlim) stopconnlims(param);
|
if(param->connlim) stopconnlims(param);
|
||||||
#endif
|
#endif
|
||||||
@ -1629,11 +1621,6 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
}
|
}
|
||||||
if(param->hostname) free(param->hostname);
|
|
||||||
if(param->username) free(param->username);
|
|
||||||
if(param->password) free(param->password);
|
|
||||||
if(param->extusername) free(param->extusername);
|
|
||||||
if(param->extpassword) free(param->extpassword);
|
|
||||||
free(param);
|
free(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1651,6 +1638,18 @@ FILTER_ACTION handleconnectflt(struct clientparam *cparam){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* A buffer filter given a buffer too small for what it makes of it hands
|
||||||
|
back one of its own, allocated with malloc, and leaves the one it was given
|
||||||
|
alone: nothing refers to that one any more, so it is freed here, unless it
|
||||||
|
is one of the connection's own buffers. The caller owns whatever *buf_p
|
||||||
|
points to on return. */
|
||||||
|
static void filterswap(struct clientparam *param, unsigned char **cur, unsigned char *now){
|
||||||
|
if(now != *cur){
|
||||||
|
if(*cur != param->clibufdata && *cur != param->srvbufdata && *cur != param->tmpbuf) free(*cur);
|
||||||
|
*cur = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
static void * itcopy (void * from, size_t size){
|
static void * itcopy (void * from, size_t size){
|
||||||
void * ret;
|
void * ret;
|
||||||
@ -1817,18 +1816,25 @@ ERRORNEXT:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void copyfilter (struct filter *filter, struct srvparam *srv){
|
/* Returns 2 when out of memory, 3 when there are more filters than a
|
||||||
|
connection has room for: a service started without some of its filters
|
||||||
|
could pass what one of them was there to stop. */
|
||||||
|
int copyfilter (struct filter *filter, struct srvparam *srv){
|
||||||
int nfilters = 0;
|
int nfilters = 0;
|
||||||
|
|
||||||
if(!filter) return;
|
if(!filter) return 0;
|
||||||
for(srv->filter = filter; srv->filter; srv->filter = srv->filter->next) nfilters++;
|
for(srv->filter = filter; srv->filter; srv->filter = srv->filter->next) nfilters++;
|
||||||
srv->filter = malloc(sizeof(struct filter) * nfilters);
|
srv->filter = malloc(sizeof(struct filter) * nfilters);
|
||||||
if(!srv->filter) return;
|
if(!srv->filter) return 2;
|
||||||
|
|
||||||
for(; filter; filter = filter->next){
|
for(; filter; filter = filter->next){
|
||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
|
|
||||||
if(!filter->filter_open || !(data = (*filter->filter_open)(filter->data, srv))) continue;
|
if(!filter->filter_open || !(data = (*filter->filter_open)(filter->data, srv))) continue;
|
||||||
|
if(srv->nfilters >= MAX_FILTERS){
|
||||||
|
if(filter->filter_close) (*filter->filter_close)(data);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
srv->filter[srv->nfilters] = *filter;
|
srv->filter[srv->nfilters] = *filter;
|
||||||
srv->filter[srv->nfilters].data = data;
|
srv->filter[srv->nfilters].data = data;
|
||||||
@ -1843,6 +1849,7 @@ void copyfilter (struct filter *filter, struct srvparam *srv){
|
|||||||
if(filter->filter_data_srv)srv->ndatfilterssrv++;
|
if(filter->filter_data_srv)srv->ndatfilterssrv++;
|
||||||
if(filter->filter_data_cli)srv->ndatfilterscli++;
|
if(filter->filter_data_cli)srv->ndatfilterscli++;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param){
|
FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param){
|
||||||
@ -1852,20 +1859,6 @@ FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param){
|
|||||||
|
|
||||||
if(!srv->nfilters) return PASS;
|
if(!srv->nfilters) return PASS;
|
||||||
|
|
||||||
if(!(param->filters = malloc(sizeof(struct filterp) * srv->nfilters)) ||
|
|
||||||
(srv->nreqfilters && !(param->reqfilters = malloc(sizeof(struct filterp *) * srv->nreqfilters))) ||
|
|
||||||
(srv->nconnectfilters && !(param->connectfilters = malloc(sizeof(struct filterp *) * srv->nconnectfilters))) ||
|
|
||||||
(srv->nafterauthfilters && !(param->afterauthfilters = malloc(sizeof(struct filterp *) * srv->nafterauthfilters))) ||
|
|
||||||
(srv->nhdrfilterssrv && !(param->hdrfilterssrv = malloc(sizeof(struct filterp *) * srv->nhdrfilterssrv))) ||
|
|
||||||
(srv->nhdrfilterscli && !(param->hdrfilterscli = malloc(sizeof(struct filterp *) * srv->nhdrfilterscli))) ||
|
|
||||||
(srv->npredatfilters && !(param->predatfilters = malloc(sizeof(struct filterp *) * srv->npredatfilters))) ||
|
|
||||||
(srv->ndatfilterssrv && !(param->datfilterssrv = malloc(sizeof(struct filterp *) * srv->ndatfilterssrv))) ||
|
|
||||||
(srv->ndatfilterscli && !(param->datfilterscli = malloc(sizeof(struct filterp *) * srv->ndatfilterscli)))
|
|
||||||
){
|
|
||||||
param->res = 21;
|
|
||||||
return REJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i<srv->nfilters; i++){
|
for(i=0; i<srv->nfilters; i++){
|
||||||
if(!srv->filter[i].filter_client)continue;
|
if(!srv->filter[i].filter_client)continue;
|
||||||
action = (*srv->filter[i].filter_client)(srv->filter[i].data, param, ¶m->filters[param->nfilters].data);
|
action = (*srv->filter[i].filter_client)(srv->filter[i].data, param, ¶m->filters[param->nfilters].data);
|
||||||
@ -1937,9 +1930,11 @@ FILTER_ACTION handleafterauthflt(struct clientparam *cparam){
|
|||||||
FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned char *cur = *buf_p;
|
||||||
|
|
||||||
for(i=0; i<param->nreqfilters; i++){
|
for(i=0; i<param->nreqfilters; i++){
|
||||||
action = (*param->reqfilters[i]->filter->filter_request)(param->reqfilters[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
action = (*param->reqfilters[i]->filter->filter_request)(param->reqfilters[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
||||||
|
filterswap(param, &cur, *buf_p);
|
||||||
if(action!=CONTINUE) return action;
|
if(action!=CONTINUE) return action;
|
||||||
}
|
}
|
||||||
return PASS;
|
return PASS;
|
||||||
@ -1948,9 +1943,11 @@ FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p
|
|||||||
FILTER_ACTION handlehdrfilterssrv(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
FILTER_ACTION handlehdrfilterssrv(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned char *cur = *buf_p;
|
||||||
|
|
||||||
for(i=0; i<param->nhdrfilterssrv; i++){
|
for(i=0; i<param->nhdrfilterssrv; i++){
|
||||||
action = (*param->hdrfilterssrv[i]->filter->filter_header_srv)(param->hdrfilterssrv[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
action = (*param->hdrfilterssrv[i]->filter->filter_header_srv)(param->hdrfilterssrv[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
||||||
|
filterswap(param, &cur, *buf_p);
|
||||||
if(action!=CONTINUE) return action;
|
if(action!=CONTINUE) return action;
|
||||||
}
|
}
|
||||||
return PASS;
|
return PASS;
|
||||||
@ -1959,9 +1956,11 @@ FILTER_ACTION handlehdrfilterssrv(struct clientparam *param, unsigned char ** bu
|
|||||||
FILTER_ACTION handlehdrfilterscli(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
FILTER_ACTION handlehdrfilterscli(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned char *cur = *buf_p;
|
||||||
|
|
||||||
for(i = 0; i < param->nhdrfilterscli; i++){
|
for(i = 0; i < param->nhdrfilterscli; i++){
|
||||||
action = (*param->hdrfilterscli[i]->filter->filter_header_cli)(param->hdrfilterscli[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
action = (*param->hdrfilterscli[i]->filter->filter_header_cli)(param->hdrfilterscli[i]->data, param, buf_p, bufsize_p, offset, length_p);
|
||||||
|
filterswap(param, &cur, *buf_p);
|
||||||
if(action!=CONTINUE) return action;
|
if(action!=CONTINUE) return action;
|
||||||
}
|
}
|
||||||
return PASS;
|
return PASS;
|
||||||
@ -1988,9 +1987,11 @@ FILTER_ACTION handledatfltcli(struct clientparam *cparam, unsigned char ** buf_p
|
|||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned char *cur = *buf_p;
|
||||||
|
|
||||||
for(i=0; i<cparam->ndatfilterscli ;i++){
|
for(i=0; i<cparam->ndatfilterscli ;i++){
|
||||||
action = (*cparam->datfilterscli[i]->filter->filter_data_cli)(cparam->datfilterscli[i]->data, cparam, buf_p, bufsize_p, offset, length_p);
|
action = (*cparam->datfilterscli[i]->filter->filter_data_cli)(cparam->datfilterscli[i]->data, cparam, buf_p, bufsize_p, offset, length_p);
|
||||||
|
filterswap(cparam, &cur, *buf_p);
|
||||||
if(action!=CONTINUE) return action;
|
if(action!=CONTINUE) return action;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2000,9 +2001,11 @@ FILTER_ACTION handledatfltcli(struct clientparam *cparam, unsigned char ** buf_p
|
|||||||
FILTER_ACTION handledatfltsrv(struct clientparam *cparam, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
FILTER_ACTION handledatfltsrv(struct clientparam *cparam, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
||||||
FILTER_ACTION action;
|
FILTER_ACTION action;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned char *cur = *buf_p;
|
||||||
|
|
||||||
for(i=0; i<cparam->ndatfilterssrv; i++){
|
for(i=0; i<cparam->ndatfilterssrv; i++){
|
||||||
action = (*cparam->datfilterssrv[i]->filter->filter_data_srv)(cparam->datfilterssrv[i]->data, cparam, buf_p, bufsize_p, offset, length_p);
|
action = (*cparam->datfilterssrv[i]->filter->filter_data_srv)(cparam->datfilterssrv[i]->data, cparam, buf_p, bufsize_p, offset, length_p);
|
||||||
|
filterswap(cparam, &cur, *buf_p);
|
||||||
if(action!=CONTINUE) return action;
|
if(action!=CONTINUE) return action;
|
||||||
}
|
}
|
||||||
return PASS;
|
return PASS;
|
||||||
|
|||||||
@ -26,16 +26,11 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
|
|||||||
|
|
||||||
user = redir->extuser;
|
user = redir->extuser;
|
||||||
pass = redir->extpass;
|
pass = redir->extpass;
|
||||||
if (!param->srvbufsize){
|
|
||||||
param->srvbufsize = SRVBUFSIZE;
|
|
||||||
param->srvbuf = malloc(param->srvbufsize);
|
|
||||||
if(!param->srvbuf) return 21;
|
|
||||||
}
|
|
||||||
buf = param->srvbuf;
|
buf = param->srvbuf;
|
||||||
username = buf + 2048;
|
username = buf + 2048;
|
||||||
if(user) {
|
if(user) {
|
||||||
if (*user == '*') {
|
if (*user == '*') {
|
||||||
if(!param->username) return 4;
|
if(!*param->username) return 4;
|
||||||
user = param->username;
|
user = param->username;
|
||||||
pass = param->password;
|
pass = param->password;
|
||||||
}
|
}
|
||||||
@ -415,15 +410,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
|||||||
else if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
|
else if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
|
||||||
int i;
|
int i;
|
||||||
if(cur->extuser){
|
if(cur->extuser){
|
||||||
if(param->extusername)
|
if(*cur->extuser == '*' && !*param->username) return 4;
|
||||||
free(param->extusername);
|
if(PARAMSTR(param, extusername, (*cur->extuser == '*')? param->username : cur->extuser)) return 21;
|
||||||
param->extusername = (unsigned char *)strdup((char *)((*cur->extuser == '*' && param->username)? param->username : cur->extuser));
|
if(cur->extpass && PARAMSTR(param, extpassword, (*cur->extuser == '*' && *param->password)?param->password : cur->extpass)) return 21;
|
||||||
if(cur->extpass){
|
|
||||||
if(param->extpassword)
|
|
||||||
free(param->extpassword);
|
|
||||||
param->extpassword = (unsigned char *)strdup((char *)((*cur->extuser == '*' && param->password)?param->password : cur->extpass));
|
|
||||||
}
|
|
||||||
if(*cur->extuser == '*' && !param->username) return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; redirs[i].name; i++){
|
for(i=0; redirs[i].name; i++){
|
||||||
@ -490,15 +479,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
|||||||
param->redirtype = redir->type;
|
param->redirtype = redir->type;
|
||||||
if(redir->type == R_TCP || redir->type ==R_HTTP) {
|
if(redir->type == R_TCP || redir->type ==R_HTTP) {
|
||||||
if(cur->extuser){
|
if(cur->extuser){
|
||||||
if(*cur -> extuser == '*' && !param->username) return 4;
|
if(*cur -> extuser == '*' && !*param->username) return 4;
|
||||||
if(param->extusername)
|
if(PARAMSTR(param, extusername, (*cur->extuser == '*')? param->username : cur->extuser)) return 21;
|
||||||
free(param->extusername);
|
if(cur->extpass && PARAMSTR(param, extpassword, (*cur->extuser == '*' && *param->password)?param->password : cur->extpass)) return 21;
|
||||||
param->extusername = (unsigned char *)strdup((char *)((*cur->extuser == '*' && param->username)? param->username : cur->extuser));
|
|
||||||
if(cur->extpass){
|
|
||||||
if(param->extpassword)
|
|
||||||
free(param->extpassword);
|
|
||||||
param->extpassword = (unsigned char *)strdup((char *)((*cur->extuser == '*' && param->password)?param->password : cur->extpass));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(redir->secure) return ssl_parent(param);
|
if(redir->secure) return ssl_parent(param);
|
||||||
return 0;
|
return 0;
|
||||||
@ -507,7 +490,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!connected || !redir) return 0;
|
if(!connected || !redir) return 0;
|
||||||
res = clientnegotiate(redir, param, (struct sockaddr *)¶m->req, param->hostname);
|
res = clientnegotiate(redir, param, (struct sockaddr *)¶m->req, *param->hostname? param->hostname : NULL);
|
||||||
if(res) parentfail(param, redir);
|
if(res) parentfail(param, redir);
|
||||||
if(saved){
|
if(saved){
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
|
|||||||
@ -201,9 +201,9 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
|
|||||||
s2 = s1;
|
s2 = s1;
|
||||||
}
|
}
|
||||||
*s2 = 0;
|
*s2 = 0;
|
||||||
if(param->username)free(param->username);
|
/* a name longer than the field is no name to authenticate */
|
||||||
param->username = (unsigned char *)strdup ((char *)buf + k + 13);
|
if(PARAMSTR(param, username, buf + k + 13)) return 0;
|
||||||
|
|
||||||
return udpresolve(af,param->username, value, NULL, NULL, 2);
|
return udpresolve(af,param->username, value, NULL, NULL, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/smtpp.c
54
src/smtpp.c
@ -33,26 +33,26 @@ int readreply (struct clientparam* param) {
|
|||||||
unsigned char * buf;
|
unsigned char * buf;
|
||||||
int res, i, bufsize = 640;
|
int res, i, bufsize = 640;
|
||||||
|
|
||||||
if(!(buf = malloc(bufsize))) return 0;
|
buf = param->tmpbuf; /* a filter may replace it with one of its own */
|
||||||
do {
|
do {
|
||||||
i = sockgetlinebuf(param, SERVER, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
|
i = sockgetlinebuf(param, SERVER, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
|
||||||
if(i < 1) break;
|
if(i < 1) break;
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
res = handlehdrfilterssrv(param, &buf, &bufsize, 0, &i);
|
res = handlehdrfilterssrv(param, &buf, &bufsize, 0, &i);
|
||||||
if(res != PASS) {
|
if(res != PASS) {
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
|
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
|
||||||
} while (i > 3 && buf[3] == '-');
|
} while (i > 3 && buf[3] == '-');
|
||||||
if(i < 3) {
|
if(i < 3) {
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
res = atoi((char *)buf);
|
res = atoi((char *)buf);
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,14 +64,14 @@ int readcommand (struct clientparam* param) {
|
|||||||
#endif
|
#endif
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
if(!(buf = malloc(bufsize))) return 0;
|
buf = param->tmpbuf; /* a filter may replace it with one of its own */
|
||||||
i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
|
i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
|
||||||
if(i < 4) return 0;
|
if(i < 4) return 0;
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
if(!strncasecmp((char *)buf, "MAIL", 4) || !strncasecmp((char *)buf, "RCPT", 4) || !strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
|
if(!strncasecmp((char *)buf, "MAIL", 4) || !strncasecmp((char *)buf, "RCPT", 4) || !strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
|
||||||
res = handlehdrfilterscli(param, &buf, &bufsize, 0, &i);
|
res = handlehdrfilterscli(param, &buf, &bufsize, 0, &i);
|
||||||
if(res != PASS) {
|
if(res != PASS) {
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
if(res == HANDLED) return 2;
|
if(res == HANDLED) return 2;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ int readcommand (struct clientparam* param) {
|
|||||||
if(!strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
|
if(!strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
|
||||||
ret = 22;
|
ret = 22;
|
||||||
}
|
}
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,12 +92,12 @@ int readdata (struct clientparam* param) {
|
|||||||
int res;
|
int res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!(buf = malloc(bufsize))) return 0;
|
buf = param->tmpbuf; /* a filter may replace it with one of its own */
|
||||||
while ((i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L])) > 0 && !(i==3 && buf[0] == '.')){
|
while ((i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L])) > 0 && !(i==3 && buf[0] == '.')){
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
res = handledatfltcli(param, &buf, &bufsize, 0, &i);
|
res = handledatfltcli(param, &buf, &bufsize, 0, &i);
|
||||||
if(res != PASS) {
|
if(res != PASS) {
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
if(res == HANDLED) return 1;
|
if(res == HANDLED) return 1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -105,11 +105,11 @@ int readdata (struct clientparam* param) {
|
|||||||
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
||||||
}
|
}
|
||||||
if(i < 1) {
|
if(i < 1) {
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
||||||
free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
return (void *)tlsprchild;
|
return (void *)tlsprchild;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
|
else if(!*param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
|
||||||
else {
|
else {
|
||||||
login = -1;
|
login = -1;
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
@ -172,8 +172,7 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
i = de64(buf,username,255);
|
i = de64(buf,username,255);
|
||||||
if(i < 0) {RETURN(666);}
|
if(i < 0) {RETURN(666);}
|
||||||
username[i] = 0;
|
username[i] = 0;
|
||||||
if(param->extpassword) free(param->extpassword);
|
if(PARAMSTR(param, extpassword, username)) {RETURN(666);}
|
||||||
param->extpassword = (unsigned char *)strdup((char *)username);
|
|
||||||
}
|
}
|
||||||
else if(login == 2){
|
else if(login == 2){
|
||||||
if(i > 13) {
|
if(i > 13) {
|
||||||
@ -192,16 +191,23 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
if(parseconnusername((char *)username+1, param, 0, 587)) {RETURN(670);}
|
if(parseconnusername((char *)username+1, param, 0, 587)) {RETURN(670);}
|
||||||
res = (int)strlen((char *)username+1) + 2;
|
res = (int)strlen((char *)username+1) + 2;
|
||||||
if(res < i){
|
if(res < i){
|
||||||
if(param->extpassword) free(param->extpassword);
|
if(PARAMSTR(param, extpassword, username + res)) {RETURN(670);}
|
||||||
param->extpassword = (unsigned char *)strdup((char *)username + res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
{
|
{
|
||||||
|
/* the host is filtered as a request, in the scratch buffer, where a
|
||||||
|
filter may also hand back a buffer of its own */
|
||||||
int action, reqbufsize, reqsize;
|
int action, reqbufsize, reqsize;
|
||||||
reqbufsize = reqsize = (int)strlen((char *)param->hostname) + 1;
|
unsigned char *req = param->tmpbuf;
|
||||||
action = handlereqfilters(param, ¶m->hostname, &reqbufsize, 0, &reqsize);
|
|
||||||
|
reqsize = (int)strlen((char *)param->hostname) + 1;
|
||||||
|
reqbufsize = CLIENTTMPBUFSIZE;
|
||||||
|
memcpy(req, param->hostname, reqsize);
|
||||||
|
action = handlereqfilters(param, &req, &reqbufsize, 0, &reqsize);
|
||||||
|
if(action == PASS && PARAMSTR(param, hostname, req)) action = REJECT;
|
||||||
|
if(req != param->tmpbuf) free(req);
|
||||||
if(action == HANDLED){
|
if(action == HANDLED){
|
||||||
RETURN(0);
|
RETURN(0);
|
||||||
}
|
}
|
||||||
@ -232,8 +238,8 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
|
|
||||||
} while (i > 3 && buf[3] == '-');
|
} while (i > 3 && buf[3] == '-');
|
||||||
if(i<3) {RETURN(672);}
|
if(i<3) {RETURN(672);}
|
||||||
if(!command || (param->extusername && param->extpassword)){
|
if(!command || (*param->extusername && *param->extpassword)){
|
||||||
if(!param->extusername || !*param->extusername || !param->extpassword || !*param->extpassword || !login){
|
if(!*param->extusername || !*param->extpassword || !login){
|
||||||
socksend(param, param->clisock, (unsigned char *)"235 auth required\r\n", 19,conf.timeouts[STRING_S]);
|
socksend(param, param->clisock, (unsigned char *)"235 auth required\r\n", 19,conf.timeouts[STRING_S]);
|
||||||
}
|
}
|
||||||
if ((login & 1)) {
|
if ((login & 1)) {
|
||||||
@ -285,9 +291,9 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
res = 1;
|
res = 1;
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
if(!strncasecmp(command, "MAIL", 4) || !strncasecmp(command, "RCPT", 4) || !strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4)){
|
if(!strncasecmp(command, "MAIL", 4) || !strncasecmp(command, "RCPT", 4) || !strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4)){
|
||||||
res = (int)strlen(command);
|
int clen = (int)strlen(command), csize = clen + 1;
|
||||||
command[res] = 0;
|
|
||||||
res = handlehdrfilterscli(param, (unsigned char **)&command, &res, 0, &res);
|
res = handlehdrfilterscli(param, (unsigned char **)&command, &csize, 0, &clen);
|
||||||
if(res != PASS) {
|
if(res != PASS) {
|
||||||
if(res == HANDLED) res = 2;
|
if(res == HANDLED) res = 2;
|
||||||
else RETURN(677);
|
else RETURN(677);
|
||||||
@ -321,7 +327,7 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
|
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
if(param->hostname&¶m->extusername) {
|
if(*param->hostname&&*param->extusername) {
|
||||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==587?0:':',ntohs(*SAPORT(¶m->sinsr)));
|
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==587?0:':',ntohs(*SAPORT(¶m->sinsr)));
|
||||||
dolog(param, buf);
|
dolog(param, buf);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,112 +70,122 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
/* Starts an empty buffer over from its beginning, and goes back to the
|
||||||
int len;
|
connection's own buffer if a filter needed a bigger one. Does nothing
|
||||||
|
while anything is left unread. */
|
||||||
if(!param->clibuf){
|
void bufrelease(struct clientparam * param, DIRECTION which){
|
||||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return 0;
|
if(which){
|
||||||
param->clibufsize = SRVBUFSIZE;
|
if(param->srvinbuf != param->srvoffset) return;
|
||||||
param->clioffset = param->cliinbuf = 0;
|
param->srvinbuf = param->srvoffset = 0;
|
||||||
|
if(param->srvbuf == param->srvbufdata) return;
|
||||||
|
free(param->srvbuf);
|
||||||
|
param->srvbuf = param->srvbufdata;
|
||||||
|
param->srvbufsize = SRVBUFSIZE(param->srv);
|
||||||
}
|
}
|
||||||
if(param->cliinbuf && param->clioffset < param->cliinbuf){
|
else {
|
||||||
return (int)param->clibuf[param->clioffset++];
|
if(param->cliinbuf != param->clioffset) return;
|
||||||
|
param->cliinbuf = param->clioffset = 0;
|
||||||
|
if(param->clibuf == param->clibufdata) return;
|
||||||
|
free(param->clibuf);
|
||||||
|
param->clibuf = param->clibufdata;
|
||||||
|
param->clibufsize = SRVBUFSIZE(param->srv);
|
||||||
}
|
}
|
||||||
param->clioffset = param->cliinbuf = 0;
|
|
||||||
if ((len = sockrecvfrom(param, param->clisock, (struct sockaddr *)¶m->sincr, param->clibuf, param->clibufsize, timeosec*1000 + timeousec))<=0) return EOF;
|
|
||||||
param->cliinbuf = len;
|
|
||||||
param->clioffset = 1;
|
|
||||||
return (int)*param->clibuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put bytes back in front of whatever the client has not been read yet, so a
|
/* Makes room for size bytes from the start of what is unread, which is
|
||||||
service which has already taken a request off the socket can hand it to
|
moved there: a body to be filtered whole is read into one buffer, which
|
||||||
another one, which reads it the way it reads anything else. */
|
may have to be bigger than the connection's own. Returns 1 when that
|
||||||
int pushbackcli(struct clientparam * param, const unsigned char * data, int len){
|
much cannot be had. */
|
||||||
unsigned left = 0;
|
int bufroom(struct clientparam * param, DIRECTION which, unsigned long size){
|
||||||
unsigned need;
|
unsigned char **buf = which? ¶m->srvbuf : ¶m->clibuf;
|
||||||
|
unsigned char *own = which? param->srvbufdata : param->clibufdata;
|
||||||
|
unsigned *inbuf = which? ¶m->srvinbuf : ¶m->cliinbuf;
|
||||||
|
unsigned *offset = which? ¶m->srvoffset : ¶m->clioffset;
|
||||||
|
unsigned *bufsize = which? ¶m->srvbufsize : ¶m->clibufsize;
|
||||||
|
unsigned left = *inbuf - *offset;
|
||||||
|
unsigned char *nb;
|
||||||
|
|
||||||
if(len <= 0) return 0;
|
if(*offset){
|
||||||
if(param->clibuf) left = param->cliinbuf - param->clioffset;
|
memmove(*buf, *buf + *offset, left);
|
||||||
need = (unsigned)len + left;
|
*inbuf = left;
|
||||||
|
*offset = 0;
|
||||||
if(!param->clibuf){
|
|
||||||
if(!(param->clibuf = malloc(need > SRVBUFSIZE? need : SRVBUFSIZE))) return 1;
|
|
||||||
param->clibufsize = need > SRVBUFSIZE? need : SRVBUFSIZE;
|
|
||||||
}
|
}
|
||||||
else if(param->clibufsize < need){
|
if(size <= *bufsize) return 0;
|
||||||
unsigned char *nb = realloc(param->clibuf, need);
|
if((unsigned long)(unsigned)size != size || !(nb = malloc(size))) return 1;
|
||||||
|
memcpy(nb, *buf, left);
|
||||||
if(!nb) return 1;
|
if(*buf != own) free(*buf);
|
||||||
param->clibuf = nb;
|
*buf = nb;
|
||||||
param->clibufsize = need;
|
*bufsize = (unsigned)size;
|
||||||
}
|
|
||||||
if(left) memmove(param->clibuf + len, param->clibuf + param->clioffset, left);
|
|
||||||
memcpy(param->clibuf, data, (size_t)len);
|
|
||||||
param->clioffset = 0;
|
|
||||||
param->cliinbuf = need;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, int timeosec){
|
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
||||||
int len;
|
int len;
|
||||||
|
unsigned keep = 0;
|
||||||
|
|
||||||
if(!param->clibuf) return 0;
|
if(param->cliinbuf && param->clioffset < param->cliinbuf){
|
||||||
if(param->cliinbuf == param->clioffset){
|
return (int)param->clibuf[param->clioffset++];
|
||||||
param->cliinbuf = param->clioffset = 0;
|
|
||||||
}
|
}
|
||||||
else if(param->clioffset){
|
if(param->climark == -2) return EOF; /* nothing more until it is cleared */
|
||||||
memmove(param->clibuf, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset);
|
if(param->climark >= 0){
|
||||||
param->cliinbuf -= param->clioffset;
|
/* what was read since the mark stays, moved to the start */
|
||||||
param->clioffset = 0;
|
keep = param->cliinbuf - (unsigned)param->climark;
|
||||||
|
if(param->climark) memmove(param->clibuf, param->clibuf + param->climark, keep);
|
||||||
|
param->climark = 0;
|
||||||
|
param->clioffset = param->cliinbuf = keep;
|
||||||
|
if(keep >= param->clibufsize){
|
||||||
|
param->climark = -2;
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(size <= param->cliinbuf) return size;
|
else bufrelease(param, CLIENT);
|
||||||
size -= param->cliinbuf;
|
if ((len = sockrecvfrom(param, param->clisock, (struct sockaddr *)¶m->sincr, param->clibuf + keep, param->clibufsize - keep, timeosec*1000 + timeousec))<=0) return EOF;
|
||||||
if((len = sockrecvfrom(param, param->clisock, (struct sockaddr *)¶m->sincr, param->clibuf + param->cliinbuf, (param->clibufsize - param->cliinbuf) < size? param->clibufsize - param->cliinbuf:size, timeosec*1000)) > 0){
|
param->cliinbuf = keep + len;
|
||||||
param->cliinbuf += len;
|
param->clioffset = keep + 1;
|
||||||
}
|
return (int)param->clibuf[keep];
|
||||||
return param->cliinbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec){
|
/* Waits until size bytes are in the buffer, from its start, without taking
|
||||||
|
them: for a look at what comes before it is read the usual way, or for
|
||||||
|
something which has to be had whole. Stops short at the end of the
|
||||||
|
buffer, at the end of the stream, or when nothing comes in time; returns
|
||||||
|
how much is there, at most size. */
|
||||||
|
unsigned long sockfillbuf(struct clientparam * param, DIRECTION which, unsigned long size, int timeosec){
|
||||||
|
unsigned char *buf = which? param->srvbuf : param->clibuf;
|
||||||
|
unsigned *inbuf = which? ¶m->srvinbuf : ¶m->cliinbuf;
|
||||||
|
unsigned *offset = which? ¶m->srvoffset : ¶m->clioffset;
|
||||||
|
unsigned bufsize = which? param->srvbufsize : param->clibufsize;
|
||||||
|
unsigned want;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if(!param->srvbuf) return 0;
|
if(*offset){
|
||||||
if(param->srvinbuf == param->srvoffset){
|
memmove(buf, buf + *offset, *inbuf - *offset);
|
||||||
param->srvinbuf = param->srvoffset = 0;
|
*inbuf -= *offset;
|
||||||
|
*offset = 0;
|
||||||
}
|
}
|
||||||
else if(param->srvoffset){
|
while(*inbuf < size && *inbuf < bufsize){
|
||||||
memmove(param->srvbuf, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset);
|
want = (size - *inbuf < bufsize - *inbuf)? (unsigned)(size - *inbuf) : bufsize - *inbuf;
|
||||||
param->srvinbuf -= param->srvoffset;
|
len = which?
|
||||||
param->srvoffset = 0;
|
sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, buf + *inbuf, (int)want, timeosec*1000)
|
||||||
|
: sockrecvfrom(param, param->clisock, (struct sockaddr *)¶m->sincr, buf + *inbuf, (int)want, timeosec*1000);
|
||||||
|
if(len <= 0) break;
|
||||||
|
*inbuf += len;
|
||||||
|
if(which){
|
||||||
|
param->nreads++;
|
||||||
|
param->statssrv64 += len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(size <= param->srvinbuf) return size;
|
return *inbuf < size? *inbuf : size;
|
||||||
size -= param->srvinbuf;
|
|
||||||
if((len = sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, param->srvbuf + param->srvinbuf, (param->srvbufsize - param->srvinbuf) < size? param->srvbufsize - param->srvinbuf:size, timeosec*1000)) > 0){
|
|
||||||
param->srvinbuf += len;
|
|
||||||
param->nreads++;
|
|
||||||
param->statssrv64 += len;
|
|
||||||
}
|
|
||||||
return param->srvinbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
|
int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
|
||||||
int len;
|
int len;
|
||||||
int bufsize;
|
|
||||||
|
|
||||||
if(!param->srvbuf){
|
|
||||||
bufsize = SRVBUFSIZE;
|
|
||||||
if(param->ndatfilterssrv > 0 && bufsize < 32768) bufsize = 32768;
|
|
||||||
if(!(param->srvbuf = malloc(bufsize))) return 0;
|
|
||||||
param->srvbufsize = bufsize;
|
|
||||||
param->srvoffset = param->srvinbuf = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
if(param->srvinbuf && param->srvoffset < param->srvinbuf){
|
if(param->srvinbuf && param->srvoffset < param->srvinbuf){
|
||||||
return (int)param->srvbuf[param->srvoffset++];
|
return (int)param->srvbuf[param->srvoffset++];
|
||||||
}
|
}
|
||||||
param->srvoffset = param->srvinbuf = 0;
|
bufrelease(param, SERVER);
|
||||||
if ((len = sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
|
if ((len = sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
|
||||||
param->srvinbuf = len;
|
param->srvinbuf = len;
|
||||||
param->srvoffset = 1;
|
param->srvoffset = 1;
|
||||||
|
|||||||
@ -141,13 +141,6 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
if(autosplice && allowsrv && param->waitserver64 && fromserver > inserverbuf && fromserver - inserverbuf >= SPLICE_MIN) splicesrv = 1;
|
if(autosplice && allowsrv && param->waitserver64 && fromserver > inserverbuf && fromserver - inserverbuf >= SPLICE_MIN) splicesrv = 1;
|
||||||
if(autosplice && allowcli && param->waitclient64 && fromclient > inclientbuf && fromclient - inclientbuf >= SPLICE_MIN) splicecli = 1;
|
if(autosplice && allowcli && param->waitclient64 && fromclient > inclientbuf && fromclient - inclientbuf >= SPLICE_MIN) splicecli = 1;
|
||||||
#endif
|
#endif
|
||||||
/* a spliced direction needs no buffer, only what was read before */
|
|
||||||
if(!splicesrv && fromserver && !param->srvbuf && (!(param->srvbuf=malloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))){
|
|
||||||
RETURN (21);
|
|
||||||
}
|
|
||||||
if(!splicecli && fromclient && !param->clibuf && (!(param->clibuf=malloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))){
|
|
||||||
RETURN (21);
|
|
||||||
}
|
|
||||||
if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0;
|
if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0;
|
||||||
if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
||||||
if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0;
|
if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0;
|
||||||
@ -268,7 +261,7 @@ log("done send to server from buf");
|
|||||||
inclientbuf -= res;
|
inclientbuf -= res;
|
||||||
fromclient -= res;
|
fromclient -= res;
|
||||||
param->clioffset += res;
|
param->clioffset += res;
|
||||||
if(param->clioffset == param->cliinbuf)param->clioffset = param->cliinbuf = 0;
|
bufrelease(param, CLIENT);
|
||||||
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
||||||
if(param->bandlimfunc) {
|
if(param->bandlimfunc) {
|
||||||
int sl1;
|
int sl1;
|
||||||
@ -314,7 +307,7 @@ log("done send to client from buf");
|
|||||||
inserverbuf -= res;
|
inserverbuf -= res;
|
||||||
fromserver -= res;
|
fromserver -= res;
|
||||||
param->srvoffset += res;
|
param->srvoffset += res;
|
||||||
if(param->srvoffset == param->srvinbuf)param->srvoffset = param->srvinbuf =0;
|
bufrelease(param, SERVER);
|
||||||
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
||||||
needaction = 0;
|
needaction = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -324,12 +317,10 @@ log("done send to client from buf");
|
|||||||
/* a direction going back to copying does once its pipe is empty */
|
/* a direction going back to copying does once its pipe is empty */
|
||||||
if(wantbufcli && !inclientpipe){
|
if(wantbufcli && !inclientpipe){
|
||||||
splicecli = wantbufcli = streakcli = 0;
|
splicecli = wantbufcli = streakcli = 0;
|
||||||
if(!param->clibuf && (!(param->clibuf=malloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))) RETURN (21);
|
|
||||||
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
||||||
}
|
}
|
||||||
if(wantbufsrv && !inserverpipe){
|
if(wantbufsrv && !inserverpipe){
|
||||||
splicesrv = wantbufsrv = streaksrv = 0;
|
splicesrv = wantbufsrv = streaksrv = 0;
|
||||||
if(!param->srvbuf && (!(param->srvbuf=malloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))) RETURN (21);
|
|
||||||
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -409,7 +400,6 @@ log("read from client to pipe");
|
|||||||
if(pipecli[0] < 0 && pipe2(pipecli, O_NONBLOCK) < 0){
|
if(pipecli[0] < 0 && pipe2(pipecli, O_NONBLOCK) < 0){
|
||||||
/* no pipe to be had: copy instead */
|
/* no pipe to be had: copy instead */
|
||||||
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
||||||
if(!param->clibuf && (!(param->clibuf=malloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))) RETURN (21);
|
|
||||||
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -459,7 +449,6 @@ log("read from server to pipe\n");
|
|||||||
#endif
|
#endif
|
||||||
if(pipesrv[0] < 0 && pipe2(pipesrv, O_NONBLOCK) < 0){
|
if(pipesrv[0] < 0 && pipe2(pipesrv, O_NONBLOCK) < 0){
|
||||||
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
||||||
if(!param->srvbuf && (!(param->srvbuf=malloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))) RETURN (21);
|
|
||||||
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/socks.c
43
src/socks.c
@ -21,7 +21,7 @@ char tracebuf[256];
|
|||||||
|
|
||||||
static void printcommand(unsigned char * buf, int command, struct clientparam *param){
|
static void printcommand(unsigned char * buf, int command, struct clientparam *param){
|
||||||
sprintf((char *)buf, "%s ", commands[command]);
|
sprintf((char *)buf, "%s ", commands[command]);
|
||||||
if(param->hostname){
|
if(*param->hostname){
|
||||||
sprintf((char *)buf + strlen((char *)buf), "%.256s", param->hostname);
|
sprintf((char *)buf + strlen((char *)buf), "%.256s", param->hostname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -37,7 +37,11 @@ void * sockschild(struct clientparam* param) {
|
|||||||
unsigned size;
|
unsigned size;
|
||||||
SASIZETYPE sasize;
|
SASIZETYPE sasize;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
unsigned char * buf=NULL;
|
/* a filter may hand back a buffer of its own in place of this one */
|
||||||
|
unsigned char * buf = param->tmpbuf;
|
||||||
|
/* the line logged, made apart from buf: logging makes its own line in
|
||||||
|
the scratch buffer */
|
||||||
|
unsigned char logline[340];
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char command=0;
|
unsigned char command=0;
|
||||||
struct pollfd fds[3];
|
struct pollfd fds[3];
|
||||||
@ -48,7 +52,6 @@ void * sockschild(struct clientparam* param) {
|
|||||||
|
|
||||||
param->service = S_SOCKS;
|
param->service = S_SOCKS;
|
||||||
|
|
||||||
if(!(buf = malloc(BUFSIZE))) {RETURN(21);}
|
|
||||||
memset(buf, 0, BUFSIZE);
|
memset(buf, 0, BUFSIZE);
|
||||||
if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
|
if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
|
||||||
RETURN(401);
|
RETURN(401);
|
||||||
@ -73,16 +76,14 @@ void * sockschild(struct clientparam* param) {
|
|||||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
|
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
|
||||||
if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);}
|
if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);}
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
if(!param->username) {
|
if(!*param->username) {
|
||||||
param->username = (unsigned char *)strdup((char *)buf);
|
if(PARAMSTR(param, username, buf)){RETURN(21);}
|
||||||
if(!param->username){RETURN(21);}
|
|
||||||
}
|
}
|
||||||
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
|
if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
|
||||||
if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);}
|
if (i && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);}
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
if(!param->password) {
|
if(!*param->password) {
|
||||||
param->password = (unsigned char *)strdup((char *)buf);
|
if(PARAMSTR(param, password, buf)){RETURN(21);}
|
||||||
if(!param->password){RETURN(21);}
|
|
||||||
}
|
}
|
||||||
buf[0] = 1;
|
buf[0] = 1;
|
||||||
buf[1] = 0;
|
buf[1] = 0;
|
||||||
@ -137,9 +138,7 @@ void * sockschild(struct clientparam* param) {
|
|||||||
default:
|
default:
|
||||||
RETURN(997);
|
RETURN(997);
|
||||||
}
|
}
|
||||||
if(param->hostname)free(param->hostname);
|
if(PARAMSTR(param, hostname, buf)){RETURN(21);}
|
||||||
param->hostname = (unsigned char *)strdup((char *)buf);
|
|
||||||
if(!param->hostname){RETURN(21);}
|
|
||||||
if (ver == 5) {
|
if (ver == 5) {
|
||||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||||
buf[0] = (unsigned char) res;
|
buf[0] = (unsigned char) res;
|
||||||
@ -151,17 +150,14 @@ void * sockschild(struct clientparam* param) {
|
|||||||
else {
|
else {
|
||||||
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
||||||
buf[127] = 0;
|
buf[127] = 0;
|
||||||
if(param->srv->needuser && *buf && !param->username) {
|
if(param->srv->needuser && *buf && !*param->username) {
|
||||||
param->username = (unsigned char *)strdup((char *)buf);
|
if(PARAMSTR(param, username, buf)){RETURN(21);}
|
||||||
if(!param->username){RETURN(21);}
|
|
||||||
}
|
}
|
||||||
if(!memcmp(SAADDR(¶m->req), "\0\0\0", 3)){
|
if(!memcmp(SAADDR(¶m->req), "\0\0\0", 3)){
|
||||||
param->service = S_SOCKS45;
|
param->service = S_SOCKS45;
|
||||||
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
||||||
buf[127] = 0;
|
buf[127] = 0;
|
||||||
if(param->hostname)free(param->hostname);
|
if(PARAMSTR(param, hostname, buf)){RETURN(21);}
|
||||||
param->hostname = (unsigned char *)strdup((char *)buf);
|
|
||||||
if(!param->hostname){RETURN(21);}
|
|
||||||
if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||||
param->sinsr = param->req;
|
param->sinsr = param->req;
|
||||||
}
|
}
|
||||||
@ -346,7 +342,7 @@ fflush(stderr);
|
|||||||
switch(command) {
|
switch(command) {
|
||||||
case 1:
|
case 1:
|
||||||
if(param->redirectfunc){
|
if(param->redirectfunc){
|
||||||
if(buf)free(buf);
|
if(buf != param->tmpbuf) free(buf);
|
||||||
return (void *)param->redirectfunc;
|
return (void *)param->redirectfunc;
|
||||||
}
|
}
|
||||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||||
@ -421,12 +417,9 @@ fflush(stderr);
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(command > 3) command = 0;
|
if(command > 3) command = 0;
|
||||||
if(buf){
|
printcommand(logline, command, param);
|
||||||
printcommand(buf, command, param);
|
dolog(param, logline);
|
||||||
|
if(buf != param->tmpbuf) free(buf);
|
||||||
dolog(param, buf);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/ssl.c
10
src/ssl.c
@ -453,11 +453,13 @@ int docli(struct clientparam* param){
|
|||||||
|
|
||||||
SSL_CONN ServerConn;
|
SSL_CONN ServerConn;
|
||||||
SSL_CERT ServerCert=NULL;
|
SSL_CERT ServerCert=NULL;
|
||||||
unsigned char *hostname;
|
unsigned char hostname[HOSTNAMELEN];
|
||||||
hostname = param->hostname;
|
|
||||||
param->hostname = (unsigned char *)PCONF->client_sni;
|
/* the name given to the server is the configured one, if any */
|
||||||
|
memcpy(hostname, param->hostname, sizeof(hostname));
|
||||||
|
if(PARAMSTR(param, hostname, PCONF->client_sni)) *param->hostname = 0;
|
||||||
ServerConn = dosrvcon(param, &ServerCert);
|
ServerConn = dosrvcon(param, &ServerCert);
|
||||||
param->hostname = hostname;
|
memcpy(param->hostname, hostname, sizeof(hostname));
|
||||||
_ssl_cert_free(ServerCert);
|
_ssl_cert_free(ServerCert);
|
||||||
|
|
||||||
if(!ServerConn) return 1;
|
if(!ServerConn) return 1;
|
||||||
|
|||||||
@ -199,6 +199,12 @@ int
|
|||||||
|
|
||||||
#define MAX_HASH_SIZE (64)
|
#define MAX_HASH_SIZE (64)
|
||||||
#define UDPBUFSIZE 16384
|
#define UDPBUFSIZE 16384
|
||||||
|
/* A connection's buffer for each side: 16K, and the 5 byte header of a TLS
|
||||||
|
record that big, which tlspr reads whole. */
|
||||||
|
#define CLIENTBUFSIZE (16384 + 64)
|
||||||
|
#define CLIENTTMPBUFSIZE 8192
|
||||||
|
#define HOSTNAMELEN 256
|
||||||
|
#define USERNAMELEN 128
|
||||||
|
|
||||||
extern char* NULLADDR;
|
extern char* NULLADDR;
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -396,8 +402,6 @@ struct httpreq {
|
|||||||
int proxy; /* the client asked the way it asks a proxy */
|
int proxy; /* the client asked the way it asks a proxy */
|
||||||
int connect; /* and asked for a tunnel */
|
int connect; /* and asked for a tunnel */
|
||||||
int mayproxy; /* an access rule sent this to the local proxy */
|
int mayproxy; /* an access rule sent this to the local proxy */
|
||||||
unsigned char *raw; /* the request as it arrived, for handing on */
|
|
||||||
int rawlen, rawsize;
|
|
||||||
int drained; /* the body has been read and thrown away */
|
int drained; /* the body has been read and thrown away */
|
||||||
char *lasthost; /* where the last request on this connection went */
|
char *lasthost; /* where the last request on this connection went */
|
||||||
void *handoff; /* a child which takes the connection over */
|
void *handoff; /* a child which takes the connection over */
|
||||||
@ -527,7 +531,7 @@ struct filterp {
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_FILTERS 16
|
#define MAX_FILTERS 256
|
||||||
|
|
||||||
/* Socket options for one kind of socket, -oc and the like: which of
|
/* Socket options for one kind of socket, -oc and the like: which of
|
||||||
sockopts[] are given, by their index there, and the value of each. */
|
sockopts[] are given, by their index there, and the value of each. */
|
||||||
@ -688,11 +692,6 @@ struct clientparam {
|
|||||||
TRAFCOUNTFUNC trafcountfunc;
|
TRAFCOUNTFUNC trafcountfunc;
|
||||||
|
|
||||||
|
|
||||||
struct filterp *filters,
|
|
||||||
**reqfilters, **connectfilters, **afterauthfilters,
|
|
||||||
**hdrfilterscli, **hdrfilterssrv,
|
|
||||||
**predatfilters, **datfilterscli, **datfilterssrv;
|
|
||||||
|
|
||||||
PROXYSERVICE service;
|
PROXYSERVICE service;
|
||||||
|
|
||||||
PROXYSERVICE clientstarttls;
|
PROXYSERVICE clientstarttls;
|
||||||
@ -735,12 +734,7 @@ struct clientparam {
|
|||||||
preauth,
|
preauth,
|
||||||
dstindep;
|
dstindep;
|
||||||
|
|
||||||
unsigned char *hostname,
|
unsigned char *clibuf,
|
||||||
*username,
|
|
||||||
*password,
|
|
||||||
*extusername,
|
|
||||||
*extpassword,
|
|
||||||
*clibuf,
|
|
||||||
*srvbuf;
|
*srvbuf;
|
||||||
|
|
||||||
/* splice() pipes for the client's and the server's data, -1 until
|
/* splice() pipes for the client's and the server's data, -1 until
|
||||||
@ -791,6 +785,34 @@ struct clientparam {
|
|||||||
member is only reached once every weighted one is in here. */
|
member is only reached once every weighted one is in here. */
|
||||||
struct chain *failedparents[MAXFAILEDPARENTS];
|
struct chain *failedparents[MAXFAILEDPARENTS];
|
||||||
int nfailedparents;
|
int nfailedparents;
|
||||||
|
/* Where in clibuf a request being read began, -1 when nothing is to be
|
||||||
|
kept, -2 once a request was too big for the buffer. While it is set,
|
||||||
|
refilling the buffer keeps everything from there on instead of
|
||||||
|
starting over, so the request can be read again from the buffer. */
|
||||||
|
int climark;
|
||||||
|
/* Names and credentials, empty when there are none. A value too long
|
||||||
|
for its field is refused, never cut short: set them with PARAMSTR. */
|
||||||
|
unsigned char hostname[HOSTNAMELEN],
|
||||||
|
username[USERNAMELEN],
|
||||||
|
password[USERNAMELEN],
|
||||||
|
extusername[USERNAMELEN],
|
||||||
|
extpassword[USERNAMELEN];
|
||||||
|
/* The filters this connection runs, which a new connection makes for
|
||||||
|
itself: the service's are not copied to it. Ordered for each stage. */
|
||||||
|
struct filterp filters[MAX_FILTERS],
|
||||||
|
*reqfilters[MAX_FILTERS], *connectfilters[MAX_FILTERS],
|
||||||
|
*afterauthfilters[MAX_FILTERS],
|
||||||
|
*hdrfilterscli[MAX_FILTERS], *hdrfilterssrv[MAX_FILTERS],
|
||||||
|
*predatfilters[MAX_FILTERS], *datfilterscli[MAX_FILTERS],
|
||||||
|
*datfilterssrv[MAX_FILTERS];
|
||||||
|
/* The connection's scratch buffer, for a log line and the like: for
|
||||||
|
something done at once, never for what has to outlive a call into
|
||||||
|
anything that could log. */
|
||||||
|
unsigned char tmpbuf[CLIENTTMPBUFSIZE];
|
||||||
|
/* Each side's data buffer, which clibuf and srvbuf point to unless a
|
||||||
|
filter needed a bigger one. */
|
||||||
|
unsigned char clibufdata[CLIENTBUFSIZE],
|
||||||
|
srvbufdata[CLIENTBUFSIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filemon {
|
struct filemon {
|
||||||
|
|||||||
@ -16,12 +16,12 @@
|
|||||||
void * tcppmchild(struct clientparam* param) {
|
void * tcppmchild(struct clientparam* param) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if(!param->hostname){
|
if(!*param->hostname){
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
if(!strncmp((char *)param->srv->target, "unix:", 5)){
|
if(!strncmp((char *)param->srv->target, "unix:", 5)){
|
||||||
make_un(param->srv->target + 5, (struct sockaddr_un *)¶m->sinsr);
|
make_un(param->srv->target + 5, (struct sockaddr_un *)¶m->sinsr);
|
||||||
make_un(param->srv->target + 5, (struct sockaddr_un *)¶m->req);
|
make_un(param->srv->target + 5, (struct sockaddr_un *)¶m->req);
|
||||||
param->hostname = (unsigned char *)strdup((char *)param->srv->target);
|
if(PARAMSTR(param, hostname, param->srv->target)) RETURN(100);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if(
|
if(
|
||||||
@ -46,7 +46,7 @@ void * tcppmchild(struct clientparam* param) {
|
|||||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
dolog(param, param->hostname);
|
dolog(param, *param->hostname? param->hostname : NULL);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
94
src/tlspr.c
94
src/tlspr.c
@ -266,64 +266,30 @@ int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * sn
|
|||||||
return snifound;
|
return snifound;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlstobufcli(struct clientparam *param){
|
/* Has one whole TLS record from one side at the start of its buffer, once
|
||||||
unsigned long len, newlen;
|
whatever is still buffered from the other side is passed on. Returns its
|
||||||
if(!param->clibuf){
|
length, or less than 0; the server's codes are one further on than the
|
||||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return -1;
|
client's, as the log has always had them. */
|
||||||
param->clibufsize = SRVBUFSIZE;
|
static int tlstobuf(struct clientparam *param, DIRECTION which){
|
||||||
param->clioffset = param->cliinbuf = 0;
|
unsigned *oinbuf = which? ¶m->cliinbuf : ¶m->srvinbuf;
|
||||||
}
|
unsigned *ooffset = which? ¶m->clioffset : ¶m->srvoffset;
|
||||||
if(param->srvinbuf != param->srvoffset){
|
unsigned char *obuf = which? param->clibuf : param->srvbuf;
|
||||||
len = socksend(param, param->clisock, param->srvbuf+param->srvoffset,param->srvinbuf-param->srvoffset, conf.timeouts[STRING_S]);
|
unsigned char *buf;
|
||||||
if(len != param->srvinbuf-param->srvoffset){
|
int e = which? 1 : 0;
|
||||||
return -2;
|
unsigned long len;
|
||||||
}
|
|
||||||
param->srvinbuf = param->srvoffset = 0;
|
|
||||||
}
|
|
||||||
len = sockfillbuffcli(param, 5, conf.timeouts[STRING_S]);
|
|
||||||
if(len < 5) return -2;
|
|
||||||
if(param->clibuf[1] != 3) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
len = 5 + size16(param->clibuf+3);
|
|
||||||
if(len > param->clibufsize) return -4;
|
|
||||||
for(newlen=param->cliinbuf; newlen < len; newlen=param->cliinbuf){
|
|
||||||
sockfillbuffcli(param, len, conf.timeouts[STRING_S]);
|
|
||||||
if(param->cliinbuf <= newlen) return -5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (int)len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tlstobufsrv(struct clientparam *param){
|
if(*oinbuf != *ooffset){
|
||||||
unsigned long len, newlen;
|
len = *oinbuf - *ooffset;
|
||||||
|
if((unsigned long)socksend(param, which? param->remsock : param->clisock, obuf + *ooffset, (int)len, conf.timeouts[STRING_S]) != len)
|
||||||
if(param->cliinbuf != param->clioffset){
|
return which? -1 : -2;
|
||||||
len = socksend(param, param->remsock, param->clibuf+param->clioffset,param->cliinbuf-param->clioffset, conf.timeouts[STRING_S]);
|
*oinbuf = *ooffset = 0;
|
||||||
if(len != param->cliinbuf-param->clioffset){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
param->cliinbuf = param->clioffset = 0;
|
|
||||||
}
|
|
||||||
if(!param->srvbuf){
|
|
||||||
if(!(param->srvbuf = malloc(SRVBUFSIZE))) return -1;
|
|
||||||
param->srvbufsize = SRVBUFSIZE;
|
|
||||||
param->srvoffset = param->srvinbuf = 0;
|
|
||||||
}
|
|
||||||
len = sockfillbuffsrv(param, 5, conf.timeouts[STRING_S]);
|
|
||||||
if(len < 5) return -3;
|
|
||||||
if(param->srvbuf[1] != 3) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
len = 5 + size16(param->srvbuf+3);
|
|
||||||
if(len > param->srvbufsize) return -5;
|
|
||||||
for(newlen=param->srvinbuf; newlen < len; newlen=param->srvinbuf){
|
|
||||||
sockfillbuffsrv(param, len, conf.timeouts[STRING_S]);
|
|
||||||
if(param->srvinbuf <= newlen) return -6;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(sockfillbuf(param, which, 5, conf.timeouts[STRING_S]) < 5) return -2 - e;
|
||||||
|
buf = which? param->srvbuf : param->clibuf;
|
||||||
|
if(buf[1] != 3) return -3 - e;
|
||||||
|
len = 5 + size16(buf + 3);
|
||||||
|
if(len > (which? param->srvbufsize : param->clibufsize)) return -4 - e;
|
||||||
|
if(sockfillbuf(param, which, len, conf.timeouts[STRING_S]) < len) return -5 - e;
|
||||||
return (int)len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +309,7 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
if(res < 0) RETURN(0);
|
if(res < 0) RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = tlstobufcli(param);
|
res = tlstobuf(param, CLIENT);
|
||||||
if(res <= 0 || param->clibuf[0] != 22){
|
if(res <= 0 || param->clibuf[0] != 22){
|
||||||
if(param->srv->requirecert)RETURN(300-res);
|
if(param->srv->requirecert)RETURN(300-res);
|
||||||
}
|
}
|
||||||
@ -351,12 +317,10 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
lv = param->clibuf[2];
|
lv = param->clibuf[2];
|
||||||
res = parsehello(1, param->clibuf, (unsigned)res, sni, &snipos, &lv, proto);
|
res = parsehello(1, param->clibuf, (unsigned)res, sni, &snipos, &lv, proto);
|
||||||
if(res > 0){
|
if(res > 0){
|
||||||
if(param->hostname){
|
if(*param->hostname){
|
||||||
free(param->hostname);
|
if(PARAMSTR(param, hostname, sni)) RETURN (100);
|
||||||
param->hostname = NULL;
|
|
||||||
}
|
}
|
||||||
else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):starttlsport(stlsproto))) RETURN (100);
|
else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):starttlsport(stlsproto))) RETURN (100);
|
||||||
if (!param->hostname)param->hostname = (unsigned char *)strdup(sni);
|
|
||||||
if(param->srv->s_option && snipos && res > 1){
|
if(param->srv->s_option && snipos && res > 1){
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -395,7 +359,7 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(param->srv->requirecert > 1){
|
if(param->srv->requirecert > 1){
|
||||||
res = tlstobufsrv(param);
|
res = tlstobuf(param, SERVER);
|
||||||
if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res);
|
if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res);
|
||||||
lv = param->srvbuf[2];
|
lv = param->srvbuf[2];
|
||||||
res = parsehello(2, param->srvbuf, (unsigned)res, sni, &snipos, &lv, proto);
|
res = parsehello(2, param->srvbuf, (unsigned)res, sni, &snipos, &lv, proto);
|
||||||
@ -408,7 +372,7 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
len = param->srvinbuf;
|
len = param->srvinbuf;
|
||||||
if(socksend(param, param->clisock, param->srvbuf,len, conf.timeouts[STRING_S]) != len) RETURN(371);
|
if(socksend(param, param->clisock, param->srvbuf,len, conf.timeouts[STRING_S]) != len) RETURN(371);
|
||||||
param->srvinbuf = 0;
|
param->srvinbuf = 0;
|
||||||
res = tlstobufsrv(param);
|
res = tlstobuf(param, SERVER);
|
||||||
if(res <= 0) RETURN(380-res);
|
if(res <= 0) RETURN(380-res);
|
||||||
if(param->srvbuf[0]!= 22) break;
|
if(param->srvbuf[0]!= 22) break;
|
||||||
switch(param->srvbuf[5]){
|
switch(param->srvbuf[5]){
|
||||||
@ -430,7 +394,7 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
if(param->srv->requirecert > 3){
|
if(param->srv->requirecert > 3){
|
||||||
if(!reqcert) RETURN(374);
|
if(!reqcert) RETURN(374);
|
||||||
for(done=0;!done;) {
|
for(done=0;!done;) {
|
||||||
res = tlstobufcli(param);
|
res = tlstobuf(param, CLIENT);
|
||||||
if(res <= 0) RETURN(390-res);
|
if(res <= 0) RETURN(390-res);
|
||||||
len = res;
|
len = res;
|
||||||
if(param->clibuf[0]!= 22) break;
|
if(param->clibuf[0]!= 22) break;
|
||||||
@ -456,7 +420,7 @@ void * tlsprchild(struct clientparam* param) {
|
|||||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
sprintf(req, "%sv%d.%d %s %s", lv<0?"NONE":lv?"TLS":"SSL", lv<0?0:lv?1:3, lv<0?0:lv?lv-1:0, param->hostname?(char *)param->hostname:"-", proto);
|
sprintf(req, "%sv%d.%d %s %s", lv<0?"NONE":lv?"TLS":"SSL", lv<0?0:lv?1:3, lv<0?0:lv?lv-1:0, *param->hostname?(char *)param->hostname:"-", proto);
|
||||||
dolog(param, (unsigned char *)req);
|
dolog(param, (unsigned char *)req);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,7 +142,6 @@ static void* transparent_filter_open(void * idata, struct srvparam * param){
|
|||||||
|
|
||||||
static FILTER_ACTION transparent_filter_client(void *fo, struct clientparam * param, void** fc){
|
static FILTER_ACTION transparent_filter_client(void *fo, struct clientparam * param, void** fc){
|
||||||
|
|
||||||
char addrbuf[64];
|
|
||||||
int res = 1;
|
int res = 1;
|
||||||
|
|
||||||
#ifdef WITH_NETFILTER
|
#ifdef WITH_NETFILTER
|
||||||
@ -164,9 +163,8 @@ static FILTER_ACTION transparent_filter_client(void *fo, struct clientparam * pa
|
|||||||
service decides as it would without the command. */
|
service decides as it would without the command. */
|
||||||
if(res) return PASS;
|
if(res) return PASS;
|
||||||
|
|
||||||
pl->myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)addrbuf, sizeof(addrbuf));
|
/* an address always fits the field */
|
||||||
if(param->hostname) pl->freefunc(param->hostname);
|
pl->myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)param->hostname, sizeof(param->hostname));
|
||||||
param->hostname = (unsigned char *)pl->strdupfunc(addrbuf);
|
|
||||||
param->sinsr = param->req;
|
param->sinsr = param->req;
|
||||||
return PASS;
|
return PASS;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,10 +50,6 @@ void * udppmchild(struct clientparam* param) {
|
|||||||
if(authres) { RETURN(authres); }
|
if(authres) { RETURN(authres); }
|
||||||
if((authres = udpbind(param))) { RETURN(authres); }
|
if((authres = udpbind(param))) { RETURN(authres); }
|
||||||
if(!param->srv->s_option)hashadd(&udp_table, param, ¶m, MAX_COUNTER_TIME);
|
if(!param->srv->s_option)hashadd(&udp_table, param, ¶m, MAX_COUNTER_TIME);
|
||||||
if(!param->srvbuf){
|
|
||||||
if(!(param->srvbuf = malloc(UDPBUFSIZE)))RETURN(11);
|
|
||||||
param->srvbufsize = UDPBUFSIZE;
|
|
||||||
}
|
|
||||||
if(!param->bandlimfunc || !(*param->bandlimfunc)(param, 0, param->srv->udplen)){
|
if(!param->bandlimfunc || !(*param->bandlimfunc)(param, 0, param->srv->udplen)){
|
||||||
if(param->udp_nhops){
|
if(param->udp_nhops){
|
||||||
for(i=1; i < param->udp_nhops; i++){
|
for(i=1; i < param->udp_nhops; i++){
|
||||||
|
|||||||
@ -93,7 +93,7 @@ static void udplog(struct clientparam *param)
|
|||||||
|
|
||||||
if(!param->srv->logfunc) return;
|
if(!param->srv->logfunc) return;
|
||||||
len = sprintf((char *)buf, "UDPMAP ");
|
len = sprintf((char *)buf, "UDPMAP ");
|
||||||
if(param->hostname) len += sprintf((char *)buf + len, "%.256s", param->hostname);
|
if(*param->hostname) len += sprintf((char *)buf + len, "%.256s", param->hostname);
|
||||||
else len += myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + len, 64);
|
else len += myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + len, 64);
|
||||||
sprintf((char *)buf + len, ":%hu", ntohs(*SAPORT(¶m->req)));
|
sprintf((char *)buf + len, ":%hu", ntohs(*SAPORT(¶m->req)));
|
||||||
param->srv->logfunc(param, buf);
|
param->srv->logfunc(param, buf);
|
||||||
@ -208,12 +208,6 @@ int udpsockmap(struct clientparam *param, int timeo)
|
|||||||
char lastname[256] = "";
|
char lastname[256] = "";
|
||||||
struct ace *lastace = NULL;
|
struct ace *lastace = NULL;
|
||||||
|
|
||||||
if (param->srvbufsize < UDPBUFSIZE) {
|
|
||||||
unsigned char *newbuf = realloc(param->srvbuf, UDPBUFSIZE);
|
|
||||||
if (!newbuf) return 21;
|
|
||||||
param->srvbuf = newbuf;
|
|
||||||
param->srvbufsize = UDPBUFSIZE;
|
|
||||||
}
|
|
||||||
cliaddr = param->sincr;
|
cliaddr = param->sincr;
|
||||||
if(param->ctrlsock != INVALID_SOCKET){
|
if(param->ctrlsock != INVALID_SOCKET){
|
||||||
sasize = sizeof(cliaddr);
|
sasize = sizeof(cliaddr);
|
||||||
@ -313,13 +307,11 @@ int udpsockmap(struct clientparam *param, int timeo)
|
|||||||
PROXYSOCKADDRTYPE newdst = dst;
|
PROXYSOCKADDRTYPE newdst = dst;
|
||||||
|
|
||||||
param->req = lastdst;
|
param->req = lastdst;
|
||||||
if (param->hostname) free(param->hostname);
|
if (PARAMSTR(param, hostname, lastname)) *param->hostname = 0;
|
||||||
param->hostname = *lastname? (unsigned char *)strdup(lastname) : NULL;
|
|
||||||
udplog(param);
|
udplog(param);
|
||||||
dst = newdst;
|
dst = newdst;
|
||||||
}
|
}
|
||||||
if (param->hostname) free(param->hostname);
|
if (PARAMSTR(param, hostname, dstname)) *param->hostname = 0;
|
||||||
param->hostname = dstname? (unsigned char *)strdup(dstname) : NULL;
|
|
||||||
param->req = dst;
|
param->req = dst;
|
||||||
if (!nhops) param->sinsr = dst;
|
if (!nhops) param->sinsr = dst;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user