From: Adam Dickmeiss Date: Wed, 5 Mar 2014 17:22:23 +0000 (+0100) Subject: HTTP X-Forwarded-For/Z39.50 Client-IP support X-Git-Tag: v1.4.5~5 X-Git-Url: http://git.indexdata.com/?p=metaproxy-moved-to-github.git;a=commitdiff_plain;h=f3e215cc00b02e3d92016f095295af2ba4649e2f HTTP X-Forwarded-For/Z39.50 Client-IP support virt_db, multi: relays Z39.50 client-IP. sru_z3950: converts X-Forwarded-For header to Z39.50 client-IP. zoom: uses Client-IP or origin address (prefer Client-IP). frontend_net: Strips tcp: from peer address (so that it is no longer printed and stripped in zoom filter). z3950_client: builds client-IP list - combining immediate peer address as returned by COMSTACK and existing client-IP list (if avaiable). The Origin only printes first X-Forwarded address. --- diff --git a/include/metaproxy/origin.hpp b/include/metaproxy/origin.hpp index f902a8a..d129e71 100644 --- a/include/metaproxy/origin.hpp +++ b/include/metaproxy/origin.hpp @@ -57,6 +57,7 @@ namespace metaproxy_1 { unsigned int m_origin_id; int m_max_sockets; std::string m_custom_session; + std::string get_forward_address() const; }; } diff --git a/src/filter_frontend_net.cpp b/src/filter_frontend_net.cpp index a1e1c01..9313411 100644 --- a/src/filter_frontend_net.cpp +++ b/src/filter_frontend_net.cpp @@ -277,6 +277,12 @@ yf::FrontendNet::ZAssocChild::ZAssocChild( const char *peername = PDU_Observable->getpeername(); if (!peername) peername = "unknown"; + else + { + const char *cp = strchr(peername, ':'); + if (cp) + peername = cp + 1; + } m_origin.set_tcpip_address(std::string(peername), m_session.id()); timeout(m_p->m_session_timeout); } diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index 5f7d1b5..3b1d6f3 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #include #include @@ -444,6 +445,13 @@ void yf::Multi::Frontend::init(mp::Package &package, Z_GDU *gdu) *breq->preferredMessageSize = *req->preferredMessageSize; *breq->maximumRecordSize = *req->maximumRecordSize; + + const char *peer_name = yaz_oi_get_string_oid( + &req->otherInfo, yaz_oid_userinfo_client_ip, 1, 0); + if (peer_name) + yaz_oi_set_string_oid(&breq->otherInfo, odr, + yaz_oid_userinfo_client_ip, 1, peer_name); + ODR_MASK_SET(breq->options, Z_Options_search); ODR_MASK_SET(breq->options, Z_Options_present); ODR_MASK_SET(breq->options, Z_Options_namedResultSets); diff --git a/src/filter_sru_to_z3950.cpp b/src/filter_sru_to_z3950.cpp index fa12345..26a6ad2 100644 --- a/src/filter_sru_to_z3950.cpp +++ b/src/filter_sru_to_z3950.cpp @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #if YAZ_VERSIONL >= 0x50000 #include #endif @@ -518,6 +519,19 @@ yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, mp_util::set_vhost_otherinfo(&init_req->otherInfo, odr_en, host, 1); } + Z_GDU *zgdu_req = package.request().get(); + if (zgdu_req->which == Z_GDU_HTTP_Request) + { + Z_HTTP_Request *hreq = zgdu_req->u.HTTP_Request; + const char *peer_name = + z_HTTP_header_lookup(hreq->headers, "X-Forwarded-For"); + if (peer_name) + { + yaz_oi_set_string_oid(&init_req->otherInfo, odr_en, + yaz_oid_userinfo_client_ip, 1, peer_name); + } + } + z3950_package.request() = apdu; // send Z3950 package diff --git a/src/filter_virt_db.cpp b/src/filter_virt_db.cpp index 094bf08..6849917 100644 --- a/src/filter_virt_db.cpp +++ b/src/filter_virt_db.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #include #include @@ -211,6 +212,13 @@ yf::VirtualDB::BackendPtr yf::VirtualDB::Frontend::init_backend( Z_GDU *org_gdu = m_init_gdu.get(); Z_InitRequest *org_init = org_gdu->u.z3950->u.initRequest; + + const char *peer_name = yaz_oi_get_string_oid( + &org_init->otherInfo, yaz_oid_userinfo_client_ip, 1, 0); + if (peer_name) + yaz_oi_set_string_oid(&init_apdu->u.initRequest->otherInfo, odr, + yaz_oid_userinfo_client_ip, 1, peer_name); + req->idAuthentication = org_init->idAuthentication; req->implementationId = org_init->implementationId; req->implementationName = org_init->implementationName; diff --git a/src/filter_z3950_client.cpp b/src/filter_z3950_client.cpp index 12fcb8c..6ea58e4 100644 --- a/src/filter_z3950_client.cpp +++ b/src/filter_z3950_client.cpp @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #include #include @@ -486,6 +487,8 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package, if (gdu->u.z3950->which == Z_APDU_close) c->m_has_closed = true; + Z_APDU *apdu = gdu->u.z3950; + // prepare connect c->m_time_elapsed = 0; c->m_waiting = true; @@ -510,7 +513,27 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package, { return; } - + const char *peer_name2 = package.origin().get_address().c_str(); + mp::odr odr; + if (apdu->which == Z_APDU_initRequest && peer_name2) + { + Z_OtherInformation **oi = &apdu->u.initRequest->otherInfo; + char *peer_name1 = + yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 1); + char *pcomb = (char *) + odr_malloc(odr, (peer_name1 ? strlen(peer_name1) : 0) + + strlen(peer_name2) + 4); + strcpy(pcomb, ""); + if (peer_name1) + { + strcat(pcomb, peer_name1); + strcat(pcomb, ", "); + } + strcat(pcomb, peer_name2); + yaz_oi_set_string_oid(&apdu->u.initRequest->otherInfo, + odr, yaz_oid_userinfo_client_ip, + 1, pcomb); + } // prepare response c->m_time_elapsed = 0; c->m_waiting = true; diff --git a/src/filter_zoom.cpp b/src/filter_zoom.cpp index 968b96b..2062b1c 100644 --- a/src/filter_zoom.cpp +++ b/src/filter_zoom.cpp @@ -51,6 +51,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include namespace mp = metaproxy_1; namespace yf = mp::filter; @@ -2614,8 +2615,13 @@ void yf::Zoom::Frontend::auth(mp::Package &package, Z_InitRequest *req, } } - std::string ip = package.origin().get_address(); - yaz_log(YLOG_LOG, "IP=%s", ip.c_str()); + Z_OtherInformation **oi = &req->otherInfo; + const char *ip = + yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 0); + if (!ip) + ip = package.origin().get_address().c_str(); + + yaz_log(YLOG_LOG, "IP=%s", ip); std::string torus_query; int failure_code; @@ -2628,13 +2634,8 @@ void yf::Zoom::Frontend::auth(mp::Package &package, Z_InitRequest *req, } else { - const char *ip_cstr = ip.c_str(); - const char *cp = strchr(ip_cstr, ':'); - if (cp) - ip_cstr = cp + 1; - torus_query = "ip encloses/net.ipaddress \""; - torus_query += escape_cql_term(std::string(ip_cstr)); + torus_query += escape_cql_term(std::string(ip)); torus_query += "\""; failure_code = YAZ_BIB1_INIT_AC_BLOCKED_NETWORK_ADDRESS; } diff --git a/src/origin.cpp b/src/origin.cpp index 8f150b1..e4f9415 100644 --- a/src/origin.cpp +++ b/src/origin.cpp @@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "config.hpp" #include - +#include #include namespace mp = metaproxy_1; @@ -39,7 +39,15 @@ int mp::Origin::get_max_sockets() void mp::Origin::set_tcpip_address(std::string addr, unsigned long s) { + // assume first call is immediate reverse IP: cs_addrstr(COMSTACK) + // 2nd call might be X-Forwarded .. we use that for logging + std::string tmp = m_address; m_address = addr; + if (tmp.length()) + { + m_address.append(" "); + m_address.append(tmp); + } m_origin_id = s; } @@ -48,15 +56,33 @@ void mp::Origin::set_custom_session(const std::string &s) m_custom_session = s; } +std::string mp::Origin::get_forward_address() const +{ + // return first component of address + // That's either first part of X-Forwarded component + size_t pos = m_address.find(' '); + if (pos != std::string::npos) + return m_address.substr(0, pos); + else + return m_address; +} + std::string mp::Origin::get_address() { - return m_address; + // return last component of address + size_t pos = m_address.rfind(' '); + if (pos != std::string::npos) + return m_address.substr(pos + 1); + else + return m_address; } std::ostream& std::operator<<(std::ostream& os, const mp::Origin& o) { - if (o.m_address.length()) - os << o.m_address; + // print first component of address + std::string a = o.get_forward_address(); + if (a.length()) + os << a; else os << "0"; os << ":" << o.m_origin_id;