mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-16 06:05:50 +08:00
Compare commits
6 Commits
235f899668
...
57b94b209b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b94b209b | ||
|
|
3040de2b55 | ||
|
|
c687380776 | ||
|
|
a00c0823f5 | ||
|
|
01600e46d6 | ||
|
|
0cf5dfc6a3 |
@ -429,11 +429,12 @@ static int targetunsafe(const char *path)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if(!strncmp(path, "./", 2) || !strncmp(path, "../", 3)) return 1;
|
if(!strncmp(path, "./", 2) || !strncmp(path, "../", 3)) return 1;
|
||||||
if(strstr(path, "/./") || strstr(path, "/../")) return 1;
|
/* a dot-dot segment, with either separator, wherever it is in the
|
||||||
if(strstr(path, "\\.\\") || strstr(path, "\\..\\")) return 1;
|
path: a walk out of the tree, or a file named to look like one */
|
||||||
|
if(strstr(path, "/..") || strstr(path, "\\..")) return 1;
|
||||||
|
if(strstr(path, "/./") || strstr(path, "\\.\\")) return 1;
|
||||||
p = path + strlen(path);
|
p = path + strlen(path);
|
||||||
if(p - path >= 2 && !strcmp(p - 2, "/.")) return 1;
|
if(p - path >= 2 && (!strcmp(p - 2, "/.") || !strcmp(p - 2, "\\."))) return 1;
|
||||||
if(p - path >= 3 && !strcmp(p - 3, "/..")) return 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1462,16 +1463,27 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i && i != 10){
|
if(i){
|
||||||
/* The body goes before the answer, as for any answer this server
|
/* The body goes before the answer, as for any answer this server
|
||||||
gives: left in the stream it would be read as the next request. */
|
gives: left in the stream it would be read as the next request. */
|
||||||
if(!r->drained){
|
if(!r->drained){
|
||||||
if(r->contentlen) httpsrv_drain(param, r->contentlen);
|
if(r->contentlen) httpsrv_drain(param, r->contentlen);
|
||||||
r->drained = 1;
|
r->drained = 1;
|
||||||
}
|
}
|
||||||
|
/* 10: a limit of the service was exceeded, which the other
|
||||||
|
services answer with 503. */
|
||||||
|
if(i == 10){
|
||||||
|
static const char body[] = "exceeded your limits\n";
|
||||||
|
|
||||||
|
r->hdrs = NULL;
|
||||||
|
r->maxage = -1;
|
||||||
|
r->keepalive = 0;
|
||||||
|
if(httpsrv_head(r, 503, "text/plain", (int64_t)sizeof(body) - 1, NULL)) return 1;
|
||||||
|
httpsrv_send(r, body, (int)sizeof(body) - 1);
|
||||||
|
}
|
||||||
/* 4 no credentials, 5 unknown user, 6 wrong password: all of them
|
/* 4 no credentials, 5 unknown user, 6 wrong password: all of them
|
||||||
should let the client offer credentials again. */
|
should let the client offer credentials again. */
|
||||||
if(i >= 4 && i <= 6) op_authrequired(r);
|
else if(i >= 4 && i <= 6) op_authrequired(r);
|
||||||
else op_forbidden(r);
|
else op_forbidden(r);
|
||||||
RETURN(i);
|
RETURN(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -555,7 +555,7 @@ static void cbfail(struct cbmap *m, int side, int writing){
|
|||||||
/* Statistics of what went through a way, as sockmap() counts them, and
|
/* Statistics of what went through a way, as sockmap() counts them, and
|
||||||
the bandwidth limits' pause: the client's data once written to the
|
the bandwidth limits' pause: the client's data once written to the
|
||||||
server, the server's once read. A read counts for the grace. */
|
server, the server's once read. A read counts for the grace. */
|
||||||
static void cbcount(struct cbmap *m, struct cbway *w, int written, ssize_t n){
|
static void cbcount(struct cbmap *m, struct cbway *w, int written, SOCKRET n){
|
||||||
struct clientparam *param = m->param;
|
struct clientparam *param = m->param;
|
||||||
int sl = 0;
|
int sl = 0;
|
||||||
|
|
||||||
@ -603,7 +603,7 @@ static int cbway(struct cbmap *m, struct cbway *w){
|
|||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned *inbuf, *offset, size;
|
unsigned *inbuf, *offset, size;
|
||||||
uint64_t inb, room;
|
uint64_t inb, room;
|
||||||
ssize_t n;
|
SOCKRET n;
|
||||||
|
|
||||||
if(!w->left) return 0;
|
if(!w->left) return 0;
|
||||||
cbbuf(param, w->src, &buf, &inbuf, &offset, &size);
|
cbbuf(param, w->src, &buf, &inbuf, &offset, &size);
|
||||||
|
|||||||
54
src/pcre.c
54
src/pcre.c
@ -220,6 +220,14 @@ struct pcre_filter_data {
|
|||||||
struct ace *acl;
|
struct ace *acl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* What a connection matches with: pcre2_match() writes into its match
|
||||||
|
data, so a thread matching on the rule's own one would race every
|
||||||
|
other thread doing the same. */
|
||||||
|
struct pcre_client_data {
|
||||||
|
struct pcre_filter_data *pcrefd;
|
||||||
|
pcre2_match_data * match_data;
|
||||||
|
};
|
||||||
|
|
||||||
static void pcre_data_free(struct pcre_filter_data *pcrefd){
|
static void pcre_data_free(struct pcre_filter_data *pcrefd){
|
||||||
_3proxy_mutex_lock(&pcre_mutex);
|
_3proxy_mutex_lock(&pcre_mutex);
|
||||||
pcrefd->users--;
|
pcrefd->users--;
|
||||||
@ -253,16 +261,31 @@ static void* pcre_filter_open(void * idata, struct srvparam * param){
|
|||||||
static FILTER_ACTION pcre_filter_client(void *fo, struct clientparam * param, void** fc){
|
static FILTER_ACTION pcre_filter_client(void *fo, struct clientparam * param, void** fc){
|
||||||
int res;
|
int res;
|
||||||
struct ace tmpace;
|
struct ace tmpace;
|
||||||
|
struct pcre_filter_data *rule = (struct pcre_filter_data *)fo;
|
||||||
|
struct pcre_client_data *pcd;
|
||||||
|
|
||||||
*fc = fo;
|
*fc = NULL;
|
||||||
if(!fo) return PASS;
|
if(!fo) return PASS;
|
||||||
#define pcrefd ((struct pcre_filter_data *)fo)
|
if(rule->acl){
|
||||||
if(!pcrefd->acl) return CONTINUE;
|
memset (&tmpace, 0, sizeof(struct ace));
|
||||||
memset (&tmpace, 0, sizeof(struct ace));
|
tmpace.src = rule->acl->src;
|
||||||
tmpace.src = pcrefd->acl->src;
|
res = pl->ACLMatches(&tmpace, param);
|
||||||
res = pl->ACLMatches(&tmpace, param);
|
if(!res) return PASS;
|
||||||
#undef pcrefd
|
}
|
||||||
return (res)? CONTINUE:PASS;
|
/* the connection goes on with a match data of its own */
|
||||||
|
if(!(pcd = pl->mallocfunc(sizeof(struct pcre_client_data)))){
|
||||||
|
*fc = NULL;
|
||||||
|
return rule->action;
|
||||||
|
}
|
||||||
|
pcd->pcrefd = rule;
|
||||||
|
pcd->match_data = NULL;
|
||||||
|
if(rule->re && !(pcd->match_data = pcre2_match_data_create_from_pattern(rule->re, NULL))){
|
||||||
|
pl->freefunc(pcd);
|
||||||
|
*fc = NULL;
|
||||||
|
return rule->action;
|
||||||
|
}
|
||||||
|
*fc = pcd;
|
||||||
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What a rewritten buffer keeps free for its caller to append to. */
|
/* What a rewritten buffer keeps free for its caller to append to. */
|
||||||
@ -278,7 +301,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
char * tmpbuf, *target, *newbuf;
|
char * tmpbuf, *target, *newbuf;
|
||||||
unsigned char *given = *buf_p;
|
unsigned char *given = *buf_p;
|
||||||
int nreplaces=0;
|
int nreplaces=0;
|
||||||
#define pcrefd ((struct pcre_filter_data *)fc)
|
struct pcre_client_data *pcd = (struct pcre_client_data *)fc;
|
||||||
|
#define pcrefd (pcd->pcrefd)
|
||||||
|
|
||||||
for(acl = pcrefd->acl; acl; acl=acl->next){
|
for(acl = pcrefd->acl; acl; acl=acl->next){
|
||||||
if(pl->ACLMatches(acl, param)){
|
if(pl->ACLMatches(acl, param)){
|
||||||
@ -291,9 +315,9 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
for(; offset < *length_p; nreplaces++){
|
for(; offset < *length_p; nreplaces++){
|
||||||
int repsz;
|
int repsz;
|
||||||
|
|
||||||
count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcrefd->match_data, pcrefd->match_context);
|
count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcd->match_data, pcrefd->match_context);
|
||||||
if(count <= 0) break;
|
if(count <= 0) break;
|
||||||
ovector = pcre2_get_ovector_pointer(pcrefd->match_data);
|
ovector = pcre2_get_ovector_pointer(pcd->match_data);
|
||||||
if(ovector[0] > (PCRE2_SIZE)*length_p || ovector[1] > (PCRE2_SIZE)*length_p || ovector[1] < ovector[0]) break;
|
if(ovector[0] > (PCRE2_SIZE)*length_p || ovector[1] > (PCRE2_SIZE)*length_p || ovector[1] < ovector[0]) break;
|
||||||
if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action;
|
if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action;
|
||||||
|
|
||||||
@ -379,7 +403,13 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
#undef pcrefd
|
#undef pcrefd
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcre_filter_clear(void *fo){
|
static void pcre_filter_clear(void *fc){
|
||||||
|
struct pcre_client_data *pcd = (struct pcre_client_data *)fc;
|
||||||
|
|
||||||
|
if(pcd){
|
||||||
|
if(pcd->match_data) pcre2_match_data_free(pcd->match_data);
|
||||||
|
pl->freefunc(pcd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pcre_filter_close(void *fo){
|
static void pcre_filter_close(void *fo){
|
||||||
|
|||||||
@ -62,6 +62,7 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#define SASIZETYPE int
|
#define SASIZETYPE int
|
||||||
|
#define SOCKRET int /* what a socket call returns: moved bytes or -1 */
|
||||||
#define SHUT_RDWR SD_BOTH
|
#define SHUT_RDWR SD_BOTH
|
||||||
#define SHUT_WR SD_SEND
|
#define SHUT_WR SD_SEND
|
||||||
#define SHUT_RD SD_RECEIVE
|
#define SHUT_RD SD_RECEIVE
|
||||||
|
|||||||
@ -35,6 +35,7 @@ extern "C" {
|
|||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#endif
|
#endif
|
||||||
#define SASIZETYPE socklen_t
|
#define SASIZETYPE socklen_t
|
||||||
|
#define SOCKRET ssize_t /* what a socket call returns: moved bytes or -1 */
|
||||||
#define SOCKET int
|
#define SOCKET int
|
||||||
#define INVALID_SOCKET (-1)
|
#define INVALID_SOCKET (-1)
|
||||||
#define _3proxy_mutex_t pthread_mutex_t
|
#define _3proxy_mutex_t pthread_mutex_t
|
||||||
|
|||||||
@ -224,6 +224,7 @@ int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * sn
|
|||||||
else if(type == 2){
|
else if(type == 2){
|
||||||
offset += 3;
|
offset += 3;
|
||||||
}
|
}
|
||||||
|
if((offset + 2) > len) return -6;
|
||||||
elen = size16(hello+offset);
|
elen = size16(hello+offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if(elen+offset != len) return -9;
|
if(elen+offset != len) return -9;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user