libzypp  17.38.8
PluginSigcheck.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
11 #include <iostream>
12 #include <vector>
13 
14 #include "PluginSigcheck.h"
15 #include <zypp-core/base/StringV.h>
17 #include <zypp/PluginScript.h>
18 
19 #undef ZYPP_BASE_LOGGER_LOGGROUP
20 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
21 
22 namespace zypp
23 {
24  namespace {
25  struct ProtocolError : SigcheckPluginException {
26  ProtocolError( const PluginScript & script_r, const PluginFrame & got_r, std::string_view expected_r )
27  : SigcheckPluginException(str::sprint( script_r.script(),"protocol error: got",got_r.command(),"expected",expected_r ))
28  {
29  if ( got_r.isErrorCommand() && not got_r.body().empty() ) {
30  // An artifical limit for the exception history:
31  static constexpr size_t maxErrorMessageSize = 2048;
32  addHistory( got_r.body().asString( maxErrorMessageSize ) );
33  }
34  }
35  };
36  } // namespace
37 
42  {
43  Impl( Pathname script_r )
44  : _script( std::move(script_r) )
45  {}
46  Impl( Pathname script_r, Args args_r )
47  : _script( std::move(script_r), std::move(args_r) )
48  {}
49 
50  void launch( const Pathname & chroot_r )
51  {
52  if ( _script.isOpen() )
53  ZYPP_THROW( SigcheckPluginException(str::sprint( _script.script(),"already launched" )) );
54 
55  try {
56  _script.openChrooted( chroot_r );
57  {
58  // -> PLUGINBEGIN
59  PluginFrame frame( "PLUGINBEGIN", { {"version","0"} } );
60  _script.send( frame );
61  PluginFrame ret = _script.receive();
62  pDBG( dump(ret) );
63 
64  // <- PLUGINSETUP (optional)
65  if ( not ret.isAckCommand() ) {
66  // Optional PLUGINSETUP
67  if ( ret.command() != "PLUGINSETUP" ) {
68  ZYPP_THROW( ProtocolError( _script, ret, "PLUGINSETUP" ) );
69  }
70  if ( ret.hasKey( "sig_extension" ) )
71  _sigExtension = ret.getHeader( "sig_extension" );
72  if ( ret.hasKey( "key_extension" ) )
73  _keyExtension = ret.getHeader( "key_extension" );
74  }
75  }
76  }
77  catch( const zypp::Exception & e ) {
78  _script.close();
79  ZYPP_THROW( SigcheckPluginException(str::sprint( "failed to launch",_script.script() ), e ) );
80  }
81  }
82 
83  void sigcheck( const Pathname & data_r, const Pathname & sig_r = Pathname(), const Pathname & key_r = Pathname() ) const
84  {
85  if ( not _script.isOpen() )
87 
88  const Pathname & root { _script.getChroot() };
89  auto sanitizePath = [&root] ( const Pathname & path_r ) -> Pathname {
90  return Pathname::stripprefix( root, path_r );
91  };
92 
93  try {
94  // -> SIGCHECK
95  PluginFrame frame( "SIGCHECK" );
96  frame.addHeader( "data", sanitizePath( data_r ).asString() );
97  if ( not sig_r.empty() )
98  frame.addHeader( "sig", sanitizePath( sig_r ).asString() );
99  if ( not key_r.empty() )
100  frame.addHeader( "key", sanitizePath( key_r ).asString() );
101 
102  _script.send( frame );
103  PluginFrame ret = _script.receive();
104  pDBG( dump(ret) );
105 
106  if ( not ret.isAckCommand() ) {
107  ZYPP_THROW( ProtocolError( _script, ret, "ACK" ) );
108  }
109  }
110  catch( const zypp::Exception & e ) {
112  }
113  }
114 
116  std::string _sigExtension;
117  std::string _keyExtension;
118  };
119 
120  std::ostream & operator<<( std::ostream & str, const SigcheckPlugin::Impl & obj )
121  { return str << obj._script; }
122 
124 
126  : _pimpl { new Impl( std::move(script_r) ) }
127  {}
128 
130  : _pimpl { new Impl( std::move(script_r), std::move(args_r) ) }
131  {}
132 
133  void SigcheckPlugin::launch( const Pathname & chroot_r )
134  { return _pimpl->launch( chroot_r ); }
135 
136  std::string SigcheckPlugin::sigExtension() const
137  { return _pimpl->_sigExtension; }
138 
139  std::string SigcheckPlugin::keyExtension() const
140  { return _pimpl->_keyExtension; }
141 
142  void SigcheckPlugin::sigcheck( const Pathname & data_r, const Pathname & sig_r, const Pathname & key_r ) const
143  { return _pimpl->sigcheck( data_r, sig_r, key_r ); }
144 
145  std::ostream & operator<<( std::ostream & str, const SigcheckPlugin & obj )
146  { return str << *obj._pimpl; }
147 
149 
151  {
153  {}
154 
155  Impl( const std::string & cmdline_r, const Pathname & plugindir_r )
156  {
157  for ( std::string_view cmd : strv::splitBSEscaped( cmdline_r, ";" ) ) {
158  Pathname plugpath;
159  SigcheckPlugin::Args plugargs;
160  for ( std::string_view arg : strv::splitBSEscaped( cmd /*blank*/ ) ) {
161  if ( arg.empty() )
162  continue;
163  if ( plugpath.empty() ) {
164  plugpath = plugindir_r / "sigcheck" / strv::unBSEscape( arg );
165  } else {
166  plugargs.emplace_back( strv::unBSEscape( arg ) );
167  }
168  }
169  if ( not plugpath.empty() ) {
170  if ( plugargs.empty() )
171  _plugins.emplace_back( std::move(plugpath) );
172  else
173  _plugins.emplace_back( std::move(plugpath), std::move(plugargs) );
174  }
175  }
176  }
177 
178  explicit operator bool() const
179  { return not _plugins.empty(); }
180 
181  void launch( const Pathname & chroot_r = Pathname() )
182  { for ( auto & plugin : _plugins ) plugin.launch( chroot_r ); }
183 
185  };
186 
187  std::ostream & operator<<( std::ostream & str, const SigcheckPlugins::Impl & obj )
188  { return str << obj._plugins; }
189 
191 
193  : _pimpl { new Impl() }
194  {}
195 
196  SigcheckPlugins::SigcheckPlugins( const std::string & cmdline_r, const Pathname & plugindir_r )
197  : _pimpl { new Impl( cmdline_r, plugindir_r ) }
198  {}
199 
200  SigcheckPlugins::operator bool() const
201  { return bool(*_pimpl); }
202 
204  { return _pimpl->_plugins; }
205 
206  void SigcheckPlugins::launch( const Pathname & chroot_r )
207  { return _pimpl->launch( chroot_r ); }
208 
209  std::ostream & operator<<( std::ostream & str, const SigcheckPlugins & obj )
210  { return str << *obj._pimpl; }
211 
212 } // namespace zypp
SigcheckPlugins()
No plugins.
bool hasKey(const std::string &key_r) const
Whether the header list contains at least one entry for key_r.
Definition: PluginFrame.h:184
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:459
Command frame for communication with PluginScript.
Definition: PluginFrame.h:41
Exception thrown by SigcheckPlugins.
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
Definition: Patch.cc:122
void launch(const Pathname &chroot_r=Pathname())
const std::string & command() const
Return the frame command.
Definition: PluginFrame.cc:439
String related utilities and Regular expression matching.
const Pathname & script() const
Return the script path if set.
void launch(const Pathname &chroot_r)
Definition: ansi.h:854
void addHeader(const std::string &key_r, const std::string &value_r=std::string())
Add header for key_r leaving already existing headers for key_r unchanged.
Definition: PluginFrame.cc:481
PluginFrame receive() const
Receive a PluginFrame.
void sigcheck(const Pathname &data_r, const Pathname &sig_r=Pathname(), const Pathname &key_r=Pathname()) const
Let plugin do the signature check.
Impl(const std::string &cmdline_r, const Pathname &plugindir_r)
SigcheckPlugin(const SigcheckPlugin &)=delete
const Plugins & plugins()
All plugins (their addresses can be captured).
bool empty() const
Test for an empty path.
Definition: Pathname.h:117
void sigcheck(const Pathname &data_r, const Pathname &sig_r=Pathname(), const Pathname &key_r=Pathname()) const
std::vector< std::string > Args
void send(const PluginFrame &frame_r) const
Send a PluginFrame.
Impl(Pathname script_r, Args args_r)
Pathname getChroot() const
Return a connected scripts chroot or an empty Pathname.
bool isAckCommand() const
Convenience to identify an ACK command.
Definition: PluginFrame.h:114
std::string sigExtension() const
Extension of a signature file to retrieve.
std::string unBSEscape(std::string_view word_r)
Definition: StringV.cc:213
std::vector< std::string_view > splitBSEscaped(std::string_view line_r, std::string_view chars_r, unsigned maxSplits_r)
Definition: StringV.cc:243
std::string keyExtension() const
Extension of a key file to retrieve.
void launch(const Pathname &chroot_r=Pathname())
Launch all plugins (optionally chrooted).
int close()
Close any open connection.
Base class for Exception.
Definition: Exception.h:152
Impl(Pathname script_r)
std::vector< SigcheckPlugin > Plugins
const std::string & getHeader(const std::string &key_r) const
Return header value for key_r.
Definition: PluginFrame.cc:469
#define pDBG
Definition: LogTools.h:304
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
Definition: Capabilities.cc:65
RW_pointer< Impl > _pimpl
Interface to plugin scripts using a Stomp inspired communication protocol.
Definition: PluginScript.h:62
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
std::string sprint(Args &&... args)
Print words as string.
Definition: LogTools.h:266
RW_pointer< Impl > _pimpl
detail::Dump< Tp > dump(const Tp &obj_r)
Definition: LogTools.h:762
static Pathname stripprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r with any root_r dir prefix striped.
Definition: Pathname.cc:281
bool isOpen() const
Whether we are connected to a script.
void launch(const Pathname &chroot_r=Pathname())
Launch the plugin.
Handle a bunch of SigcheckPlugins.
void openChrooted(const Pathname &chroot_r)
Like open() but runs the script chrooted into chroot_r.