mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-16 06:05:50 +08:00
Compare commits
2 Commits
9a2351abeb
...
5babf687f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5babf687f6 | ||
|
|
3894d25a02 |
@ -1618,6 +1618,23 @@ void * httpsrvchild(struct clientparam *param)
|
|||||||
r.lasthost = lasthost;
|
r.lasthost = lasthost;
|
||||||
param->res = 0;
|
param->res = 0;
|
||||||
|
|
||||||
|
/* What the request brought belongs to it alone. A connection
|
||||||
|
can carry a client's request after another's, as a reverse
|
||||||
|
proxy reuses its upstreams, so the credentials and the host
|
||||||
|
of an earlier request decide nothing for this one. */
|
||||||
|
if(param->username){
|
||||||
|
free(param->username);
|
||||||
|
param->username = NULL;
|
||||||
|
}
|
||||||
|
if(param->password){
|
||||||
|
free(param->password);
|
||||||
|
param->password = NULL;
|
||||||
|
}
|
||||||
|
if(param->hostname){
|
||||||
|
free(param->hostname);
|
||||||
|
param->hostname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
answered = httpsrv_request(param, &r);
|
answered = httpsrv_request(param, &r);
|
||||||
handoff = r.handoff;
|
handoff = r.handoff;
|
||||||
if(r.raw) free(r.raw);
|
if(r.raw) free(r.raw);
|
||||||
|
|||||||
21
src/proxy.c
21
src/proxy.c
@ -340,6 +340,27 @@ for(;;){
|
|||||||
clhdrofs_req = -1;
|
clhdrofs_req = -1;
|
||||||
param->nolongdatfilter = 0;
|
param->nolongdatfilter = 0;
|
||||||
|
|
||||||
|
/* What the request brought belongs to it alone. A connection can carry
|
||||||
|
a request after another's, so the credentials of an earlier request
|
||||||
|
decide nothing for this one. */
|
||||||
|
if(param->username){
|
||||||
|
free(param->username);
|
||||||
|
param->username = NULL;
|
||||||
|
}
|
||||||
|
if(param->password){
|
||||||
|
free(param->password);
|
||||||
|
param->password = NULL;
|
||||||
|
}
|
||||||
|
param->pwtype = 0;
|
||||||
|
if(param->extusername){
|
||||||
|
free(param->extusername);
|
||||||
|
param->extusername = NULL;
|
||||||
|
}
|
||||||
|
if(param->extpassword){
|
||||||
|
free(param->extpassword);
|
||||||
|
param->extpassword = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* A connection waiting a while for its next request, or a tunnel, holds
|
/* A connection waiting a while for its next request, or a tunnel, holds
|
||||||
no buffer: it is taken again once a request starts coming. */
|
no buffer: it is taken again once a request starts coming. */
|
||||||
if(buf && param->cliinbuf == param->clioffset){
|
if(buf && param->cliinbuf == param->clioffset){
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
"""Authentication and access rules in front of the HTTP server."""
|
"""Authentication and access rules in front of the HTTP server."""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
def run(t):
|
def run(t):
|
||||||
if not t.skip_unless("httpsrv"):
|
if not t.skip_unless("httpsrv"):
|
||||||
@ -49,3 +51,19 @@ def run(t):
|
|||||||
|
|
||||||
t.contains(t.http(url + "/echo", auth=("alice", "secret")), "path=/echo",
|
t.contains(t.http(url + "/echo", auth=("alice", "secret")), "path=/echo",
|
||||||
"an authenticated request is dispatched")
|
"an authenticated request is dispatched")
|
||||||
|
|
||||||
|
# --- credentials do not outlive the request that carried them ------
|
||||||
|
# A kept connection answers a second request without credentials as
|
||||||
|
# unauthenticated: a reverse proxy reuses its upstreams between
|
||||||
|
# clients, so one client's login must not open another's way in.
|
||||||
|
creds = base64.b64encode(b"alice:secret").decode()
|
||||||
|
text, closed = t.raw_session(srv,
|
||||||
|
f"GET /echo HTTP/1.1\r\nHost: t\r\n"
|
||||||
|
f"Authorization: Basic {creds}\r\n\r\n"
|
||||||
|
f"GET /echo HTTP/1.1\r\nHost: t\r\nConnection: close\r\n\r\n")
|
||||||
|
parts = text.split("HTTP/1.")
|
||||||
|
t.eq(3, len(parts), "the kept connection answers both requests")
|
||||||
|
t.eq(True, parts[1].startswith("1 200"),
|
||||||
|
"the request with credentials is allowed")
|
||||||
|
t.eq(True, parts[2].startswith("0 401"),
|
||||||
|
"the request after it, without credentials, is refused")
|
||||||
|
|||||||
@ -4,6 +4,8 @@ Access rules accumulate until "flush", so each service section here starts
|
|||||||
from a clean list.
|
from a clean list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import base64
|
||||||
|
|
||||||
|
|
||||||
def run(t):
|
def run(t):
|
||||||
if not t.skip_unless("httpsrv"):
|
if not t.skip_unless("httpsrv"):
|
||||||
@ -108,3 +110,18 @@ def run(t):
|
|||||||
t.eq(407, t.http(origin + "/echo", proxy=needs_auth,
|
t.eq(407, t.http(origin + "/echo", proxy=needs_auth,
|
||||||
proxy_auth=("alice", "wrong")).status,
|
proxy_auth=("alice", "wrong")).status,
|
||||||
"wrong proxy credentials are refused")
|
"wrong proxy credentials are refused")
|
||||||
|
|
||||||
|
# credentials do not outlive the request which carried them: a second
|
||||||
|
# request on the same connection, without them, is asked again
|
||||||
|
creds = base64.b64encode(b"alice:secret").decode()
|
||||||
|
text, closed = t.raw_session(auth,
|
||||||
|
f"GET {origin}/echo HTTP/1.1\r\nHost: 127.0.0.1:{srv}\r\n"
|
||||||
|
f"Proxy-Authorization: Basic {creds}\r\n\r\n"
|
||||||
|
f"GET {origin}/echo HTTP/1.1\r\nHost: 127.0.0.1:{srv}\r\n"
|
||||||
|
f"Connection: close\r\n\r\n")
|
||||||
|
parts = text.split("HTTP/1.")
|
||||||
|
t.eq(3, len(parts), "the kept connection answers both requests")
|
||||||
|
t.eq(True, parts[1].startswith("1 200"),
|
||||||
|
"the request with credentials is allowed")
|
||||||
|
t.eq(True, parts[2].startswith("0 407"),
|
||||||
|
"the request after it, without credentials, is refused")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user