Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Linux: Run external process with requesting password
Forum Updated to NodeBB v4.3 + New Features

Linux: Run external process with requesting password

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 3 Posters 4.9k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    robcont_
    wrote on 28 Feb 2019, 08:20 last edited by robcont_
    #1

    Hi,
    I'm working on a Qt application on Linux OS. What I need is to exec some system commands and track the progress between each one. I know QProcess class is designed for these purposes, but I need some commands to be execute with root permissions (e.g. sudo apt-get update/install). I've found pkexec tool, but I wanto to avoid to ask permissions for each command.
    Below an example of what I need:

    QProgressDialog *dialog= new QProgressDialog();
    QProcess *proc = QProcess();
    [...]
    
    proc .execute("sudo apt-get update"); 
    dialog.setValue(20);
    
    proc .execute("sudo apt-get install MY_PACKAGE");
    dialog.setValue(50);
    
    proc .execute("sudo RUN_MY_SCRIPT");
    dialog.setValue(100);
    

    I've tried also another solution. I've created a simple script with all the commands, running this with pkexec tool. This works fine, but I cannot track progress from between each command.

    QProcess::execute("pkexec MY_SCRIPT_WITH_ALL_COMMANDS"); 
    
    J 1 Reply Last reply 28 Feb 2019, 09:11
    0
    • S Offline
      S Offline
      sierdzio
      Moderators
      wrote on 28 Feb 2019, 08:28 last edited by
      #2

      You can print progress inside your script echo 20, echo 50 etc. And then use QProcess::readyReadStandardOutput to react to it in your GUI.

      (Z(:^

      R 1 Reply Last reply 28 Feb 2019, 09:09
      4
      • S sierdzio
        28 Feb 2019, 08:28

        You can print progress inside your script echo 20, echo 50 etc. And then use QProcess::readyReadStandardOutput to react to it in your GUI.

        R Offline
        R Offline
        robcont_
        wrote on 28 Feb 2019, 09:09 last edited by
        #3

        @sierdzio
        How did I not think about it? Thank you!!!!

        1 Reply Last reply
        0
        • R robcont_
          28 Feb 2019, 08:20

          Hi,
          I'm working on a Qt application on Linux OS. What I need is to exec some system commands and track the progress between each one. I know QProcess class is designed for these purposes, but I need some commands to be execute with root permissions (e.g. sudo apt-get update/install). I've found pkexec tool, but I wanto to avoid to ask permissions for each command.
          Below an example of what I need:

          QProgressDialog *dialog= new QProgressDialog();
          QProcess *proc = QProcess();
          [...]
          
          proc .execute("sudo apt-get update"); 
          dialog.setValue(20);
          
          proc .execute("sudo apt-get install MY_PACKAGE");
          dialog.setValue(50);
          
          proc .execute("sudo RUN_MY_SCRIPT");
          dialog.setValue(100);
          

          I've tried also another solution. I've created a simple script with all the commands, running this with pkexec tool. This works fine, but I cannot track progress from between each command.

          QProcess::execute("pkexec MY_SCRIPT_WITH_ALL_COMMANDS"); 
          
          J Offline
          J Offline
          JonB
          wrote on 28 Feb 2019, 09:11 last edited by JonB
          #4

          @robcont_
          @sierdzio's suggestion of putting echos 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 add set -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?

          R 1 Reply Last reply 28 Feb 2019, 10:01
          2
          • J JonB
            28 Feb 2019, 09:11

            @robcont_
            @sierdzio's suggestion of putting echos 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 add set -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?

            R Offline
            R Offline
            robcont_
            wrote on 28 Feb 2019, 10:01 last edited by
            #5

            @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 with sudo.
            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.

            J 1 Reply Last reply 28 Feb 2019, 10:16
            0
            • R robcont_
              28 Feb 2019, 10:01

              @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 with sudo.
              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.

              J Offline
              J Offline
              JonB
              wrote on 28 Feb 2019, 10:16 last edited by JonB
              #6

              @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 further sudo 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 the sudos) and executing that script itself via sudo 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 out sudo -A, --askpass for that?

              So there are a few things to look at!

              R 1 Reply Last reply 28 Feb 2019, 10:57
              2
              • J JonB
                28 Feb 2019, 10:16

                @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 further sudo 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 the sudos) and executing that script itself via sudo 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 out sudo -A, --askpass for that?

                So there are a few things to look at!

                R Offline
                R Offline
                robcont_
                wrote on 28 Feb 2019, 10:57 last edited by robcont_
                #7

                @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 without gksudo, 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 out sudo -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.

                J 1 Reply Last reply 28 Feb 2019, 11:16
                0
                • R robcont_
                  28 Feb 2019, 10:57

                  @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 without gksudo, 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 out sudo -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.

                  J Offline
                  J Offline
                  JonB
                  wrote on 28 Feb 2019, 11:16 last edited by JonB
                  #8

                  @robcont_
                  Well, that link shows several possible prompters, the first of which is plain sudo and only the last of which is pkexec, 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 my sudo 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.04 zenity --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.

                  R 1 Reply Last reply 28 Feb 2019, 12:13
                  1
                  • J JonB
                    28 Feb 2019, 11:16

                    @robcont_
                    Well, that link shows several possible prompters, the first of which is plain sudo and only the last of which is pkexec, 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 my sudo 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.04 zenity --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.

                    R Offline
                    R Offline
                    robcont_
                    wrote on 28 Feb 2019, 12:13 last edited by
                    #9

                    @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");
                    
                    J 1 Reply Last reply 28 Feb 2019, 14:28
                    2
                    • R robcont_
                      28 Feb 2019, 12:13

                      @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");
                      
                      J Offline
                      J Offline
                      JonB
                      wrote on 28 Feb 2019, 14:28 last edited by
                      #10

                      @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.

                      R 1 Reply Last reply 28 Feb 2019, 15:09
                      0
                      • J JonB
                        28 Feb 2019, 14:28

                        @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.

                        R Offline
                        R Offline
                        robcont_
                        wrote on 28 Feb 2019, 15:09 last edited by
                        #11

                        @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 ...
                        }
                        
                        J 1 Reply Last reply 28 Feb 2019, 17:46
                        0
                        • R robcont_
                          28 Feb 2019, 15:09

                          @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 ...
                          }
                          
                          J Offline
                          J Offline
                          JonB
                          wrote on 28 Feb 2019, 17:46 last edited by JonB
                          #12

                          @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 like

                          env 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 use system() here. You've already started using QProcess, at least use that instead.

                          • echo: Just don't do this. You don't know how echo 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, maybe sudo -S -l or sudo -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 run sudo -S as the one & only process and directly send the password [followed by newline, sudo -S requires that] from your Qt program to its stdin. You've already started using QProcess, 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's stdin.

                          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 using echo ... | to do this is so offensive I can't help but protest! :)

                          1 Reply Last reply
                          1

                          1/12

                          28 Feb 2019, 08:20

                          • Login

                          • Login or register to search.
                          1 out of 12
                          • First post
                            1/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved