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
|
||||
}
|
||||
if(!strncmp(path, "./", 2) || !strncmp(path, "../", 3)) return 1;
|
||||
if(strstr(path, "/./") || strstr(path, "/../")) return 1;
|
||||
if(strstr(path, "\\.\\") || strstr(path, "\\..\\")) return 1;
|
||||
/* a dot-dot segment, with either separator, wherever it is in the
|
||||
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);
|
||||
if(p - path >= 2 && !strcmp(p - 2, "/.")) return 1;
|
||||
if(p - path >= 3 && !strcmp(p - 3, "/..")) return 1;
|
||||
if(p - path >= 2 && (!strcmp(p - 2, "/.") || !strcmp(p - 2, "\\."))) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1462,16 +1463,27 @@ static int httpsrv_request(struct clientparam *param, struct httpreq *r)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(i && i != 10){
|
||||
if(i){
|
||||
/* 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. */
|
||||
if(!r->drained){
|
||||
if(r->contentlen) httpsrv_drain(param, r->contentlen);
|
||||
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
|
||||
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);
|
||||
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
|
||||
the bandwidth limits' pause: the client's data once written to the
|
||||
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;
|
||||
int sl = 0;
|
||||
|
||||
@ -603,7 +603,7 @@ static int cbway(struct cbmap *m, struct cbway *w){
|
||||
unsigned char *buf;
|
||||
unsigned *inbuf, *offset, size;
|
||||
uint64_t inb, room;
|
||||
ssize_t n;
|
||||
SOCKRET n;
|
||||
|
||||
if(!w->left) return 0;
|
||||
cbbuf(param, w->src, &buf, &inbuf, &offset, &size);
|
||||
|
||||
50
src/pcre.c
50
src/pcre.c
@ -220,6 +220,14 @@ struct pcre_filter_data {
|
||||
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){
|
||||
_3proxy_mutex_lock(&pcre_mutex);
|
||||
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){
|
||||
int res;
|
||||
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;
|
||||
#define pcrefd ((struct pcre_filter_data *)fo)
|
||||
if(!pcrefd->acl) return CONTINUE;
|
||||
if(rule->acl){
|
||||
memset (&tmpace, 0, sizeof(struct ace));
|
||||
tmpace.src = pcrefd->acl->src;
|
||||
tmpace.src = rule->acl->src;
|
||||
res = pl->ACLMatches(&tmpace, param);
|
||||
#undef pcrefd
|
||||
return (res)? CONTINUE:PASS;
|
||||
if(!res) return 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. */
|
||||
@ -278,7 +301,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
||||
char * tmpbuf, *target, *newbuf;
|
||||
unsigned char *given = *buf_p;
|
||||
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){
|
||||
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++){
|
||||
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;
|
||||
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(!(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
|
||||
}
|
||||
|
||||
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){
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#define SASIZETYPE int
|
||||
#define SOCKRET int /* what a socket call returns: moved bytes or -1 */
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#define SHUT_WR SD_SEND
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
|
||||
@ -35,6 +35,7 @@ extern "C" {
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#define SASIZETYPE socklen_t
|
||||
#define SOCKRET ssize_t /* what a socket call returns: moved bytes or -1 */
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET (-1)
|
||||
#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){
|
||||
offset += 3;
|
||||
}
|
||||
if((offset + 2) > len) return -6;
|
||||
elen = size16(hello+offset);
|
||||
offset += 2;
|
||||
if(elen+offset != len) return -9;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user