title: Proper method to acquire root access on Linux for Qt applications
body: <p>Good day</p>
  
  <p><strong>Background:</strong></p>
  
  <p>I am creating an OpenVPN wrapper application for Linux systems which is near completion. I have run into a little snag. </p>
  
  <p>OpenVPN requires root access to modify routing tables (add and remove routes). Here is where things get a little vague and confusing.</p>
  
  <p>Hopefully, by extending <a href="https://stackoverflow.com/questions/5929220/get-root-privileges-to-my-qt-app">this question</a>, some industry standard answers and solutions could be shared.</p>
  
  <p><strong>Documentation:</strong></p>
  
  <p>So, after a number of hours searching, I compiled a list of possible methods for acquiring root access, however none seem to be official nor any real solid guidance given to acquire this SU privilege.</p>
  
  <p>Let us consider the following methods.</p>
  
  <hr>
  
  <p><strong>1. Using pkexec &amp; polkits</strong></p>
  
  <p>Please find official <a href="https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html" rel="noreferrer">freedesktop polkit documentation here</a> and <a href="https://www.freedesktop.org/software/polkit/docs/latest/polkit-apps.html" rel="noreferrer">here</a> for some information on best practises</p>
  
  <p>There are a few tutorials found online using pkexec and polkits
   - <a href="https://greyok.github.io/simple-polkit-tutorial.html" rel="noreferrer">here</a>, this helped me create my polkit file.
   - <a href="https://stackoverflow.com/questions/5625870/how-to-launch-a-qprocess-with-root-rights">SO Thread</a>
   - And a <a href="https://q-a-assistant.info/life-arts/is-there-a-way-to-gain-superuser-access-from-a-qt-app/3365703" rel="noreferrer">lovely small tutorial</a> for Qt applications</p>
  
  <p>To give a brief explanation (of my understanding) about <code>pkexec</code> and <code>polkits</code>:</p>
  
  <ul>
  <li><code>polkits</code>: </li>
  </ul>
  
  <p>polkits consist of actions and rules (see documenation for indepth reading and explaination). It defines actions of an application and the rules associated with it. Rules can be defined as a user belonging to a specific group, whereby the action queries the rule, it it has succeeded in passing the rule, the user is authenticated automatically (with no popup password prompt), else they are required to enter an administrator password </p>
  
  <ul>
  <li><code>pkexec</code>: </li>
  </ul>
  
  <p>a application used to interface with the polkit actions and authenticate an application to acquire root access.</p>
  
  <p>These require adding an action into <code>/usr/share/polkit-1/actions/</code> and <code>/usr/share/polkit-1/rules.d/</code> (amongst other directories, see documentation for all locations)</p>
  
  <p>This method seems to be well used (but requires a bit more explaination to be understood easily, imo)</p>
  
  <p><em>note: There are <code>qt-polkit</code> libraries made available for usage, see their  <a href="https://github.com/KDE/polkit-qt-1" rel="noreferrer">github repository</a></em></p>
  
  <p><strong>For a simple TL;DR version, see <a href="https://askubuntu.com/a/525515/376524">this</a></strong></p>
  
  <p>The polkit file I created (note this may not be correct, but it does work for me):</p>
  
  <p>Location where it can be found/added (there are others too)</p>
  
  <pre><code>/usr/share/polkit-1/actions
  </code></pre>
  
  <p>Policy Kit file name:
      com.myappname.something.policy    // the <code>.policy</code> is required</p>
  
  <p><strong>Note:</strong></p>
  
  <pre><code>com.myappname.something
  </code></pre>
  
  <p>is refereed to as the namespace of the policy (reading the documenation, this will not be clear)</p>
  
  <p>Policy Kit content</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
  "http://www.freedesktop.org/software/polkit/policyconfig-1.dtd"&gt;
  &lt;policyconfig&gt;
    &lt;vendor&gt;My App Name&lt;/vendor&gt;
    &lt;vendor_url&gt;http://myappurl.com/&lt;/vendor_url&gt;
  
    &lt;action id="com.myappname.something.myaction-name"&gt;
      &lt;description&gt;Run the polkit for My App which requires it for X usage&lt;/description&gt;
      &lt;message&gt;My App requires access to X, which requires root authentication, please let me have su access&lt;/message&gt;
      &lt;icon_name&gt;myappname&lt;/icon_name&gt;
      &lt;defaults&gt;
        &lt;allow_any&gt;auth_admin_keep&lt;/allow_any&gt;
        &lt;allow_inactive&gt;auth_admin_keep&lt;/allow_inactive&gt;
        &lt;allow_active&gt;auth_admin_keep&lt;/allow_active&gt;
      &lt;/defaults&gt;
      &lt;annotate key="org.freedesktop.policykit.exec.path"&gt;/usr/bin/myappname&lt;/annotate&gt;
      &lt;annotate key="org.freedesktop.policykit.exec.allow_gui"&gt;true&lt;/annotate&gt;
    &lt;/action&gt;
  
  &lt;/policyconfig&gt;
  </code></pre>
  
  <p><em>Notes about my policy file (the important bits)</em></p>
  
  <ul>
  <li>This is just an example, see documentation for official examples and descriptions:</li>
  <li><code>&lt;vendor&gt;My App Name&lt;/vendor&gt;</code> is the application name, it can have spaces</li>
  <li><p><code>&lt;action id="com.myappname.something.myaction-name"&gt;</code> any action name here. </p></li>
  <li><p>NOTE!
  The file name -> <code>com.myappname.something.policy</code> and,
  the <code>action id</code> -> <code>com.myappname.something.myaction-name</code> should have the same namespace </p></li>
  <li><p>The icon name should be in accordance with with the latest freedesktop icon spec found <a href="https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#example" rel="noreferrer">here</a></p></li>
  </ul>
  
  <p><strong>TL;DR</strong> (or don't want to):
  icon locations are: </p>
  
  <pre><code> 1. /home/yourusername/.icons (sometimes not there)
   2. /home/yourusername/.local/share/icons
   2. /usr/share/icons
  </code></pre>
  
  <p><em>as long as they conform to the sizes and are a <code>.png</code>, you can pass the filename only (omitting the format)</em></p>
  
  <ul>
  <li><p><code>Very Important</code>: </p>
  
  <pre><code>&lt;annotate key="org.freedesktop.policykit.exec.path"&gt;/usr/bin/myappname&lt;/annotate&gt;
  &lt;annotate key="org.freedesktop.policykit.exec.allow_gui"&gt;true&lt;/annotate&gt;
  </code></pre></li>
  </ul>
  
  <p>When calling <code>pkexec &lt;myappname&gt;</code>, and NOT having these lines <em>(honestly, I am not quite sure purpose of them)</em>, one will run into an error similar to this:</p>
  
  <pre><code>2017-12-19 12::58:24 Fatal: QXcbConnection: Could not connect to display  ((null):0, (null))
  
  Aborted (core dumped)
  </code></pre>
  
  <p>Note: keep the <code>key</code> the same, however you can and probably should change the <code>exec.path</code> key to your application location.</p>
  
  <p><strong>How do policy kits work?</strong></p>
  
  <p>In short, if you review the lovely <a href="https://greyok.github.io/simple-polkit-tutorial.html" rel="noreferrer">example</a> mentioned earlier (and skip all the very similar names of files), it becomes clear.</p>
  
  <p>When one runs:</p>
  
  <pre><code>pkexec &lt;myappname&gt; 
  </code></pre>
  
  <p>this calls the local authentication agent to run the application (in our case) as root. </p>
  
  <p>This is handled by the <code>actions</code> (the policy kit mentioned above). Further more, the rules utilize the <code>action id</code> to perform addition queries, etc which can be viewed in the provided examples above.</p>
  
  <p>Once the admin password has been entered, depending on the 'settings' entered into defaults (see <a href="https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html" rel="noreferrer">here</a>), we have:</p>
  
  <pre><code>auth_admin_keep
  </code></pre>
  
  <blockquote>
    <p>Like auth_admin but the authorization is kept for a brief period (e.g. five minutes).</p>
  </blockquote>
  
  <p>Thus, the user can (in my OpenVPN application) connect to an OpenVPN connection for the next 5 minutes, until the password is requested again.</p>
  
  <hr>
  
  <p><strong>2. <code>Sudo</code> (/etc/sudoers):</strong></p>
  
  <p>This seems to be the go to method for most users who required root access, however it is not recommended:</p>
  
  <p>e.g. Check root access before running the main application by calling a singleShot <code>QProcess</code> with arguments:</p>
  
  <pre><code>/bin/sh -c sudo -v
  </code></pre>
  
  <p>will result in exit code of <code>1</code> in various Linux distributions (thus causing me to search for alternatives)</p>
  
  <hr>
  
  <p><strong>3. setuid():</strong></p>
  
  <p>A very good <a href="https://forum.qt.io/post/153042" rel="noreferrer">example</a> can be found here, unfortunatly it doesn't seem to work on modern Linux distros for the reason of it being a security hole which can easily be exploited.</p>
  
  <p>In short, the process requires one to:</p>
  
  <pre><code>chmod +x &lt;executable&gt;
  </code></pre>
  
  <p>and checking that the <code>s</code> bit is set in the application using <code>getuid()</code> to get the user id and <code>getgid()</code> to get the group id of the user.</p>
  
  <p>These functions can be found in Linux headers defined by:</p>
  
  <pre><code>&lt;sys/types.h&gt; // defines structs
  &lt;unistd.h&gt;    // defines methods
  </code></pre>
  
  <p>However, this does not seem to work with modern day Linux systems. Here is the output of executing a root owned application with the <code>s</code> bit set, run as a normal (unprivileged) user:</p>
  
  <pre><code>2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))
  
  Aborted (core dumped)
  </code></pre>
  
  <p>Farewell, <code>setuid()</code></p>
  
  <hr>
  
  <p><strong>4. Other methods:</strong> </p>
  
  <ul>
  <li><strong>PAM</strong></li>
  </ul>
  
  <p>for further reading, see</p>
  
  <ul>
  <li><a href="https://linux.die.net/man/3/pam" rel="noreferrer">man page</a></li>
  <li><a href="https://www.packtpub.com/books/content/development-pluggable-authentication-modules-pam" rel="noreferrer">tutorial/explanation</a></li>
  <li><p>A <a href="https://forum.qt.io/topic/15005/qt-linux-unix-pam-and-cross-platform-authentication-systems" rel="noreferrer">QT Forum</a> question regarding cross platform PAM intergration</p>
  
  <ul>
  <li><code>QT usermode</code>
  Qt provides a <a href="https://wiki.qt.io/How_to_get_applications_running_with_root_privileges" rel="noreferrer">small implementation for acquiring root access</a>, but it is only available to Linux distrobutions using <code>yum</code> package manager.</li>
  </ul></li>
  </ul>
  
  <p>A question followed up on this, see <a href="https://forum.qt.io/topic/11729/admin-user-mode-adapt-gui-to-current-privileges" rel="noreferrer">this QT Forum question</a></p>
  
  <hr>
  
  <p><strong>Problem:</strong></p>
  
  <p>Above may only include a small portion of available methods to acquire root access, however considering that some applications are used globally, they are often attacked or pried apart or even compromised.</p>
  
  <p>After doing this research, it has broadened my knowledge, but hasn't given me a sure-fire method which is recommended, but only hints.</p>
  
  <p><strong>Question:</strong></p>
  
  <p>Which method above is preferred in industry i.e. when should I use the one over the other (PAM vs polkits vs simple sudo) and if other methods are available, are these preferred?</p>