Solved Linux: Run external process with requesting password
-
You can print progress inside your script
echo 20
,echo 50
etc. And then use QProcess::readyReadStandardOutput to react to it in your GUI. -
@sierdzio
How did I not think about it? Thank you!!!! -
@robcont_
@sierdzio's suggestion of puttingecho
s into script may work, but it's also possible that depending on line/pipe buffering your calling program won't get to see those lines of output until termination of script, which is not what you want. You'll have to test and see?BTW, you might be advised to put a
set -e
at the head of your script, to deal with any errors which might happen. If you wish to report to your user what the script is doing, you might also addset -x
.Otherwise, are you happy to go down the
pkexec
route with all commands put into one script and executed at the same time, or did you actively want to run each command separately, or what? -
@JonB
Yes I've tested @sierdzio 's suggestion and it works. I marked the topic as solved for this reason.However, the best would be to run each command separately, as is I put them one by one in a shell.
The problem I do not know how to get around is that each command must be run withsudo
.
In a shell the password is asked only for the first command, with the others "inheriting" these permissions.
I would like to have the same behavior in my app. A dialog asking for password is prompted only for the the first command. The others will be executed as well as I already gave authorization. -
@robcont_
Then perhaps you should not yet mark your question as solved!You have several possibilities.
The first is I don't know why you have gone down the
pkexec
route at all? Are you planning to configure it for your script with its permissions-XML file or what? If not I don't think I understand what it is adding to the situation.The next is to utilise the fact that
sudo
is prepared to "cache" the password, once initially supplied, for a period of time. Issuing furthersudo
commands during that period should not re-prompt for password.Security policies may support credential caching to allow the user to run
sudo again for a period of time without requiring authentication. The
sudoers policy caches credentials for 15 minutes, unless overridden in
sudoers(5). By running sudo with the -v option, a user can update the
cached credentials without running a command.So I don't know whether you tested that out on your target system for your multiple
sudo
commands, or just assumed they would each re-prompt.The next is that if you're going to put all your commands into one script file for
pkexec
I don't know why you introduced that instead of just doing same script file (without thesudo
s) and executing that script itself viasudo
to achieve the same principle.I think you're saying you do actively wish to prompt for password first time, rather than just granting automatic privilege (via
pkexec
), which is indeed a good idea. Have you tried outsudo -A, --askpass
for that?So there are a few things to look at!
-
@JonB said in Linux: Run external process with requesting password:
The first is I don't know why you have gone down the
pkexec
route at all? Are you planning to configure it for your script with its permissions-XML file or what? If not I don't think I understand what it is adding to the situation.I'm using
pkexec
show a dialog asking for password. I followed this this post. I have a clean installation of Kubuntu withoutgksudo, kdesudo, kdesu
and I need to run my app without these tools installed.I think you're saying you do actively wish to prompt for password first time, rather than just granting automatic privilege (via
pkexec
), which is indeed a good idea. Have you tried outsudo -A, --askpass
for that?This is exactely what I want! Sorry I'm new on Linux and I didn't knew the
sudo -A, --askpass
option. How can I configure it properly? Following the same link above I'm not succeeding. -
@robcont_
Well, that link shows several possible prompters, the first of which is plainsudo
and only the last of which ispkexec
, and as it notes that may require configuring. You proably/perhaps do not want to have to do any system configuring to support your solution.Unfortunately I cannot actually test anything on my Ubuntu because I'm already configured (via
/etc/sudoers
) not to require a password, so mysudo
won't prompt !But from reading try:
env SUDO_ASKPASS=/usr/bin/ssh-askpass sudo ls -l env SUDO_ASKPASS="/usr/bin/zenity --password" sudo ls -l
However, it does look like
ssh-askpass
needs installing. On my Ubuntu 18.04zenity --password ...
does work out-of-the-box.Now that I realise
pkexec
works by putting up the standard desktop password dialog for you, perhaps that is a perfectly good reason for using that after all. It does for me. -
@JonB
Thanks for your help. After some readings I've found a working solution.QProcess askPermission; askPermission.start("kdialog --password \"Please enter your password to continue\""); askPermission.waitForReadyRead(-1); QByteArray sudoPwd = askPermission.readAll().simplified(); askPermission.close(); system("echo " + sudoPwd + " | sudo -S apt-get update"); system("echo " + sudoPwd + " | sudo -S apt-get install gawk");
-
@robcont_
I'm happy for you if you're happy with this.I assume you know it's a nasty security risk, and will go completely wrong depending on what characters are in the password, but you're happy with that? If you do at least want it to work regardless of what letters might be in the password, just let us know.
-
@JonB said in Linux: Run external process with requesting password:
@robcont_
I'm happy for you if you're happy with this.I assume you know it's a nasty security risk, and will go completely wrong depending on what characters are in the password, but you're happy with that? If you do at least want it to work regardless of what letters might be in the password, just let us know.
Yeah, I know there could be security risks. Now I verify first the correctness of the password with a "dummy"
ls
command, and only if it is successful I continue with the others. Otherwise, I request the password again.bool askForPermissions() { QProcess shell; shell.start("kdialog --title \"Superuser\" --password \"Please enter your password to continue\""); shell.waitForReadyRead(-1); QByteArray sudoPwd = shell.readAllStandardOutput().simplified(); shell.close(); int ret = system("echo " + sudoPwd + " | sudo -S ls"); if (ret != 0) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Error")); msgBox.setIcon(QMessageBox::Critical); msgBox.setText(tr("\nWrong password")); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setButtonText(QMessageBox::Ok, "Retry"); msgBox.exec(); } return ret == 0; } void myFunct() { while (!askForPermissions()) {} // Permissions granted, do work ... }
-
@robcont_
As I said, if you are happy with what you are doing that's OK. But if you don't mind my saying, there are so many faults/potential problems with your approach, I wouldn't do things your way. If it's not too much trouble, if I were you I would reconsider.The whole idea of getting the password from the user yourself and then passing it to
sudo
(or whatever) is dodgy. If it's possible to adapt to something likeenv SUDO_ASKPASS="kdialog --password" sudo ls
where that means that
sudo
itself is getting the password but using your dialog it would be better. However, I agree this might cause re-prompt issues, I don't know.Assuming you wish to stick with getting the password yourself and passing to
sudo
, I still think you should consider changing your code:-
system(...)
: Just don't do this, don't usesystem()
here. You've already started usingQProcess
, at least use that instead. -
echo
: Just don't do this. You don't know howecho
works, and you don't know what it does with a whole bunch of characters, which might be in the password and will just make it go wrong (if you're lucky, or do something nasty if I pick a nasty password). -
|
: Don't do this either :) Using the pipe is going to force your command to be executed via a shell, and you don't want that. -
sudo -S ls
: Not great. At least try to find an option which doesn't try to run some command, maybesudo -S -l
orsudo -S true
will do what you want better/safer, you'll have to try.
You don't need
echo
, pipe or shell at all. All you want to do here is runsudo -S
as the one & only process and directly send the password [followed by newline,sudo -S
requires that] from your Qt program to itsstdin
. You've already started usingQProcess
, it will do this for you neatly. I can't remember the exact calls, but look at the doc page and it tells you (I think there's even an example) how you can write from your calling app to the sub-process'sstdin
.The above will take you a bit of reading & programming compared to the quick & dirty way you have now. I realise it's up to you whether that effort is worth it or not --- it is if you might work with
QProcess
again in the future, or you just want to learn --- it's just that usingecho ... |
to do this is so offensive I can't help but protest! :) -