@@ -37,15 +37,16 @@ extern "C"
3737
3838OscapScannerRemoteSsh::OscapScannerRemoteSsh ():
3939 OscapScannerBase(),
40- mSshConnection(this )
40+ mSshConnection(this ),
41+ mUserIsSudoer(false )
4142{
4243 mSshConnection .setCancelRequestSource (&mCancelRequested );
4344}
4445
4546OscapScannerRemoteSsh::~OscapScannerRemoteSsh ()
4647{}
4748
48- void OscapScannerRemoteSsh::splitTarget (const QString& in, QString& target, unsigned short & port)
49+ void OscapScannerRemoteSsh::splitTarget (const QString& in, QString& target, unsigned short & port, bool & userIsSudoer )
4950{
5051 // NB: We dodge a bullet here because the editor will always pass a port
5152 // as the last component. A lot of checking and parsing does not need
@@ -55,10 +56,19 @@ void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsi
5556 // being there and always being the last component.
5657
5758 // FIXME: Ideally, this should split from the right side and stop after one split
58- QStringList split = in.split (' :' );
59+ userIsSudoer = false ;
60+ QStringList sudoerSplit = in.split (' ' );
61+ if (sudoerSplit.size () > 1 )
62+ {
63+ if (sudoerSplit.at (1 ) == " sudo" )
64+ {
65+ userIsSudoer = true ;
66+ }
67+ }
68+ QStringList hostPortSplit = sudoerSplit.at (0 ).split (' :' );
5969
60- const QString portString = split .back ();
61- split .removeLast ();
70+ const QString portString = hostPortSplit .back ();
71+ hostPortSplit .removeLast ();
6272
6373 {
6474 bool status = false ;
@@ -68,25 +78,37 @@ void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsi
6878 port = status ? portCandidate : 22 ;
6979 }
7080
71- target = split .join (" :" );
81+ target = hostPortSplit .join (" :" );
7282}
7383
7484void OscapScannerRemoteSsh::setTarget (const QString& target)
7585{
76- OscapScannerBase::setTarget (target);
86+ QStringList sudoerSplit = target.split (' ' );
87+ OscapScannerBase::setTarget (sudoerSplit.at (0 ));
7788
7889 if (mSshConnection .isConnected ())
7990 mSshConnection .disconnect ();
8091
8192 QString cleanTarget;
8293 unsigned short port;
94+ bool userIsSudoer;
8395
84- splitTarget (target, cleanTarget, port);
96+ splitTarget (target, cleanTarget, port, userIsSudoer );
8597
8698 mSshConnection .setTarget (cleanTarget);
8799 mSshConnection .setPort (port);
88100}
89101
102+ bool OscapScannerRemoteSsh::getUserIsSudoer () const
103+ {
104+ return mUserIsSudoer ;
105+ }
106+
107+ void OscapScannerRemoteSsh::setUserIsSudoer (bool userIsSudoer)
108+ {
109+ mUserIsSudoer = userIsSudoer;
110+ }
111+
90112void OscapScannerRemoteSsh::setSession (ScanningSession* session)
91113{
92114 OscapScannerBase::setSession (session);
@@ -99,6 +121,10 @@ void OscapScannerRemoteSsh::setSession(ScanningSession* session)
99121QStringList OscapScannerRemoteSsh::getCommandLineArgs () const
100122{
101123 QStringList args (" oscap-ssh" );
124+ if (mUserIsSudoer )
125+ {
126+ args.append (" --sudo" );
127+ }
102128 args.append (mSshConnection .getTarget ());
103129 args.append (QString::number (mSshConnection .getPort ()));
104130
@@ -235,28 +261,34 @@ void OscapScannerRemoteSsh::evaluate()
235261
236262 if (mScannerMode == SM_OFFLINE_REMEDIATION)
237263 {
238- args = buildOfflineRemediationArgs (inputFile,
264+ args. append ( buildOfflineRemediationArgs (inputFile,
239265 resultFile,
240266 reportFile,
241- arfFile);
267+ arfFile)) ;
242268 }
243269 else
244270 {
245- args = buildEvaluationArgs (inputFile,
271+ args. append ( buildEvaluationArgs (inputFile,
246272 tailoringFile,
247273 resultFile,
248274 reportFile,
249275 arfFile,
250- mScannerMode == SM_SCAN_ONLINE_REMEDIATION);
276+ mScannerMode == SM_SCAN_ONLINE_REMEDIATION)) ;
251277 }
252278
253279 const QString sshCmd = args.join (" " );
254280
255281 emit infoMessage (QObject::tr (" Starting the remote process..." ));
256282
257283 QProcess process (this );
284+ QString sudo;
285+ if (mUserIsSudoer )
286+ {
287+ // tell sudo not to bother to read password from the terminal
288+ sudo = " sudo -n" ;
289+ }
258290
259- process.start (SCAP_WORKBENCH_LOCAL_SSH_PATH, baseArgs + QStringList (QString (" cd '%1'; " SCAP_WORKBENCH_REMOTE_OSCAP_PATH " %2 " ).arg (workingDir).arg (sshCmd)));
291+ process.start (SCAP_WORKBENCH_LOCAL_SSH_PATH, baseArgs + QStringList (QString (" cd '%1';" " %2 " SCAP_WORKBENCH_REMOTE_OSCAP_PATH " %3 " ).arg (workingDir). arg (sudo ).arg (sshCmd)));
260292 process.waitForStarted ();
261293
262294 if (process.state () != QProcess::Running)
@@ -328,6 +360,31 @@ void OscapScannerRemoteSsh::evaluate()
328360 signalCompletion (mCancelRequested );
329361}
330362
363+ void OscapScannerRemoteSsh::selectError (MessageType& kind, const QString& message)
364+ {
365+ OscapScannerBase::selectError (kind, message);
366+ if (mUserIsSudoer )
367+ {
368+ if (message.contains (QRegExp (" ^sudo:" )))
369+ {
370+ kind = MSG_ERROR;
371+ }
372+ }
373+
374+ }
375+
376+ void OscapScannerRemoteSsh::processError (QString& message)
377+ {
378+ OscapScannerBase::processError (message);
379+ if (mUserIsSudoer && message.contains (QRegExp (" ^sudo:" )))
380+ {
381+ message.replace (QRegExp (" ^sudo:" ), " Error invoking sudo on the host:" );
382+ message += " .\n Only passwordless sudo setup on the remote host is supported by scap-workbench." ;
383+ message += " \n To configure a non-privileged user oscap-user to run only the oscap binary as root, "
384+ " add this User Specification to your sudoers file: oscap-user ALL=(root) NOPASSWD: /usr/bin/oscap xccdf eval *" ;
385+ }
386+ }
387+
331388void OscapScannerRemoteSsh::ensureConnected ()
332389{
333390 if (mSshConnection .isConnected ())
0 commit comments