From b615fe30b9f85cde24a548c9ba9a25539c0f6934 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Thu, 2 Jul 2026 16:24:02 +0100 Subject: [PATCH] configurable request header for determining peer --- src/chttpd/src/chttpd.erl | 28 ++++++++++++++++++++++++++-- src/chttpd/src/chttpd_external.erl | 2 +- src/couch/src/couch_auth_lockout.erl | 13 ++----------- src/couch/src/couch_httpd.erl | 13 +++++++++++++ src/couch/src/couch_httpd_auth.erl | 10 ++++------ 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl index 485e012c2cb..b7ae2753ea3 100644 --- a/src/chttpd/src/chttpd.erl +++ b/src/chttpd/src/chttpd.erl @@ -64,7 +64,8 @@ send_redirect/2, send_chunked_error/2, send_json/2, send_json/3, send_json/4, - validate_ctype/2 + validate_ctype/2, + peer/1 ]). -export([authenticate_request/3]). @@ -266,7 +267,7 @@ handle_request_int(MochiReq) -> P end, - Peer = MochiReq:get(peer), + Peer = peer(MochiReq), Method1 = case MochiReq:get(method) of @@ -840,6 +841,29 @@ body(#httpd{mochi_req = MochiReq, req_body = ReqBody}) -> validate_ctype(Req, Ctype) -> couch_httpd:validate_ctype(Req, Ctype). +peer(#httpd{} = Req) -> + peer(Req#httpd.mochi_req); +peer(MochiReq) -> + case config:get("chttpd", "peer_header") of + undefined -> + peer_from_socket(MochiReq); + PeerHeader -> + case MochiReq:get_header_value(PeerHeader) of + undefined -> + peer_from_socket(MochiReq); + Peer -> + Peer + end + end. + +peer_from_socket(MochiReq) -> + case MochiReq:get(socket) of + {remote, _Pid, _} -> + nopeer; + _ -> + MochiReq:get(peer) + end. + json_body(#httpd{} = Httpd) -> json_body(Httpd, []). diff --git a/src/chttpd/src/chttpd_external.erl b/src/chttpd/src/chttpd_external.erl index fe63de3b220..b57c42c56f1 100644 --- a/src/chttpd/src/chttpd_external.erl +++ b/src/chttpd/src/chttpd_external.erl @@ -93,7 +93,7 @@ json_req_obj_field(<<"body">>, #httpd{req_body = undefined, mochi_req = Req}, _D json_req_obj_field(<<"body">>, #httpd{req_body = Body}, _Db, _DocId) -> Body; json_req_obj_field(<<"peer">>, #httpd{peer = undefined, mochi_req = Req}, _, _) -> - ?l2b(Req:get(peer)); + ?l2b(chttpd:peer(Req)); json_req_obj_field(<<"peer">>, #httpd{peer = Peer}, _Db, _DocId) -> ?l2b(Peer); json_req_obj_field(<<"form">>, #httpd{mochi_req = Req, method = Method} = HttpReq, Db, DocId) -> diff --git a/src/couch/src/couch_auth_lockout.erl b/src/couch/src/couch_auth_lockout.erl index ceed57f113c..63fdabd7b5b 100644 --- a/src/couch/src/couch_auth_lockout.erl +++ b/src/couch/src/couch_auth_lockout.erl @@ -27,7 +27,7 @@ is_locked_out(#httpd{} = Req, UserName, UserSalt) -> is_locked_out_int(#httpd{} = Req, Mode, UserName, UserSalt) -> LockoutThreshold = lockout_threshold(), - case peer(Req) of + case Req#httpd.peer of nopeer -> false; Peer -> @@ -48,7 +48,7 @@ is_locked_out_int(#httpd{} = Req, Mode, UserName, UserSalt) -> end. lockout(#httpd{} = Req, UserName, UserSalt) -> - case peer(Req) of + case Req#httpd.peer of nopeer -> ok; Peer -> @@ -74,12 +74,3 @@ lockout_mode() -> lockout_threshold() -> config:get_integer("chttpd_auth_lockout", "threshold", 5). - -peer(#httpd{mochi_req = MochiReq}) -> - Socket = mochiweb_request:get(socket, MochiReq), - case Socket of - {remote, _Pid, _Ref} -> - nopeer; - _ -> - mochiweb_request:get(peer, MochiReq) - end. diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl index 5253e4d3cd2..ce7179ee2ed 100644 --- a/src/couch/src/couch_httpd.erl +++ b/src/couch/src/couch_httpd.erl @@ -1425,6 +1425,19 @@ http_respond_(#httpd{mochi_req = MochiReq}, Code, Headers, Args, Type) -> MochiReq:Type({Code, Headers, Args}). peer(MochiReq) -> + case config:get("chttpd", "peer_header") of + undefined -> + peer_from_socket(MochiReq); + PeerHeader -> + case MochiReq:get_header_value(PeerHeader) of + undefined -> + peer_from_socket(MochiReq); + Peer -> + Peer + end + end. + +peer_from_socket(MochiReq) -> case MochiReq:get(socket) of {remote, Pid, _} -> node(Pid); diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl index 3779be66bcf..ba26ef50c32 100644 --- a/src/couch/src/couch_httpd_auth.erl +++ b/src/couch/src/couch_httpd_auth.erl @@ -813,18 +813,16 @@ integer_to_binary(Int, Len) when is_integer(Int), is_integer(Len) -> Padded = <>, binary:part(Padded, byte_size(Padded), -Len). -authentication_warning(#httpd{mochi_req = Req}, User) -> - Peer = Req:get(peer), +authentication_warning(#httpd{} = Req, User) -> couch_log:warning( "~p: Authentication failed for user ~s from ~s", - [?MODULE, User, Peer] + [?MODULE, User, Req#httpd.peer] ). -lockout_warning(#httpd{mochi_req = Req}, User) -> - Peer = Req:get(peer), +lockout_warning(#httpd{} = Req, User) -> couch_log:warning( "~p: Authentication rejected for locked-out user ~s from ~s", - [?MODULE, User, Peer] + [?MODULE, User, Req#httpd.peer] ). -ifdef(TEST).