cloudmatrix / esky

an auto-update framework for frozen python apps
BSD 3-Clause "New" or "Revised" License
362 stars 74 forks source link

Unable to get admin rights #114

Closed JPFrancoia closed 6 years ago

JPFrancoia commented 8 years ago

Im trying to get admin rights through the function call app.get_root(). I need them because when my program is installed on the user's computer, the executable files are in the system files/directories. Ex: C:\Program Files.

But app.get_root() causes an exception on both Windows and Linux (I haven't tried yet on OSX).

On Linux:

Traceback (most recent call last):
  File "/home/djipey/informatique/python/ChemBrows/updater.py", line 59, in run
    self.app.get_root()
  File "/usr/lib/python3.5/site-packages/esky/__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 140, in start
    self.close()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 156, in close
    self.pipe.read()
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_base.py", line 123, in read
    raise EOFError
EOFError

So I modified sudo_base.py to get infos:

        self.check_connection()
        sz = self._read(4)
        print(len(sz))
        print(sz)
        if len(sz) < 4:
            raise EOFError

And when I run my program, I get:

0
b''

So I guess there is a problem with the object SecureStringPipe.

Also, I sometimes have another exception, still on Linux:

Traceback (most recent call last):
  File "/home/djipey/informatique/python/ChemBrows/updater.py", line 59, in run
    self.app.get_root()
  File "/usr/lib/python3.5/site-packages/esky/__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 136, in start
    msg = self.pipe.read()
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_base.py", line 121, in read
    sz = self._read(4)
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_unix.py", line 82, in _read
    return os.read(self.rfd,size)
OSError: [Errno 9] Mauvais descripteur de fichier

It randomly appears, but the first one is the main one.

On windows:

  File "C:\Users\djipey\Desktop\ChemBrows_freeze\updater.py", line 59, in run
    self.app.get_root()
  File "C:\Python34\lib\site-packages\esky\__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "C:\Python34\lib\site-packages\esky\sudo\__init__.py", line 123, in start
    (self.proc,self.pipe) = spawn_sudo(self)
  File "C:\Python34\lib\site-packages\esky\sudo\__init__.py", line 83, in spawn_sudo
    return _impl.spawn_sudo(proxy)
  File "C:\Python34\lib\site-packages\esky\sudo\sudo_win32.py", line 313, in spawn_sudo
    execinfo.lpVerb = "runas"
TypeError: bytes or integer address expected instead of str instance
JPFrancoia commented 8 years ago

I'm actually calling it from a PyQt GUI programm, but in a very simple way. It opens a window (gksudo, I guess) to ask for my password.

I realize this cannot work at all.

Looking at the file, I can see the function _read is not implemented yet, and will return None.

So in the read fucntion:

    def read(self):
        """Read the next string from the pipe.

        The expected data format is:  4-byte size, data, signature
        """
        self.check_connection()
        sz = self._read(4)
        if len(sz) < 4:
            raise EOFError
        sz = struct.unpack("I",sz)[0]
        data = self._read(sz)
        if len(data) < sz:
            raise EOFError
        sig = self._read(self._read_hmac.digest_size)
        self._read_hmac.update(data)
        if sig != self._read_hmac.digest():
            self.close()
            raise RuntimeError("mismatched hmac; terminating")
        return data

len(sz) will always be 0, and the function will fail with an EOFError exception.

JPFrancoia commented 8 years ago

Hum I don't know, I applied a fix on sudo_win32 to fix the issue I mentioned at first (on Windows). It was a bytes thing.

After that, I get the same error on Windows AND on Linux. So the issue is not platform specific.

JPFrancoia commented 8 years ago

I actually get (randomly) one of the following exceptions when I try to use app.get_root():

Traceback (most recent call last):
  File "/home/djipey/informatique/python/ChemBrows/updater.py", line 60, in run
    self.app.get_root()
  File "/usr/lib/python3.5/site-packages/esky/__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 136, in start
    msg = self.pipe.read()
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_base.py", line 121, in read
    sz = self._read(4)
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_unix.py", line 83, in _read
    return os.read(self.rfd,size)
TypeError: an integer is required (got type NoneType)

OR

Traceback (most recent call last):
  File "/home/djipey/informatique/python/ChemBrows/updater.py", line 59, in run
    self.app.get_root()
  File "/usr/lib/python3.5/site-packages/esky/__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 140, in start
    self.close()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 156, in close
    self.pipe.read()
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_base.py", line 123, in read
    raise EOFError
EOFError

OR

Traceback (most recent call last):
  File "/home/djipey/informatique/python/ChemBrows/updater.py", line 60, in run
    self.app.get_root()
  File "/usr/lib/python3.5/site-packages/esky/__init__.py", line 312, in get_root
    self.sudo_proxy.start()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 140, in start
    self.close()
  File "/usr/lib/python3.5/site-packages/esky/sudo/__init__.py", line 157, in close
    self.pipe.write(b("CLOSE"))
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_base.py", line 141, in write
    self._write(struct.pack("I",len(data)))
  File "/usr/lib/python3.5/site-packages/esky/sudo/sudo_unix.py", line 86, in _write
    return os.write(self.wfd,data)
BrokenPipeError: [Errno 32] Relais brisé (pipe)
timeyyy commented 8 years ago

The various commit errors is because we have some threads going on here..

On linux the issue seems to be related to using sudo,

If gksudo is installed apt-get install gksu the tests run fine.

I looked at the parameters passed to gksudo, the k flag was being passed which does the folllowing

 Preserve the current environments, does not set $HOME
       nor $PATH, for example.

I found a similar command in sudo

-E, --preserve-env          preserve user environment when running command

After passing this command in with sudo, we can now successfully get root.

The Next Steps Our tests still fail with this error

  File "/tmp/tmpx46e41zt/scripts/script1.py", line 85, in <module>
  File "/home/alfa/git/esky/esky/__init__.py", line 325, in drop_root
    self.sudo_proxy.terminate()
  File "/home/alfa/git/esky/esky/sudo/__init__.py", line 165, in terminate
    self.proc.terminate()
  File "/usr/lib/python3.4/subprocess.py", line 1686, in terminate
    self.send_signal(signal.SIGTERM)
  File "/usr/lib/python3.4/subprocess.py", line 1681, in send_signal
    os.kill(self.pid, sig)
PermissionError: [Errno 1] Operation not permitted

I added allow_from_sudo decorator to the drop_root function The PermissionError is no longer thrown however calling has_root after drop_root still gives us true. The assert below fails in our tests.

    already_root = app.has_root()
    app.get_root()
    assert app.has_root()
    app.drop_root()
    assert app.has_root() == already_root
rfk commented 6 years ago

Thanks for reaching out. Unfortunately this project is no longer actively maintained, so I'm going to move it into archive mode:

https://rfk.id.au/blog/entry/archiving-open-source-projects/