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_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>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>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>
|
||||
|
||||
@ -1436,7 +1436,10 @@ as
|
||||
.br
|
||||
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
|
||||
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
|
||||
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 preauth = (param->preauth == 1 && acentry->action <= REDIRECT);
|
||||
|
||||
username = param->username?param->username:(unsigned char *)"-";
|
||||
username = *param->username?param->username:(unsigned char *)"-";
|
||||
if(acentry->src) {
|
||||
for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
|
||||
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)) {
|
||||
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)
|
||||
if(IPInentry((struct sockaddr *)¶m->req, ipentry)) {
|
||||
break;
|
||||
}
|
||||
if(!ipentry) {
|
||||
if(acentry->dstnames && param->hostname){
|
||||
if(acentry->dstnames && *param->hostname){
|
||||
for(i=0; param->hostname[i]; i++){
|
||||
param->hostname[i] = tolower(param->hostname[i]);
|
||||
}
|
||||
|
||||
33
src/auth.c
33
src/auth.c
@ -83,8 +83,8 @@ int cacheauth(struct clientparam * param){
|
||||
|
||||
|
||||
if(
|
||||
((type & 2) && !param->username) ||
|
||||
((type & 4) && !param->password) ||
|
||||
((type & 2) && !*param->username) ||
|
||||
((type & 4) && !*param->password) ||
|
||||
(
|
||||
(type & 1) && *SAFAMILY(¶m->sincr) != AF_INET
|
||||
#ifndef NOIPV6
|
||||
@ -100,10 +100,7 @@ int cacheauth(struct clientparam * param){
|
||||
return 10;
|
||||
}
|
||||
|
||||
if(!(type&2) && *ac.username){
|
||||
if(param->username) free(param->username);
|
||||
param->username = (unsigned char *)strdup((char *)ac.username);
|
||||
}
|
||||
if(!(type&2) && *ac.username && PARAMSTR(param, username, ac.username)) return 4;
|
||||
if((type & 32)){
|
||||
memset(¶m->sinsl, 0, sizeof(param->sinsl));
|
||||
*(SAFAMILY(¶m->sinsl)) = ac.sinsl_family;
|
||||
@ -125,13 +122,11 @@ int doauth(struct clientparam * param){
|
||||
if(authfuncs->authorize &&
|
||||
(res = (*authfuncs->authorize)(param)))
|
||||
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=""};
|
||||
|
||||
if(param->username) {
|
||||
strncpy((char *)ac.username, (char *)param->username, 64);
|
||||
ac.username[63] = 0;
|
||||
}
|
||||
if(*SAFAMILY(¶m->sincr) == AF_INET
|
||||
#ifndef NOIPV6
|
||||
|| *SAFAMILY(¶m->sincr) == AF_INET6
|
||||
@ -158,7 +153,7 @@ int doauth(struct clientparam * param){
|
||||
}
|
||||
if(!res){
|
||||
ret = (param->preauth == 2)? 0 : alwaysauth(param);
|
||||
if (param->afterauthfilters){
|
||||
if (param->nafterauthfilters){
|
||||
FILTER_ACTION action;
|
||||
|
||||
action = handleafterauthflt(param);
|
||||
@ -173,16 +168,18 @@ int doauth(struct clientparam * param){
|
||||
|
||||
int ipauth(struct clientparam * param){
|
||||
int res;
|
||||
unsigned char *username;
|
||||
username = param->username;
|
||||
param->username = NULL;
|
||||
unsigned char c;
|
||||
|
||||
/* the rules are matched as if no name had been given */
|
||||
c = *param->username;
|
||||
*param->username = 0;
|
||||
res = checkACL(param);
|
||||
param->username = username;
|
||||
*param->username = c;
|
||||
return res;
|
||||
}
|
||||
|
||||
int userauth(struct clientparam * param){
|
||||
return (param->username)? 0:4;
|
||||
return (*param->username)? 0:4;
|
||||
}
|
||||
|
||||
int dnsauth(struct clientparam * param){
|
||||
@ -221,7 +218,7 @@ int dnsauth(struct clientparam * param){
|
||||
return 3;
|
||||
}
|
||||
|
||||
return param->username? 0:3;
|
||||
return *param->username? 0:3;
|
||||
}
|
||||
|
||||
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];
|
||||
char pass[256] = {0};
|
||||
|
||||
if (!param->username) return 4;
|
||||
if (!param->pwtype && param->password) {
|
||||
if (!*param->username) return 4;
|
||||
if (!param->pwtype && *param->password) {
|
||||
if (pwl_table.ihashtable && hashresolv(&pwl_table, param->username, pass, NULL)) {
|
||||
switch(pass[0]){
|
||||
case CL: {
|
||||
|
||||
@ -401,7 +401,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
total_length += (2+len);
|
||||
|
||||
/* Called-Station-ID */
|
||||
if(param->hostname){
|
||||
if(*param->hostname){
|
||||
*ptr++ = PW_CALLED_STATION_ID;
|
||||
len = strlen((char *)param->hostname);
|
||||
if(len > 253) len = 253;
|
||||
@ -443,7 +443,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
|
||||
|
||||
/* Username */
|
||||
if(param->username){
|
||||
if(*param->username){
|
||||
len = strlen((char *)param->username);
|
||||
if(len>128)len=128;
|
||||
*ptr++ = PW_USER_NAME;
|
||||
@ -502,7 +502,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
total_length+=6;
|
||||
}
|
||||
|
||||
if(auth && param->password){
|
||||
if(auth && *param->password){
|
||||
len = strlen((char *)param->password);
|
||||
if(len > 128) len = 128;
|
||||
*ptr++ = PW_PASSWORD;
|
||||
|
||||
@ -12,12 +12,7 @@
|
||||
void * autochild(struct clientparam* param) {
|
||||
int len;
|
||||
|
||||
if(!param->clibuf){
|
||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return 0;
|
||||
param->clibufsize = SRVBUFSIZE;
|
||||
param->clioffset = param->cliinbuf = 0;
|
||||
}
|
||||
len = sockfillbuffcli(param, 1, CONNECTION_S);
|
||||
len = sockfillbuf(param, CLIENT, 1, CONNECTION_S);
|
||||
if (len != 1){
|
||||
param->res = 801;
|
||||
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 = ':';
|
||||
return 1;
|
||||
}
|
||||
if(hostname != (char *)param->hostname){
|
||||
if(param->hostname) free(param->hostname);
|
||||
param->hostname = (unsigned char *)strdup(hostname + (se!=0));
|
||||
if(PARAMSTR(param, hostname, hostname + (se!=0))){
|
||||
if(se) *se = ']';
|
||||
if(sp) *sp = ':';
|
||||
return 1;
|
||||
}
|
||||
if(sp){
|
||||
port = atoi(sp+1);
|
||||
@ -576,6 +577,22 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
|
||||
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){
|
||||
char *sb = NULL, *se = NULL, *sp = NULL;
|
||||
|
||||
@ -584,13 +601,12 @@ int parseusername(char *username, struct clientparam *param, int extpasswd){
|
||||
*sb = 0;
|
||||
*se = 0;
|
||||
if(sp) *sp = 0;
|
||||
if(*(sb+1)) {
|
||||
if(param->password) free(param->password);
|
||||
param->password = (unsigned char *)strdup(sb+1);
|
||||
}
|
||||
if(*username) {
|
||||
if(param->username) free(param->username);
|
||||
param->username = (unsigned char *)strdup(username);
|
||||
if((*(sb+1) && PARAMSTR(param, password, sb+1)) ||
|
||||
(*username && PARAMSTR(param, username, username))){
|
||||
*sb = ':';
|
||||
*se = ':';
|
||||
if(sp) *sp = ':';
|
||||
return 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 = 0;
|
||||
if(param->extpassword) free(param->extpassword);
|
||||
param->extpassword = (unsigned char *) strdup(sp+1);
|
||||
if(PARAMSTR(param, extpassword, sp+1)) extpasswd = -1;
|
||||
}
|
||||
}
|
||||
if(param->extusername) free(param->extusername);
|
||||
param->extusername = (unsigned char *)strdup(username);
|
||||
if(extpasswd < 0 || PARAMSTR(param, extusername, username)) extpasswd = -1;
|
||||
if(sb) *sb = ':';
|
||||
if(se) *se = ':';
|
||||
if(sp) *sp = ':';
|
||||
return 0;
|
||||
return extpasswd < 0;
|
||||
}
|
||||
|
||||
int parseconnusername(char *username, struct clientparam *param, int extpasswd, uint16_t port){
|
||||
char *sb, *se;
|
||||
if(!username || !*username) return 1;
|
||||
if ((sb=strchr(username, conf.delimchar)) == NULL){
|
||||
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 && param->remsock == INVALID_SOCKET) return 2;
|
||||
if(*param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(¶m->req)? ntohs(*SAPORT(¶m->req)) : port);
|
||||
return parseusername(username, param, extpasswd);
|
||||
}
|
||||
while ((se=strchr(sb+1, conf.delimchar)))sb=se;
|
||||
|
||||
@ -162,7 +162,7 @@ int start_proxy_thread(struct child * chp){
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
_3proxy_mutex_lock(&runningservices_mutex);
|
||||
|
||||
@ -41,7 +41,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
|
||||
*innbuf = i;
|
||||
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)){
|
||||
return 703;
|
||||
}
|
||||
@ -53,10 +53,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
|
||||
res = atoi(buf)/100;
|
||||
if(res == 3){
|
||||
sprintf(buf, "PASS %.128s\r\n",
|
||||
param->extusername?
|
||||
(param->extpassword?
|
||||
param->extpassword:(unsigned char *)"")
|
||||
:(unsigned char *)"3proxy@");
|
||||
*param->extusername? param->extpassword : (unsigned char *)"3proxy@");
|
||||
res = (int)strlen(buf);
|
||||
if((int)socksend(param, param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
|
||||
return 705;
|
||||
|
||||
@ -28,7 +28,7 @@ void * ftpprchild(struct clientparam* param) {
|
||||
#endif
|
||||
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->operation = CONNECT;
|
||||
#ifndef _WIN32
|
||||
@ -73,11 +73,11 @@ void * ftpprchild(struct clientparam* param) {
|
||||
/* 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
|
||||
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]);
|
||||
RETURN(805);
|
||||
}
|
||||
param->extpassword = (unsigned char *)strdup((char *)buf+5);
|
||||
if(PARAMSTR(param, extpassword, buf+5)){RETURN(806);}
|
||||
inbuf = BUFSIZE;
|
||||
res = ftplogin(param, (char *)buf, &inbuf);
|
||||
param->res = res;
|
||||
@ -341,7 +341,7 @@ CLEANRET:
|
||||
dolog(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
|
||||
}
|
||||
if(req) free(req);
|
||||
if(buf) free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
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;
|
||||
|
||||
|
||||
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 & 2) && *param->username) ulen = strlen((const char *)param->username) + 1;
|
||||
if((type & 4) && *param->password) plen = strlen((const char *)param->password) + 1;
|
||||
if((type & 1) && !(type & 8)) a1len = SAADDRLEN(¶m->sincr);
|
||||
if((type & 16)) acllen = sizeof(param->srv->acl);
|
||||
if((type & 64)) a2len = SAADDRLEN(¶m->req);
|
||||
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 & 1024)) a3len = SAADDRLEN(¶m->srv->intsa);
|
||||
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);
|
||||
if(ulen + plen + a1len + acllen + a2len + p1len + hlen + oplen + a3len + p2len <= ht->hash_size){
|
||||
int offset = 0;
|
||||
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 & 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 & 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 & 64)){ memcpy(hash + offset, SAADDR(¶m->req), a2len); offset += a2len; }
|
||||
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 & 1024)){ memcpy(hash + offset, SAADDR(¶m->srv->intsa), a3len); offset += a3len; }
|
||||
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);
|
||||
unsigned int blen = ht->hash_size;
|
||||
if(!bctx) { memcpy(param->hash, hash, ht->hash_size); return; }
|
||||
if((type & 2) && param->username)mdh_update(bctx, param->username, ulen);
|
||||
if((type & 4) && param->password)mdh_update(bctx, param->password, plen);
|
||||
if((type & 2) && *param->username)mdh_update(bctx, param->username, ulen);
|
||||
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 & 16))mdh_update(bctx, ¶m->srv->acl, acllen);
|
||||
if((type & 64))mdh_update(bctx, SAADDR(¶m->req), a2len);
|
||||
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 & 1024))mdh_update(bctx, SAADDR(¶m->srv->intsa), a3len);
|
||||
if((type & 2048))mdh_update(bctx, SAPORT(¶m->srv->intsa), 2);
|
||||
|
||||
@ -54,8 +54,6 @@
|
||||
after it should be tried again. */
|
||||
#define HTTPSRV_REWRITTEN 2
|
||||
#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 */
|
||||
#define HTTPSRV_LEN_CHUNKED (-1)
|
||||
#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)
|
||||
{
|
||||
struct clientparam *param = r->param;
|
||||
char buf[HTTPSRV_BLOCK];
|
||||
char *buf = (char *)param->tmpbuf;
|
||||
uint64_t sent = 0;
|
||||
|
||||
#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;
|
||||
while(sent < size){
|
||||
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;
|
||||
|
||||
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. */
|
||||
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;
|
||||
int chunked;
|
||||
uint64_t sent = 0;
|
||||
@ -1141,11 +1139,12 @@ int httpopbyname(const unsigned char *name)
|
||||
*/
|
||||
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;
|
||||
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,
|
||||
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. */
|
||||
static void httpsrv_linger(struct clientparam *param)
|
||||
{
|
||||
char buf[HTTPSRV_BLOCK];
|
||||
char *buf = (char *)param->tmpbuf;
|
||||
struct pollfd fd;
|
||||
uint64_t left = HTTPSRV_MAXBODY;
|
||||
time_t deadline = time(NULL) + conf.timeouts[LINGER_TO];
|
||||
@ -1179,33 +1178,12 @@ static void httpsrv_linger(struct clientparam *param)
|
||||
fd.events = POLLIN;
|
||||
if(param->srv->so._poll(param->sostate, &fd, 1, timeo * 1000) <= 0) break;
|
||||
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;
|
||||
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
|
||||
buffer and answers it as a proxy would, asking for its own credentials if
|
||||
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
|
||||
handed on again. */
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
next = proxychild(param);
|
||||
@ -1283,11 +1263,15 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
||||
struct httprule *rule;
|
||||
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',
|
||||
conf.timeouts[STRING_S]);
|
||||
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(rawkeep(r, buf, i)) RETURN(710);
|
||||
buf[i] = 0;
|
||||
|
||||
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,
|
||||
'\n', conf.timeouts[STRING_S])) > 2){
|
||||
hdrs++;
|
||||
if(rawkeep(r, buf, i)) RETURN(710);
|
||||
buf[i] = 0;
|
||||
if(!strncasecmp(buf, "host:", 5) && !r->proxy){
|
||||
sp = buf + 5;
|
||||
@ -1393,13 +1376,10 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
||||
creds[clen] = 0;
|
||||
|
||||
q = strchr(creds, ':');
|
||||
if(q){
|
||||
*q = 0;
|
||||
if(param->password) free(param->password);
|
||||
param->password = (unsigned char *)strdup(q + 1);
|
||||
}
|
||||
if(param->username) free(param->username);
|
||||
param->username = (unsigned char *)strdup(creds);
|
||||
if(q) *q = 0;
|
||||
/* credentials too long to keep are no credentials */
|
||||
if((q && PARAMSTR(param, password, q + 1)) || PARAMSTR(param, username, creds))
|
||||
*param->username = *param->password = 0;
|
||||
}
|
||||
else if(!strncasecmp(buf, "connection:", 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
|
||||
is still in the stream and there is no answering it: what follows would
|
||||
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(param->hostname) free(param->hostname);
|
||||
param->hostname = (unsigned char *)strdup(host);
|
||||
if(PARAMSTR(param, hostname, host)) RETURN(706);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
handoff = r.handoff;
|
||||
if(r.raw) free(r.raw);
|
||||
param->climark = -1;
|
||||
if(!answered) break;
|
||||
|
||||
/* 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]);
|
||||
}
|
||||
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;
|
||||
res = (*param->srv->authfunc)(param);
|
||||
if(res) {RETURN(res);}
|
||||
@ -227,7 +227,7 @@ void * imappchild(struct clientparam* param) {
|
||||
RETURN (mapsocket(param, 180));
|
||||
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)));
|
||||
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;
|
||||
break;
|
||||
case 'U':
|
||||
if(param->username && *param->username){
|
||||
if(*param->username){
|
||||
for(len = 0; i< 4000 && param->username[len]; 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;
|
||||
@ -171,7 +171,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
|
||||
}
|
||||
break;
|
||||
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++){
|
||||
buf[i] = param->hostname[len];
|
||||
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);
|
||||
}
|
||||
|
||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
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);
|
||||
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) {
|
||||
@ -351,10 +353,8 @@ NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
}
|
||||
#ifndef _WIN32
|
||||
void logsyslog(struct clientparam * param, const unsigned char *s) {
|
||||
|
||||
unsigned char tmpbuf[8192];
|
||||
dobuf(param, tmpbuf, s, NULL);
|
||||
if(!param->nolog)syslog(LOG_INFO, "%s", tmpbuf);
|
||||
dobuf(param, param->tmpbuf, s, NULL);
|
||||
if(!param->nolog)syslog(LOG_INFO, "%s", param->tmpbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -276,6 +276,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
int replen, num;
|
||||
char * replace;
|
||||
char * tmpbuf, *target, *newbuf;
|
||||
unsigned char *given = *buf_p;
|
||||
int nreplaces=0;
|
||||
#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;
|
||||
}
|
||||
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;
|
||||
*bufsize_p = newsize;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ static int ldapfunc(struct clientparam *param)
|
||||
char escuser[512];
|
||||
|
||||
/* 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;
|
||||
|
||||
/* init ldap ---------------------- */
|
||||
|
||||
@ -78,7 +78,7 @@ static int pamfunc(struct clientparam *param)
|
||||
NULL };
|
||||
|
||||
/* 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;*/
|
||||
|
||||
#ifdef USERCASE
|
||||
|
||||
@ -31,7 +31,7 @@ extern "C" {
|
||||
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, '\\');
|
||||
if(dom)*dom++=0;
|
||||
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){
|
||||
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->password);
|
||||
return 4;
|
||||
|
||||
@ -68,7 +68,7 @@ void * pop3pchild(struct clientparam* param) {
|
||||
RETURN (mapsocket(param, 180));
|
||||
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)));
|
||||
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]);
|
||||
}
|
||||
|
||||
#ifndef WITHMAIN
|
||||
/* 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
|
||||
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){
|
||||
unsigned char *newbuf;
|
||||
|
||||
@ -171,6 +173,16 @@ static int growbuf(unsigned char **buf, int *bufsize, int need){
|
||||
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){
|
||||
void **pp = (void **)p;
|
||||
if(*pp) { free(*pp); *pp = NULL; }
|
||||
@ -467,16 +479,11 @@ for(;;){
|
||||
sb = (unsigned char *)strchr((char *)username, ':');
|
||||
if(sb){
|
||||
*sb = 0;
|
||||
if(param->password)free(param->password);
|
||||
param->password = (unsigned char *)strdup((char *)sb+1);
|
||||
param->pwtype = 0;
|
||||
}
|
||||
else if(param->password){
|
||||
free(param->password);
|
||||
param->password = NULL;
|
||||
}
|
||||
if(param->username)free(param->username);
|
||||
param->username = (unsigned char *)strdup((char *)username);
|
||||
/* credentials too long to keep are no credentials */
|
||||
if(PARAMSTR(param, password, sb? sb+1 : NULL) || PARAMSTR(param, username, username))
|
||||
*param->username = *param->password = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -512,11 +519,10 @@ for(;;){
|
||||
c = *se;
|
||||
*se = 0;
|
||||
}
|
||||
if(param->hostname && (!*param->hostname || isnumber(param->hostname[strlen((char *)param->hostname) - 1]))){
|
||||
free(param->hostname);
|
||||
param->hostname = NULL;
|
||||
if(*param->hostname && isnumber(param->hostname[strlen((char *)param->hostname) - 1])){
|
||||
*param->hostname = 0;
|
||||
}
|
||||
if(!param->hostname){
|
||||
if(!*param->hostname){
|
||||
if(parsehostname((char *)sb, param, 80)) RETURN(100);
|
||||
}
|
||||
newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
|
||||
@ -543,17 +549,9 @@ for(;;){
|
||||
if(i<=0)continue;
|
||||
username[i] = 0;
|
||||
sb = (unsigned char *)strchr((char *)username, ':');
|
||||
if(sb){
|
||||
*sb = 0;
|
||||
if(param->extpassword)free(param->extpassword);
|
||||
param->extpassword = (unsigned char *)strdup((char *)sb+1);
|
||||
}
|
||||
else if(param->extpassword){
|
||||
free(param->extpassword);
|
||||
param->extpassword = NULL;
|
||||
}
|
||||
if(param->extusername)free(param->extusername);
|
||||
param->extusername = (unsigned char *)strdup((char *)username);
|
||||
if(sb) *sb = 0;
|
||||
if(PARAMSTR(param, extpassword, sb? sb+1 : NULL) || PARAMSTR(param, extusername, username))
|
||||
*param->extusername = *param->extpassword = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -606,7 +604,7 @@ for(;;){
|
||||
#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 <= 10 || haveconnection || param->transparent) RETURN(res);
|
||||
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){
|
||||
uint64_t newlen64;
|
||||
newlen64 = (uint64_t) sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S);
|
||||
newlen64 = fillwhole(param, CLIENT, contentlength64);
|
||||
if(newlen64 == contentlength64) {
|
||||
action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, 0, (int *)¶m->cliinbuf);
|
||||
if(action == HANDLED){
|
||||
@ -1025,9 +1023,9 @@ for(;;){
|
||||
if(keepalive <= 1) {
|
||||
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");
|
||||
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);}
|
||||
hlen = (int)(sb - buf);
|
||||
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){
|
||||
uint64_t newlen;
|
||||
newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S);
|
||||
newlen = fillwhole(param, SERVER, contentlength64);
|
||||
if(newlen == contentlength64) {
|
||||
action = handlepredatflt(param);
|
||||
if(action == HANDLED){
|
||||
|
||||
30
src/proxy.h
30
src/proxy.h
@ -22,6 +22,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
@ -36,8 +37,9 @@
|
||||
#define MAXNSERVERS 5
|
||||
#define DEFAULT_MAXCHILD 500
|
||||
|
||||
#define TCPBUFSIZE 65536
|
||||
#define SRVBUFSIZE (param->srv->bufsize?param->srv->bufsize:((param->service == S_UDPPM)?UDPBUFSIZE:TCPBUFSIZE))
|
||||
/* How much of a connection's buffer is read into at once: all of it, or
|
||||
less if the service was told so with -b. */
|
||||
#define SRVBUFSIZE(srv) (((srv)->bufsize > 0 && (srv)->bufsize < CLIENTBUFSIZE)? (unsigned)(srv)->bufsize : CLIENTBUFSIZE)
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -116,17 +118,6 @@ void daemonize(void);
|
||||
#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
|
||||
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 sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec);
|
||||
unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, int timeosec);
|
||||
unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec);
|
||||
unsigned long sockfillbuf(struct clientparam * param, DIRECTION which, 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 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 dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
|
||||
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 lognone(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);
|
||||
struct passwords * copypwl (struct passwords *pwl);
|
||||
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 handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p);
|
||||
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);
|
||||
#endif
|
||||
|
||||
int pushbackcli(struct clientparam * param, const unsigned char * data, int len);
|
||||
int parsepattern(struct hostname *h, unsigned char *arg);
|
||||
int parsepathpattern(struct hostname *h, unsigned char *arg);
|
||||
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. */
|
||||
static void srvdiscard(struct srvstart *s){
|
||||
srvfree(&s->srv);
|
||||
if(s->defparam.hostname) free(s->defparam.hostname);
|
||||
if(s->cbc_string) free(s->cbc_string);
|
||||
if(s->cbl_string) free(s->cbl_string);
|
||||
if(s->fp) fclose(s->fp);
|
||||
@ -751,7 +750,7 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
||||
|
||||
|
||||
#ifndef STDMAIN
|
||||
copyfilter(conf.filters, srv);
|
||||
if((error = copyfilter(conf.filters, srv))) return error;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -1055,8 +1054,10 @@ static int srvspawn(struct srvstart *s, SOCKET client_sock){
|
||||
usleep(SLEEPTIME);
|
||||
return 1;
|
||||
};
|
||||
*newparam = *defparam;
|
||||
if(defparam->hostname)newparam->hostname=(unsigned char *)strdup((char *)defparam->hostname);
|
||||
memcpy(newparam, defparam, offsetof(struct clientparam, filters));
|
||||
newparam->clibuf = newparam->clibufdata;
|
||||
newparam->srvbuf = newparam->srvbufdata;
|
||||
newparam->clibufsize = newparam->srvbufsize = SRVBUFSIZE(srv);
|
||||
clearstat(newparam);
|
||||
if(!s->isudp) newparam->clisock = client_sock;
|
||||
newparam->prev = newparam->next = NULL;
|
||||
@ -1431,6 +1432,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
||||
param->paused = srv->paused;
|
||||
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
||||
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;
|
||||
_3proxy_mutex_init(&srv->counter_mutex);
|
||||
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
||||
@ -1551,8 +1553,8 @@ void freeparam(struct clientparam * param) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(param->clibuf) free(param->clibuf);
|
||||
if(param->srvbuf) free(param->srvbuf);
|
||||
if(param->clibuf != param->clibufdata) free(param->clibuf);
|
||||
if(param->srvbuf != param->srvbufdata) free(param->srvbuf);
|
||||
#ifdef WITHSPLICE
|
||||
if(param->pipecli[0] >= 0) close(param->pipecli[0]);
|
||||
if(param->pipecli[1] >= 0) close(param->pipecli[1]);
|
||||
@ -1590,22 +1592,12 @@ void freeparam(struct clientparam * param) {
|
||||
param->srv->so._closesocket(param->sostate, param->clisock);
|
||||
}
|
||||
}
|
||||
if(param->datfilterssrv) free(param->datfilterssrv);
|
||||
#ifndef STDMAIN
|
||||
if(param->reqfilters) free(param->reqfilters);
|
||||
if(param->connectfilters) free(param->connectfilters);
|
||||
if(param->afterauthfilters) free(param->afterauthfilters);
|
||||
if(param->hdrfilterscli) free(param->hdrfilterscli);
|
||||
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--){
|
||||
while(param->nfilters > 0){
|
||||
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);
|
||||
#endif
|
||||
/* Leaving the service comes last. Once its last child is gone, srvfree()
|
||||
@ -1629,11 +1621,6 @@ void freeparam(struct clientparam * param) {
|
||||
}
|
||||
_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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
static void * itcopy (void * from, size_t size){
|
||||
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;
|
||||
|
||||
if(!filter) return;
|
||||
if(!filter) return 0;
|
||||
for(srv->filter = filter; srv->filter; srv->filter = srv->filter->next) nfilters++;
|
||||
srv->filter = malloc(sizeof(struct filter) * nfilters);
|
||||
if(!srv->filter) return;
|
||||
if(!srv->filter) return 2;
|
||||
|
||||
for(; filter; filter = filter->next){
|
||||
void *data = NULL;
|
||||
|
||||
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].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_cli)srv->ndatfilterscli++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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(!(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++){
|
||||
if(!srv->filter[i].filter_client)continue;
|
||||
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 action;
|
||||
int i;
|
||||
unsigned char *cur = *buf_p;
|
||||
|
||||
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);
|
||||
filterswap(param, &cur, *buf_p);
|
||||
if(action!=CONTINUE) return action;
|
||||
}
|
||||
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 action;
|
||||
int i;
|
||||
unsigned char *cur = *buf_p;
|
||||
|
||||
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);
|
||||
filterswap(param, &cur, *buf_p);
|
||||
if(action!=CONTINUE) return action;
|
||||
}
|
||||
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 action;
|
||||
int i;
|
||||
unsigned char *cur = *buf_p;
|
||||
|
||||
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);
|
||||
filterswap(param, &cur, *buf_p);
|
||||
if(action!=CONTINUE) return action;
|
||||
}
|
||||
return PASS;
|
||||
@ -1988,9 +1987,11 @@ FILTER_ACTION handledatfltcli(struct clientparam *cparam, unsigned char ** buf_p
|
||||
#ifndef STDMAIN
|
||||
FILTER_ACTION action;
|
||||
int i;
|
||||
unsigned char *cur = *buf_p;
|
||||
|
||||
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);
|
||||
filterswap(cparam, &cur, *buf_p);
|
||||
if(action!=CONTINUE) return action;
|
||||
}
|
||||
#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 action;
|
||||
int i;
|
||||
unsigned char *cur = *buf_p;
|
||||
|
||||
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);
|
||||
filterswap(cparam, &cur, *buf_p);
|
||||
if(action!=CONTINUE) return action;
|
||||
}
|
||||
return PASS;
|
||||
|
||||
@ -26,16 +26,11 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
|
||||
|
||||
user = redir->extuser;
|
||||
pass = redir->extpass;
|
||||
if (!param->srvbufsize){
|
||||
param->srvbufsize = SRVBUFSIZE;
|
||||
param->srvbuf = malloc(param->srvbufsize);
|
||||
if(!param->srvbuf) return 21;
|
||||
}
|
||||
buf = param->srvbuf;
|
||||
username = buf + 2048;
|
||||
if(user) {
|
||||
if (*user == '*') {
|
||||
if(!param->username) return 4;
|
||||
if(!*param->username) return 4;
|
||||
user = param->username;
|
||||
pass = param->password;
|
||||
}
|
||||
@ -415,15 +410,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
else if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
|
||||
int i;
|
||||
if(cur->extuser){
|
||||
if(param->extusername)
|
||||
free(param->extusername);
|
||||
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(*cur->extuser == '*' && !param->username) return 4;
|
||||
if(*cur->extuser == '*' && !*param->username) return 4;
|
||||
if(PARAMSTR(param, extusername, (*cur->extuser == '*')? param->username : cur->extuser)) return 21;
|
||||
if(cur->extpass && PARAMSTR(param, extpassword, (*cur->extuser == '*' && *param->password)?param->password : cur->extpass)) return 21;
|
||||
}
|
||||
|
||||
for(i=0; redirs[i].name; i++){
|
||||
@ -490,15 +479,9 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
param->redirtype = redir->type;
|
||||
if(redir->type == R_TCP || redir->type ==R_HTTP) {
|
||||
if(cur->extuser){
|
||||
if(*cur -> extuser == '*' && !param->username) return 4;
|
||||
if(param->extusername)
|
||||
free(param->extusername);
|
||||
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(*cur -> extuser == '*' && !*param->username) return 4;
|
||||
if(PARAMSTR(param, extusername, (*cur->extuser == '*')? param->username : cur->extuser)) return 21;
|
||||
if(cur->extpass && PARAMSTR(param, extpassword, (*cur->extuser == '*' && *param->password)?param->password : cur->extpass)) return 21;
|
||||
}
|
||||
if(redir->secure) return ssl_parent(param);
|
||||
return 0;
|
||||
@ -507,7 +490,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
}
|
||||
|
||||
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(saved){
|
||||
SOCKET s;
|
||||
|
||||
@ -201,8 +201,8 @@ uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_
|
||||
s2 = s1;
|
||||
}
|
||||
*s2 = 0;
|
||||
if(param->username)free(param->username);
|
||||
param->username = (unsigned char *)strdup ((char *)buf + k + 13);
|
||||
/* a name longer than the field is no name to authenticate */
|
||||
if(PARAMSTR(param, username, buf + k + 13)) return 0;
|
||||
|
||||
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;
|
||||
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 {
|
||||
i = sockgetlinebuf(param, SERVER, buf, bufsize-1, '\n', conf.timeouts[STRING_L]);
|
||||
if(i < 1) break;
|
||||
#ifndef WITHMAIN
|
||||
res = handlehdrfilterssrv(param, &buf, &bufsize, 0, &i);
|
||||
if(res != PASS) {
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
|
||||
} while (i > 3 && buf[3] == '-');
|
||||
if(i < 3) {
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return 0;
|
||||
}
|
||||
buf[i] = 0;
|
||||
res = atoi((char *)buf);
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -64,14 +64,14 @@ int readcommand (struct clientparam* param) {
|
||||
#endif
|
||||
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]);
|
||||
if(i < 4) return 0;
|
||||
#ifndef WITHMAIN
|
||||
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);
|
||||
if(res != PASS) {
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
if(res == HANDLED) return 2;
|
||||
return -1;
|
||||
}
|
||||
@ -81,7 +81,7 @@ int readcommand (struct clientparam* param) {
|
||||
if(!strncasecmp((char *)buf, "STARTTLS", 8) || !strncasecmp((char *)buf, "TURN", 4)){
|
||||
ret = 22;
|
||||
}
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -92,12 +92,12 @@ int readdata (struct clientparam* param) {
|
||||
int res;
|
||||
#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] == '.')){
|
||||
#ifndef WITHMAIN
|
||||
res = handledatfltcli(param, &buf, &bufsize, 0, &i);
|
||||
if(res != PASS) {
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
if(res == HANDLED) return 1;
|
||||
return -1;
|
||||
}
|
||||
@ -105,11 +105,11 @@ int readdata (struct clientparam* param) {
|
||||
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
||||
}
|
||||
if(i < 1) {
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return 0;
|
||||
}
|
||||
socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S]);
|
||||
free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#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 {
|
||||
login = -1;
|
||||
buf[i] = 0;
|
||||
@ -172,8 +172,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
i = de64(buf,username,255);
|
||||
if(i < 0) {RETURN(666);}
|
||||
username[i] = 0;
|
||||
if(param->extpassword) free(param->extpassword);
|
||||
param->extpassword = (unsigned char *)strdup((char *)username);
|
||||
if(PARAMSTR(param, extpassword, username)) {RETURN(666);}
|
||||
}
|
||||
else if(login == 2){
|
||||
if(i > 13) {
|
||||
@ -192,16 +191,23 @@ void * smtppchild(struct clientparam* param) {
|
||||
if(parseconnusername((char *)username+1, param, 0, 587)) {RETURN(670);}
|
||||
res = (int)strlen((char *)username+1) + 2;
|
||||
if(res < i){
|
||||
if(param->extpassword) free(param->extpassword);
|
||||
param->extpassword = (unsigned char *)strdup((char *)username + res);
|
||||
if(PARAMSTR(param, extpassword, username + res)) {RETURN(670);}
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
reqbufsize = reqsize = (int)strlen((char *)param->hostname) + 1;
|
||||
action = handlereqfilters(param, ¶m->hostname, &reqbufsize, 0, &reqsize);
|
||||
unsigned char *req = param->tmpbuf;
|
||||
|
||||
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){
|
||||
RETURN(0);
|
||||
}
|
||||
@ -232,8 +238,8 @@ void * smtppchild(struct clientparam* param) {
|
||||
|
||||
} while (i > 3 && buf[3] == '-');
|
||||
if(i<3) {RETURN(672);}
|
||||
if(!command || (param->extusername && param->extpassword)){
|
||||
if(!param->extusername || !*param->extusername || !param->extpassword || !*param->extpassword || !login){
|
||||
if(!command || (*param->extusername && *param->extpassword)){
|
||||
if(!*param->extusername || !*param->extpassword || !login){
|
||||
socksend(param, param->clisock, (unsigned char *)"235 auth required\r\n", 19,conf.timeouts[STRING_S]);
|
||||
}
|
||||
if ((login & 1)) {
|
||||
@ -285,9 +291,9 @@ void * smtppchild(struct clientparam* param) {
|
||||
res = 1;
|
||||
#ifndef WITHMAIN
|
||||
if(!strncasecmp(command, "MAIL", 4) || !strncasecmp(command, "RCPT", 4) || !strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4)){
|
||||
res = (int)strlen(command);
|
||||
command[res] = 0;
|
||||
res = handlehdrfilterscli(param, (unsigned char **)&command, &res, 0, &res);
|
||||
int clen = (int)strlen(command), csize = clen + 1;
|
||||
|
||||
res = handlehdrfilterscli(param, (unsigned char **)&command, &csize, 0, &clen);
|
||||
if(res != PASS) {
|
||||
if(res == HANDLED) res = 2;
|
||||
else RETURN(677);
|
||||
@ -321,7 +327,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
|
||||
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)));
|
||||
dolog(param, buf);
|
||||
}
|
||||
|
||||
@ -70,112 +70,122 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
||||
return res;
|
||||
}
|
||||
|
||||
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
||||
int len;
|
||||
|
||||
if(!param->clibuf){
|
||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return 0;
|
||||
param->clibufsize = SRVBUFSIZE;
|
||||
param->clioffset = param->cliinbuf = 0;
|
||||
/* Starts an empty buffer over from its beginning, and goes back to the
|
||||
connection's own buffer if a filter needed a bigger one. Does nothing
|
||||
while anything is left unread. */
|
||||
void bufrelease(struct clientparam * param, DIRECTION which){
|
||||
if(which){
|
||||
if(param->srvinbuf != param->srvoffset) return;
|
||||
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){
|
||||
return (int)param->clibuf[param->clioffset++];
|
||||
else {
|
||||
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
|
||||
service which has already taken a request off the socket can hand it to
|
||||
another one, which reads it the way it reads anything else. */
|
||||
int pushbackcli(struct clientparam * param, const unsigned char * data, int len){
|
||||
unsigned left = 0;
|
||||
unsigned need;
|
||||
/* Makes room for size bytes from the start of what is unread, which is
|
||||
moved there: a body to be filtered whole is read into one buffer, which
|
||||
may have to be bigger than the connection's own. Returns 1 when that
|
||||
much cannot be had. */
|
||||
int bufroom(struct clientparam * param, DIRECTION which, unsigned long size){
|
||||
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(param->clibuf) left = param->cliinbuf - param->clioffset;
|
||||
need = (unsigned)len + left;
|
||||
|
||||
if(!param->clibuf){
|
||||
if(!(param->clibuf = malloc(need > SRVBUFSIZE? need : SRVBUFSIZE))) return 1;
|
||||
param->clibufsize = need > SRVBUFSIZE? need : SRVBUFSIZE;
|
||||
if(*offset){
|
||||
memmove(*buf, *buf + *offset, left);
|
||||
*inbuf = left;
|
||||
*offset = 0;
|
||||
}
|
||||
else if(param->clibufsize < need){
|
||||
unsigned char *nb = realloc(param->clibuf, need);
|
||||
|
||||
if(!nb) return 1;
|
||||
param->clibuf = nb;
|
||||
param->clibufsize = need;
|
||||
}
|
||||
if(left) memmove(param->clibuf + len, param->clibuf + param->clioffset, left);
|
||||
memcpy(param->clibuf, data, (size_t)len);
|
||||
param->clioffset = 0;
|
||||
param->cliinbuf = need;
|
||||
if(size <= *bufsize) return 0;
|
||||
if((unsigned long)(unsigned)size != size || !(nb = malloc(size))) return 1;
|
||||
memcpy(nb, *buf, left);
|
||||
if(*buf != own) free(*buf);
|
||||
*buf = nb;
|
||||
*bufsize = (unsigned)size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, int timeosec){
|
||||
int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
||||
int len;
|
||||
unsigned keep = 0;
|
||||
|
||||
if(!param->clibuf) return 0;
|
||||
if(param->cliinbuf == param->clioffset){
|
||||
param->cliinbuf = param->clioffset = 0;
|
||||
if(param->cliinbuf && param->clioffset < param->cliinbuf){
|
||||
return (int)param->clibuf[param->clioffset++];
|
||||
}
|
||||
else if(param->clioffset){
|
||||
memmove(param->clibuf, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset);
|
||||
param->cliinbuf -= param->clioffset;
|
||||
param->clioffset = 0;
|
||||
if(param->climark == -2) return EOF; /* nothing more until it is cleared */
|
||||
if(param->climark >= 0){
|
||||
/* what was read since the mark stays, moved to the start */
|
||||
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;
|
||||
size -= param->cliinbuf;
|
||||
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 += len;
|
||||
}
|
||||
return param->cliinbuf;
|
||||
else bufrelease(param, CLIENT);
|
||||
if ((len = sockrecvfrom(param, param->clisock, (struct sockaddr *)¶m->sincr, param->clibuf + keep, param->clibufsize - keep, timeosec*1000 + timeousec))<=0) return EOF;
|
||||
param->cliinbuf = keep + len;
|
||||
param->clioffset = keep + 1;
|
||||
return (int)param->clibuf[keep];
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(!param->srvbuf) return 0;
|
||||
if(param->srvinbuf == param->srvoffset){
|
||||
param->srvinbuf = param->srvoffset = 0;
|
||||
if(*offset){
|
||||
memmove(buf, buf + *offset, *inbuf - *offset);
|
||||
*inbuf -= *offset;
|
||||
*offset = 0;
|
||||
}
|
||||
else if(param->srvoffset){
|
||||
memmove(param->srvbuf, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset);
|
||||
param->srvinbuf -= param->srvoffset;
|
||||
param->srvoffset = 0;
|
||||
}
|
||||
if(size <= param->srvinbuf) return 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;
|
||||
while(*inbuf < size && *inbuf < bufsize){
|
||||
want = (size - *inbuf < bufsize - *inbuf)? (unsigned)(size - *inbuf) : bufsize - *inbuf;
|
||||
len = which?
|
||||
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;
|
||||
}
|
||||
return param->srvinbuf;
|
||||
}
|
||||
return *inbuf < size? *inbuf : size;
|
||||
}
|
||||
|
||||
|
||||
int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
|
||||
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){
|
||||
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;
|
||||
param->srvinbuf = len;
|
||||
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 && allowcli && param->waitclient64 && fromclient > inclientbuf && fromclient - inclientbuf >= SPLICE_MIN) splicecli = 1;
|
||||
#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->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
||||
if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0;
|
||||
@ -268,7 +261,7 @@ log("done send to server from buf");
|
||||
inclientbuf -= res;
|
||||
fromclient -= 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->bandlimfunc) {
|
||||
int sl1;
|
||||
@ -314,7 +307,7 @@ log("done send to client from buf");
|
||||
inserverbuf -= res;
|
||||
fromserver -= res;
|
||||
param->srvoffset += res;
|
||||
if(param->srvoffset == param->srvinbuf)param->srvoffset = param->srvinbuf =0;
|
||||
bufrelease(param, SERVER);
|
||||
if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
||||
needaction = 0;
|
||||
continue;
|
||||
@ -324,12 +317,10 @@ log("done send to client from buf");
|
||||
/* a direction going back to copying does once its pipe is empty */
|
||||
if(wantbufcli && !inclientpipe){
|
||||
splicecli = wantbufcli = streakcli = 0;
|
||||
if(!param->clibuf && (!(param->clibuf=malloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))) RETURN (21);
|
||||
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
||||
}
|
||||
if(wantbufsrv && !inserverpipe){
|
||||
splicesrv = wantbufsrv = streaksrv = 0;
|
||||
if(!param->srvbuf && (!(param->srvbuf=malloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))) RETURN (21);
|
||||
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){
|
||||
/* no pipe to be had: copy instead */
|
||||
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
||||
if(!param->clibuf && (!(param->clibuf=malloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))) RETURN (21);
|
||||
if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
||||
continue;
|
||||
}
|
||||
@ -459,7 +449,6 @@ log("read from server to pipe\n");
|
||||
#endif
|
||||
if(pipesrv[0] < 0 && pipe2(pipesrv, O_NONBLOCK) < 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;
|
||||
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){
|
||||
sprintf((char *)buf, "%s ", commands[command]);
|
||||
if(param->hostname){
|
||||
if(*param->hostname){
|
||||
sprintf((char *)buf + strlen((char *)buf), "%.256s", param->hostname);
|
||||
}
|
||||
else
|
||||
@ -37,7 +37,11 @@ void * sockschild(struct clientparam* param) {
|
||||
unsigned size;
|
||||
SASIZETYPE sasize;
|
||||
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 command=0;
|
||||
struct pollfd fds[3];
|
||||
@ -48,7 +52,6 @@ void * sockschild(struct clientparam* param) {
|
||||
|
||||
param->service = S_SOCKS;
|
||||
|
||||
if(!(buf = malloc(BUFSIZE))) {RETURN(21);}
|
||||
memset(buf, 0, BUFSIZE);
|
||||
if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
|
||||
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 && (res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != (int)i) {RETURN(441);}
|
||||
buf[i] = 0;
|
||||
if(!param->username) {
|
||||
param->username = (unsigned char *)strdup((char *)buf);
|
||||
if(!param->username){RETURN(21);}
|
||||
if(!*param->username) {
|
||||
if(PARAMSTR(param, username, buf)){RETURN(21);}
|
||||
}
|
||||
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);}
|
||||
buf[i] = 0;
|
||||
if(!param->password) {
|
||||
param->password = (unsigned char *)strdup((char *)buf);
|
||||
if(!param->password){RETURN(21);}
|
||||
if(!*param->password) {
|
||||
if(PARAMSTR(param, password, buf)){RETURN(21);}
|
||||
}
|
||||
buf[0] = 1;
|
||||
buf[1] = 0;
|
||||
@ -137,9 +138,7 @@ void * sockschild(struct clientparam* param) {
|
||||
default:
|
||||
RETURN(997);
|
||||
}
|
||||
if(param->hostname)free(param->hostname);
|
||||
param->hostname = (unsigned char *)strdup((char *)buf);
|
||||
if(!param->hostname){RETURN(21);}
|
||||
if(PARAMSTR(param, hostname, buf)){RETURN(21);}
|
||||
if (ver == 5) {
|
||||
if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
|
||||
buf[0] = (unsigned char) res;
|
||||
@ -151,17 +150,14 @@ void * sockschild(struct clientparam* param) {
|
||||
else {
|
||||
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
||||
buf[127] = 0;
|
||||
if(param->srv->needuser && *buf && !param->username) {
|
||||
param->username = (unsigned char *)strdup((char *)buf);
|
||||
if(!param->username){RETURN(21);}
|
||||
if(param->srv->needuser && *buf && !*param->username) {
|
||||
if(PARAMSTR(param, username, buf)){RETURN(21);}
|
||||
}
|
||||
if(!memcmp(SAADDR(¶m->req), "\0\0\0", 3)){
|
||||
param->service = S_SOCKS45;
|
||||
if(sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]) < 0) {RETURN(441);}
|
||||
buf[127] = 0;
|
||||
if(param->hostname)free(param->hostname);
|
||||
param->hostname = (unsigned char *)strdup((char *)buf);
|
||||
if(!param->hostname){RETURN(21);}
|
||||
if(PARAMSTR(param, hostname, buf)){RETURN(21);}
|
||||
if(!getip46(param->srv->family, buf, (struct sockaddr *) ¶m->req)) RETURN(100);
|
||||
param->sinsr = param->req;
|
||||
}
|
||||
@ -346,7 +342,7 @@ fflush(stderr);
|
||||
switch(command) {
|
||||
case 1:
|
||||
if(param->redirectfunc){
|
||||
if(buf)free(buf);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||
@ -421,12 +417,9 @@ fflush(stderr);
|
||||
}
|
||||
|
||||
if(command > 3) command = 0;
|
||||
if(buf){
|
||||
printcommand(buf, command, param);
|
||||
|
||||
dolog(param, buf);
|
||||
free(buf);
|
||||
}
|
||||
printcommand(logline, command, param);
|
||||
dolog(param, logline);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
10
src/ssl.c
10
src/ssl.c
@ -453,11 +453,13 @@ int docli(struct clientparam* param){
|
||||
|
||||
SSL_CONN ServerConn;
|
||||
SSL_CERT ServerCert=NULL;
|
||||
unsigned char *hostname;
|
||||
hostname = param->hostname;
|
||||
param->hostname = (unsigned char *)PCONF->client_sni;
|
||||
unsigned char hostname[HOSTNAMELEN];
|
||||
|
||||
/* 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);
|
||||
param->hostname = hostname;
|
||||
memcpy(param->hostname, hostname, sizeof(hostname));
|
||||
_ssl_cert_free(ServerCert);
|
||||
|
||||
if(!ServerConn) return 1;
|
||||
|
||||
@ -199,6 +199,12 @@ int
|
||||
|
||||
#define MAX_HASH_SIZE (64)
|
||||
#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;
|
||||
typedef enum {
|
||||
@ -396,8 +402,6 @@ struct httpreq {
|
||||
int proxy; /* the client asked the way it asks a proxy */
|
||||
int connect; /* and asked for a tunnel */
|
||||
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 */
|
||||
char *lasthost; /* where the last request on this connection went */
|
||||
void *handoff; /* a child which takes the connection over */
|
||||
@ -527,7 +531,7 @@ struct filterp {
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define MAX_FILTERS 16
|
||||
#define MAX_FILTERS 256
|
||||
|
||||
/* 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. */
|
||||
@ -688,11 +692,6 @@ struct clientparam {
|
||||
TRAFCOUNTFUNC trafcountfunc;
|
||||
|
||||
|
||||
struct filterp *filters,
|
||||
**reqfilters, **connectfilters, **afterauthfilters,
|
||||
**hdrfilterscli, **hdrfilterssrv,
|
||||
**predatfilters, **datfilterscli, **datfilterssrv;
|
||||
|
||||
PROXYSERVICE service;
|
||||
|
||||
PROXYSERVICE clientstarttls;
|
||||
@ -735,12 +734,7 @@ struct clientparam {
|
||||
preauth,
|
||||
dstindep;
|
||||
|
||||
unsigned char *hostname,
|
||||
*username,
|
||||
*password,
|
||||
*extusername,
|
||||
*extpassword,
|
||||
*clibuf,
|
||||
unsigned char *clibuf,
|
||||
*srvbuf;
|
||||
|
||||
/* 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. */
|
||||
struct chain *failedparents[MAXFAILEDPARENTS];
|
||||
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 {
|
||||
|
||||
@ -16,12 +16,12 @@
|
||||
void * tcppmchild(struct clientparam* param) {
|
||||
int res;
|
||||
|
||||
if(!param->hostname){
|
||||
if(!*param->hostname){
|
||||
#ifdef WITH_UN
|
||||
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->req);
|
||||
param->hostname = (unsigned char *)strdup((char *)param->srv->target);
|
||||
if(PARAMSTR(param, hostname, param->srv->target)) RETURN(100);
|
||||
} else
|
||||
#endif
|
||||
if(
|
||||
@ -46,7 +46,7 @@ void * tcppmchild(struct clientparam* param) {
|
||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||
CLEANRET:
|
||||
|
||||
dolog(param, param->hostname);
|
||||
dolog(param, *param->hostname? param->hostname : 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;
|
||||
}
|
||||
|
||||
int tlstobufcli(struct clientparam *param){
|
||||
unsigned long len, newlen;
|
||||
if(!param->clibuf){
|
||||
if(!(param->clibuf = malloc(SRVBUFSIZE))) return -1;
|
||||
param->clibufsize = SRVBUFSIZE;
|
||||
param->clioffset = param->cliinbuf = 0;
|
||||
}
|
||||
if(param->srvinbuf != param->srvoffset){
|
||||
len = socksend(param, param->clisock, param->srvbuf+param->srvoffset,param->srvinbuf-param->srvoffset, conf.timeouts[STRING_S]);
|
||||
if(len != param->srvinbuf-param->srvoffset){
|
||||
return -2;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* Has one whole TLS record from one side at the start of its buffer, once
|
||||
whatever is still buffered from the other side is passed on. Returns its
|
||||
length, or less than 0; the server's codes are one further on than the
|
||||
client's, as the log has always had them. */
|
||||
static int tlstobuf(struct clientparam *param, DIRECTION which){
|
||||
unsigned *oinbuf = which? ¶m->cliinbuf : ¶m->srvinbuf;
|
||||
unsigned *ooffset = which? ¶m->clioffset : ¶m->srvoffset;
|
||||
unsigned char *obuf = which? param->clibuf : param->srvbuf;
|
||||
unsigned char *buf;
|
||||
int e = which? 1 : 0;
|
||||
unsigned long len;
|
||||
|
||||
int tlstobufsrv(struct clientparam *param){
|
||||
unsigned long len, newlen;
|
||||
|
||||
if(param->cliinbuf != param->clioffset){
|
||||
len = socksend(param, param->remsock, param->clibuf+param->clioffset,param->cliinbuf-param->clioffset, conf.timeouts[STRING_S]);
|
||||
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(*oinbuf != *ooffset){
|
||||
len = *oinbuf - *ooffset;
|
||||
if((unsigned long)socksend(param, which? param->remsock : param->clisock, obuf + *ooffset, (int)len, conf.timeouts[STRING_S]) != len)
|
||||
return which? -1 : -2;
|
||||
*oinbuf = *ooffset = 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -343,7 +309,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
if(res < 0) RETURN(0);
|
||||
}
|
||||
|
||||
res = tlstobufcli(param);
|
||||
res = tlstobuf(param, CLIENT);
|
||||
if(res <= 0 || param->clibuf[0] != 22){
|
||||
if(param->srv->requirecert)RETURN(300-res);
|
||||
}
|
||||
@ -351,12 +317,10 @@ void * tlsprchild(struct clientparam* param) {
|
||||
lv = param->clibuf[2];
|
||||
res = parsehello(1, param->clibuf, (unsigned)res, sni, &snipos, &lv, proto);
|
||||
if(res > 0){
|
||||
if(param->hostname){
|
||||
free(param->hostname);
|
||||
param->hostname = NULL;
|
||||
if(*param->hostname){
|
||||
if(PARAMSTR(param, hostname, sni)) 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){
|
||||
int len;
|
||||
|
||||
@ -395,7 +359,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
}
|
||||
|
||||
if(param->srv->requirecert > 1){
|
||||
res = tlstobufsrv(param);
|
||||
res = tlstobuf(param, SERVER);
|
||||
if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res);
|
||||
lv = param->srvbuf[2];
|
||||
res = parsehello(2, param->srvbuf, (unsigned)res, sni, &snipos, &lv, proto);
|
||||
@ -408,7 +372,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
len = param->srvinbuf;
|
||||
if(socksend(param, param->clisock, param->srvbuf,len, conf.timeouts[STRING_S]) != len) RETURN(371);
|
||||
param->srvinbuf = 0;
|
||||
res = tlstobufsrv(param);
|
||||
res = tlstobuf(param, SERVER);
|
||||
if(res <= 0) RETURN(380-res);
|
||||
if(param->srvbuf[0]!= 22) break;
|
||||
switch(param->srvbuf[5]){
|
||||
@ -430,7 +394,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
if(param->srv->requirecert > 3){
|
||||
if(!reqcert) RETURN(374);
|
||||
for(done=0;!done;) {
|
||||
res = tlstobufcli(param);
|
||||
res = tlstobuf(param, CLIENT);
|
||||
if(res <= 0) RETURN(390-res);
|
||||
len = res;
|
||||
if(param->clibuf[0]!= 22) break;
|
||||
@ -456,7 +420,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||
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);
|
||||
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){
|
||||
|
||||
char addrbuf[64];
|
||||
int res = 1;
|
||||
|
||||
#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. */
|
||||
if(res) return PASS;
|
||||
|
||||
pl->myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)addrbuf, sizeof(addrbuf));
|
||||
if(param->hostname) pl->freefunc(param->hostname);
|
||||
param->hostname = (unsigned char *)pl->strdupfunc(addrbuf);
|
||||
/* an address always fits the field */
|
||||
pl->myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)param->hostname, sizeof(param->hostname));
|
||||
param->sinsr = param->req;
|
||||
return PASS;
|
||||
}
|
||||
|
||||
@ -50,10 +50,6 @@ void * udppmchild(struct clientparam* param) {
|
||||
if(authres) { RETURN(authres); }
|
||||
if((authres = udpbind(param))) { RETURN(authres); }
|
||||
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->udp_nhops){
|
||||
for(i=1; i < param->udp_nhops; i++){
|
||||
|
||||
@ -93,7 +93,7 @@ static void udplog(struct clientparam *param)
|
||||
|
||||
if(!param->srv->logfunc) return;
|
||||
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);
|
||||
sprintf((char *)buf + len, ":%hu", ntohs(*SAPORT(¶m->req)));
|
||||
param->srv->logfunc(param, buf);
|
||||
@ -208,12 +208,6 @@ int udpsockmap(struct clientparam *param, int timeo)
|
||||
char lastname[256] = "";
|
||||
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;
|
||||
if(param->ctrlsock != INVALID_SOCKET){
|
||||
sasize = sizeof(cliaddr);
|
||||
@ -313,13 +307,11 @@ int udpsockmap(struct clientparam *param, int timeo)
|
||||
PROXYSOCKADDRTYPE newdst = dst;
|
||||
|
||||
param->req = lastdst;
|
||||
if (param->hostname) free(param->hostname);
|
||||
param->hostname = *lastname? (unsigned char *)strdup(lastname) : NULL;
|
||||
if (PARAMSTR(param, hostname, lastname)) *param->hostname = 0;
|
||||
udplog(param);
|
||||
dst = newdst;
|
||||
}
|
||||
if (param->hostname) free(param->hostname);
|
||||
param->hostname = dstname? (unsigned char *)strdup(dstname) : NULL;
|
||||
if (PARAMSTR(param, hostname, dstname)) *param->hostname = 0;
|
||||
param->req = dst;
|
||||
if (!nhops) param->sinsr = dst;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user