libzypp 17.37.10

proxyinfolibproxy.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include <zypp-core/AutoDispose.h>
14#include <iostream>
15#include <optional>
16#include <cstdlib>
17
18#include <zypp-core/base/Logger.h>
19#include <zypp-core/base/String.h>
20#include <zypp-core/fs/WatchFile>
21#include <zypp-core/Pathname.h>
22
23#include <zypp-curl/proxyinfo/ProxyInfoLibproxy>
24
25#include <dlfcn.h> // for dlload, dlsym, dlclose
26#include <glib.h> // g_clear_pointer and g_strfreev
27
28 using std::endl;
29 using namespace zypp::base;
30
31 namespace zypp {
32 namespace env {
33 inline bool inYAST()
34 {
35 static const bool _inYAST { ::getenv("YAST_IS_RUNNING") };
36 return _inYAST;
37 }
38 }
39
40 namespace media {
41
42 namespace {
43
44 using CreateFactoryCb = CreateFactorySig<pxProxyFactoryType>;
45 using DelFactoryCb = DelFactorySig<pxProxyFactoryType>;
46 using GetProxiesCb = GetProxiesSig<pxProxyFactoryType>;
47
48 struct LibProxyAPI
49 {
50 zypp::AutoDispose<void *> libProxyLibHandle;
51 CreateFactoryCb createProxyFactory = nullptr;
52 DelFactoryCb deleteProxyFactory = nullptr;
53 GetProxiesCb getProxies = nullptr;
54 FreeProxiesCb freeProxies = nullptr;
55
61 static void fallbackFreeProxies( char **proxies ) {
62 g_clear_pointer (&proxies, g_strfreev);
63 }
64
65 static std::unique_ptr<LibProxyAPI> create() {
66 MIL << "Detecting libproxy availability" << std::endl;
67 zypp::AutoDispose<void *> handle( dlopen("libproxy.so.1", RTLD_LAZY ), []( void *ptr ){ if ( ptr ) ::dlclose(ptr); });
68 if ( !handle ) {
69 MIL << "No libproxy support detected (could not load library): " << dlerror() << std::endl;
70 return nullptr;
71 }
72
73 std::unique_ptr<LibProxyAPI> apiInstance = std::make_unique<LibProxyAPI>();
74 apiInstance->libProxyLibHandle = std::move(handle);
75 apiInstance->createProxyFactory = (CreateFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_new" );
76 if ( !apiInstance->createProxyFactory ){
77 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_new): " << dlerror() << std::endl;
78 return nullptr;
79 }
80 apiInstance->deleteProxyFactory = (DelFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free" );
81 if ( !apiInstance->deleteProxyFactory ){
82 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_free): " << dlerror() << std::endl;
83 return nullptr;
84 }
85 apiInstance->getProxies = (GetProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_get_proxies" );
86 if ( !apiInstance->getProxies ){
87 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_get_proxies): " << dlerror() << std::endl;
88 return nullptr;
89 }
90 apiInstance->freeProxies = (FreeProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free_proxies" );
91 if ( !apiInstance->freeProxies ){
92 MIL << "Older version of libproxy detected, using fallback function to free the proxy list (could not resolve px_proxy_factory_free_proxies): " << dlerror() << std::endl;
93 apiInstance->freeProxies = &fallbackFreeProxies;
94 }
95
96 MIL << "Libproxy is available" << std::endl;
97 return apiInstance;
98 }
99 };
100
101 LibProxyAPI *proxyApi() {
102 static std::unique_ptr<LibProxyAPI> api = LibProxyAPI::create();
103 return api.get();
104 }
105
106 LibProxyAPI &assertProxyApi() {
107 auto api = proxyApi();
108 if ( !api )
109 ZYPP_THROW( zypp::Exception("LibProxyAPI is not available.") );
110 return *api;
111 }
112 }
113
114 struct TmpUnsetEnv
115 {
116 TmpUnsetEnv(const char *var_r) : _set(false), _var(var_r) {
117 const char * val = getenv( _var.c_str() );
118 if ( val )
119 {
120 _set = true;
121 _val = val;
122 ::unsetenv( _var.c_str() );
123 }
124 }
125
126 TmpUnsetEnv(const TmpUnsetEnv &) = delete;
127 TmpUnsetEnv(TmpUnsetEnv &&) = delete;
128 TmpUnsetEnv &operator=(const TmpUnsetEnv &) = delete;
129 TmpUnsetEnv &operator=(TmpUnsetEnv &&) = delete;
130
131 ~TmpUnsetEnv()
132 {
133 if ( _set )
134 {
135 setenv( _var.c_str(), _val.c_str(), 1 );
136 }
137 }
138
139 bool _set;
140 std::string _var;
141 std::string _val;
142 };
143
144 static pxProxyFactoryType * getProxyFactory()
145 {
146 static pxProxyFactoryType * proxyFactory = 0;
147
148 // Force libproxy into using "/etc/sysconfig/proxy"
149 // if it exists.
150 static WatchFile sysconfigProxy( "/etc/sysconfig/proxy", WatchFile::NO_INIT );
151 if ( sysconfigProxy.hasChanged() )
152 {
153 MIL << "Build Libproxy Factory from /etc/sysconfig/proxy" << endl;
154 if ( proxyFactory )
155 assertProxyApi().deleteProxyFactory( proxyFactory );
156
157 TmpUnsetEnv envguard[] __attribute__ ((__unused__)) = { "KDE_FULL_SESSION", "GNOME_DESKTOP_SESSION_ID", "DESKTOP_SESSION" };
158 proxyFactory = assertProxyApi().createProxyFactory();
159 }
160 else if ( ! proxyFactory )
161 {
162 MIL << "Build Libproxy Factory" << endl;
163 proxyFactory = assertProxyApi().createProxyFactory();
164 }
165
166 return proxyFactory;
167 }
168
169 ProxyInfoLibproxy::ProxyInfoLibproxy()
170 : ProxyInfo::Impl()
171 , _factory( getProxyFactory())
172 {
173 _enabled = !(_factory == NULL);
174 }
175
176 ProxyInfoLibproxy::~ProxyInfoLibproxy()
177 {}
178
179 bool ProxyInfoLibproxy::isAvailabe()
180 {
181 return ( proxyApi () != nullptr );
182 }
183
184 std::string ProxyInfoLibproxy::proxy(const Url & url_r) const
185 {
186 if (!_enabled)
187 return "";
188
189 const url::ViewOption vopt =
190 url::ViewOption::WITH_SCHEME
191 + url::ViewOption::WITH_HOST
192 + url::ViewOption::WITH_PORT
193 + url::ViewOption::WITH_PATH_NAME;
194
195 auto &api = assertProxyApi ();
196
197 zypp::AutoDispose<char **> proxies(
198 api.getProxies(_factory, url_r.asString(vopt).c_str())
199 , api.freeProxies
200 );
201 if ( !proxies.value() )
202 return "";
203
204 // bsc#1244710: libproxy appears to return /etc/sysconfig/proxy
205 // values after $*_proxy environment variables.
206 // In YAST, e.g after changing the proxy settings, we'd like
207 // /etc/sysconfig/proxy changes to take effect immediately.
208 // So we pick the last one matching our schema.
209 const std::string myschema { url_r.getScheme()+":" };
210 std::optional<std::string> result;
211 for ( int i = 0; proxies[i]; ++i ) {
212 if ( str::hasPrefix( proxies[i], myschema ) ) {
213 result = str::asString( proxies[i] );
214 if ( not env::inYAST() )
215 break;
216 }
217 }
218
219 return result.value_or( "" );
220 }
221
222 ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyBegin() const
223 { return _no_proxy.begin(); }
224
225 ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyEnd() const
226 { return _no_proxy.end(); }
227
228 } // namespace media
229} // namespace zypp
zypp::AutoDispose
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
zypp::AutoDispose::value
reference value() const
Reference to the Tp object.
Definition AutoDispose.h:138
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::Url::getScheme
std::string getScheme() const
Returns the scheme name of the URL.
Definition Url.cc:551
zypp::Url::asString
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:515
zypp::WatchFile
Remember a files attributes to detect content changes.
Definition watchfile.h:50
zypp::WatchFile::hasChanged
bool hasChanged()
Definition watchfile.h:80
zypp::WatchFile::NO_INIT
@ NO_INIT
Definition watchfile.h:52
zypp::media::ProxyInfoLibproxy::_enabled
DefaultIntegral< bool, false > _enabled
Definition proxyinfolibproxy.h:61
zypp::media::ProxyInfoLibproxy::_factory
pxProxyFactoryType * _factory
Definition proxyinfolibproxy.h:63
zypp::media::ProxyInfoLibproxy::noProxyBegin
ProxyInfo::NoProxyIterator noProxyBegin() const override
Definition proxyinfolibproxy.cc:222
zypp::media::ProxyInfoLibproxy::~ProxyInfoLibproxy
~ProxyInfoLibproxy() override
Definition proxyinfolibproxy.cc:176
zypp::media::ProxyInfoLibproxy::ProxyInfoLibproxy
ProxyInfoLibproxy()
Definition proxyinfolibproxy.cc:169
zypp::media::ProxyInfoLibproxy::proxy
std::string proxy(const Url &url_r) const override
Definition proxyinfolibproxy.cc:184
zypp::media::ProxyInfoLibproxy::noProxyEnd
ProxyInfo::NoProxyIterator noProxyEnd() const override
Definition proxyinfolibproxy.cc:225
zypp::media::ProxyInfoLibproxy::_no_proxy
ProxyInfo::NoProxyList _no_proxy
Definition proxyinfolibproxy.h:62
zypp::media::ProxyInfoLibproxy::isAvailabe
static bool isAvailabe()
Definition proxyinfolibproxy.cc:179
zypp::media::ProxyInfo
Definition proxyinfo.h:30
zypp::media::ProxyInfo::NoProxyIterator
std::list< std::string >::const_iterator NoProxyIterator
Definition proxyinfo.h:35
zypp::base
Definition Random.cc:7
zypp::env
Namespace intended to collect all environment variables we use.
Definition Env.h:25
zypp::env::inYAST
bool inYAST()
Definition proxyinfolibproxy.cc:33
zypp::media
Definition MediaNetworkRequestExecutor.h:22
zypp::media::GetProxiesSig
char **(*)(ProxyFactoryType *self, const char *url) GetProxiesSig
Definition proxyinfolibproxy.h:35
zypp::media::DelFactorySig
void(*)(ProxyFactoryType *self) DelFactorySig
Definition proxyinfolibproxy.h:32
zypp::media::FreeProxiesCb
void(*)(char **proxies) FreeProxiesCb
Definition proxyinfolibproxy.h:37
zypp::media::CreateFactorySig
ProxyFactoryType *(*)(void) CreateFactorySig
Definition proxyinfolibproxy.h:29
zypp::media::getProxyFactory
static pxProxyFactoryType * getProxyFactory()
Definition proxyinfolibproxy.cc:144
zypp::str::asString
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition String.h:140
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1097
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition Application.cc:20
pxProxyFactoryType
struct _pxProxyFactory pxProxyFactoryType
Definition proxyinfolibproxy.h:22
zypp::media::ProxyInfo::Impl::Impl
Impl()
Ctor.
Definition proxyinfoimpl.h:28
zypp::media::TmpUnsetEnv
Definition proxyinfolibproxy.cc:115
zypp::media::TmpUnsetEnv::_val
std::string _val
Definition proxyinfolibproxy.cc:141
zypp::media::TmpUnsetEnv::TmpUnsetEnv
TmpUnsetEnv(TmpUnsetEnv &&)=delete
zypp::media::TmpUnsetEnv::TmpUnsetEnv
TmpUnsetEnv(const char *var_r)
Definition proxyinfolibproxy.cc:116
zypp::media::TmpUnsetEnv::_set
bool _set
Definition proxyinfolibproxy.cc:139
zypp::media::TmpUnsetEnv::operator=
TmpUnsetEnv & operator=(const TmpUnsetEnv &)=delete
zypp::media::TmpUnsetEnv::operator=
TmpUnsetEnv & operator=(TmpUnsetEnv &&)=delete
zypp::media::TmpUnsetEnv::TmpUnsetEnv
TmpUnsetEnv(const TmpUnsetEnv &)=delete
zypp::media::TmpUnsetEnv::_var
std::string _var
Definition proxyinfolibproxy.cc:140
zypp::media::TmpUnsetEnv::~TmpUnsetEnv
~TmpUnsetEnv()
Definition proxyinfolibproxy.cc:131
zypp::url::ViewOption
Url::asString() view options.
Definition UrlBase.h:41
AutoDispose.h
Pathname.h
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
Logger.h
MIL
#define MIL
Definition Logger.h:100
ERR
#define ERR
Definition Logger.h:102
String.h