Gambas request password before running command

Post

Posted
Rating:
#1 (In Topic #1356)
Regular
theyikes is in the usergroup ‘Regular’
Hey again! I'm back to haunt you with yet another question. I won't say it's trivial, suffice to say it has me confused. Essentially I'm trying to run a command that requires a password. I have partially succeeded. here's what i have:

  Dim Command As String
Command = "pkexec ls /root"
Shell Command Wait For Read As "Answer"
 Dim sResult As String
 Shell command To sResult
 TextArea1.Text = sResult

This snippet works. Yeah it asks me twice for the password but that's fine.

here's where I'm stuck.
Dim Command As String
Command = "fdisk -l"
Shell Command Wait For Read As "Answer"
 Dim sResult As String
 Shell command To sResult
 TextArea1.Text = sResult
For some reason this command won't request a password and I'm getting a blank screen.
I know I'm close, i can practically taste success.

Any advice guys?
Online now: No Back to the top

Post

Posted
Rating:
#2
Regular
theyikes is in the usergroup ‘Regular’
 Ok i know i can circumvent the issue by using sudo -E filename.gambas. but I'd   love to know if it's possible to do it where it prompts me for a password……. if that makes sense.
Online now: No Back to the top

Post

Posted
Rating:
#3
Regular
vuott is in the usergroup ‘Regular’

theyikes said

… I'm stuck.
It's "pkexec" command that requests the password.
"pkexec" brings up the password prompt.

Europaeus sum !

<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Online now: No Back to the top

Post

Posted
Rating:
#4
Guru
BruceSteers is in the usergroup ‘Guru’
 When you use Shell you run the command string as a new process.

Using pkexec (albeit wrongly) authorises that process only.

When you run Shell again that process needs authorising too.
The password will not carry over to another shell command.
Online now: No Back to the top

Post

Posted
Rating:
#5
Avatar
Regular
cage is in the usergroup ‘Regular’
 I have a program that checks for updates using the shell command. Then it opens a terminal and requests to do the updates. It will ask for a password then proceed with doing the updates.  Of course the commands are for Arch Linux but can be modified for use with any Linux flavor.

–Checks for updates
Dim Result As String

Shell "checkupdates" To Result

–Then a request to do the updates
–opens a terminal and asks for password
–then proceeds with the update.

Shell "/usr/bin/xfce4-terminal -e '/usr/bin/yay'" Wait

Hope that helps.
Online now: No Back to the top

Post

Posted
Rating:
#6
Regular
vuott is in the usergroup ‘Regular’
Perhaps you could use the “.RunAsRoot()” Method of the Class “Desktop” (you need to activate the Component “gb.desktop”):

Code (gambas)

  1. Public Sub Form_Open()
  2.  
  3.   Desktop.RunAsRoot("fdisk -l", True)
  4.  
  5.   Dim sResult As String
  6.   Shell "fdisk -l" To sResult
  7.   TextArea1.Text = sResult
  8.  

Europaeus sum !

<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Online now: No Back to the top

Post

Posted
Rating:
#7
Guru
BruceSteers is in the usergroup ‘Guru’
I think what you are looking for is an age old question of mine.

how can a program ask for password once then run multiple Shell commands?

That's not so easy and involves creating an internal bash process you can Write and Read from.

I did something  similar in my VBox-Mounter program : VirtualBox image mounter - Gambas ONE but it did not really need to check output, it was just for issuing mount umount commands.

Attached is a project with the RootCommand.class

if you import RootCommand.class or copy it into your projects .src folder you can use it the same as the test project does.

Code (gambas)

  1.  
  2. RootCommand("fdisk -l")
  3.  
  4.  

it will ask for password the first time you use a command then not again.

Then when RootCommand_Prompt() event triggers RootCommand.ProcessText has the command output

or you can get the output as it comes in the RootCommand_Read event.

The output text does not really handle \r that great but mostly works okay.

You can use RootCommand.Kill that ends the shell when exiting the program. or it can be used at any time but be warned if it cannot kill the shell the program hard quits so best to do it at program exit.

you should find it quite usable.

(some of you other folks might find this useful too  :) )

Don't ask me tons of questions about it yikes.. just use it,
OR STUDY THE CODE TILL YOU UNDERSTAND (there are comments and help in the RootCommand.class file)

And don't rework all the code to be all wrong then tell us in great detail how it errors.

PS. Your use of "For Read" in your code is useless if you do not have a process variable and an Answer_Read() method to go with it
and also it makes no sense to use  "For Read" with "Wait" ,
'For Read' is for handling the Process and when using Wait the Process has already ended after the command has run

Attachment
Online now: No Back to the top

Post

Posted
Rating:
#8
Guru
BruceSteers is in the usergroup ‘Guru’

vuott said

Perhaps you could use the “.RunAsRoot()” Method of the Class “Desktop” (you need to activate the Component “gb.desktop”):

Code (gambas)

  1. Public Sub Form_Open()
  2.  
  3.   Desktop.RunAsRoot("fdisk -l", True)
  4.  
  5.   Dim sResult As String
  6.   Shell "fdisk -l" To sResult
  7.   TextArea1.Text = sResult
  8.  

Sadly it doesn't work like that. they would again be 2 separate processes, the second not being authorized.

Desktop.RunAsRoot could do with returning the result if you use Wait but it currently does not :(

I could maybe make another merge request?
As Desktop.RunAsRoot did not use pkexec until I came along :) it only used the depreciated gksu,kdsu,etc commands.
Update Desktop.class, add pkexec to Desktop.RunAsRoot() as gksu/kdesu/etc no longer exist (!246) · Merge requests · Gambas / gambas · GitLab

It would be really handy if it returned the result if you use Wait and return the Process if you don't.
Not so sure Ben would like the idea of that though

EDIT: I submitted a merger request , maybe he'll add it? Update Desktop.class, Enhance RunAsRoot and RunAs to return either the result text or process. (!350) · Merge requests · Gambas / gambas · GitLab
Online now: No Back to the top

Post

Posted
Rating:
#9
Regular
theyikes is in the usergroup ‘Regular’
 Hey! Thanks for all VERY detailed replies!! ok i can kind of make sense of what you're all saying but I'm still confused. BruceSteers thanks for the code. It's going to take me a while to process it all, but i have time on my side. In the meantime i'll try doing something more basic and I'll work my way up. Thanks again guys.
Online now: No Back to the top

Post

Posted
Rating:
#10
Avatar
Administrator
gbWilly is in the usergroup ‘unknown’
I used to have some applications that restarted with elevated rights using gksudo.
Had some simple code and a file being present or not to determine if the application run with elevated rights.
So, the application started itself with a restart with elevated rights and shut down the previous one (Quit worked as no GUI was stared yet, only a restart of application with elevated right)

Here is a code snippet (from a startup module of my application ClientConfigurator and run before any gui gets loaded):

Code (gambas)

  1. '
  2.     Shell "/usr/local/bin/gksudo ClientConfigurator &"     '-> restarts ClientConfigurator with elevated rights asking for a password
  3.     Quit                                                   '-> closes the current running instance of ClientConfigurator
  4. '
  5.  

Then, shit changed and it didn't work anymore, because of progress I guess.

So now, I have a workaround to get this done. From my notes of those days:

TO START WITH ELEVATED RIGHTS:
gksudo no longer present on newer systems
as workaround copy added:
gksudo -> /usr/local/bin
chmod 755 gksudo

How to make this gksudo
1. Make empty textfile
2. Add this to the file:

Code

pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY $@
3. Save as gksudo
4. Make executable
5. copy to /usr/local/bin
6. chmod 755 gksudo

Now, if you restart your application using above method, all your code will run elevated.
You provide a password when starting the application.
I use a lot of Exec commands this way to configure systems fast and easy and uniform.

This method meant that all my old code worked the same when it ran on a newer system.
Only thing happening here is tricking my old code using gksudo while it actually uses pkexec

Well, at least you now know how to make your application run with elevated rights (this is for Debian/Ubuntu systems).

Have fun…

gbWilly
- Gambas Dutch translator
- Gambas wiki content contributor
- Gambas debian/ubuntu package recipe contributor
- GambOS, a distro for learning Gambas and more…
- Gambas3 Debian/Ubuntu repositories


… there is always a Catch if things go wrong!
Online now: No Back to the top

Post

Posted
Rating:
#11
Regular
vuott is in the usergroup ‘Regular’

BruceSteers said

Sadly it doesn't work like that. they would again be 2 separate processes, the second not being authorized.
Certainly, but it also depends on what is to be done.
For example, if I need to change the permissions of a file-device, my solution is effective.

Code (gambas)

  1. Public Sub Button1_Click()
  2.  
  3.   Desktop.RunAsRoot("chmod 444 /dev/input/mouse0")
  4.  
  5.   Shell "cat /dev/input/mouse0" For Read As "Processus"
  6.  
  7.  
  8.  
  9. Public Sub Processus_Read()
  10.  
  11.  
  12.   Read #Last, s, -4
  13.  
  14.   Print Int@(s)
  15.  
But I don't know what theyikes wants to do.  :|

Europaeus sum !

<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Online now: No Back to the top

Post

Posted
Rating:
#12
Guru
BruceSteers is in the usergroup ‘Guru’
So Benoit did not really like my merge suggestions.

He said

Benoit said

If you want to run a command-line tool as root (like in your example), you have to do it "by hand", with the help of the 'Process.Expect()' method to handle password prompts…

So here is that class again but using Process.Expect() from component gb.util /comp/gb.util/process/expect - Gambas Documentation

The Prompt detection event and Kill event has gone now replaced by RootCommand_End() event fired when a command finishes.

Advantages here is that no internal bash shell is needed to be kept open and it does not need pkexec just sudo,
Also you do not NEED to use RootCommand.Kill when program closes to kill the internal bash process
(but it can be used if a command maybe still running to kill it)

The commands are now just run each time using Shell and Process.Expect set so password is entered

Code (gambas)

  1. Shell " sudo -p '[sudo]: ' -E " & $sCommand With ["XTERM=xterm-mono"] For Input Output As "PROC"
  2.  
i use sudo -p "[sudo]: " to force set the prompt line so detection cannot fail if you've set a custom one and -E to pass user environment variables.

the class pops open a little border-less window with a MaskBox in it to initially enter your password.
Attachment

This is better than the last method.
Feel free to put it in your own code, modify the minimal password window to your hearts content :)

Enjoy :)
Online now: No Back to the top

Post

Posted
Rating:
#13
Regular
vuott is in the usergroup ‘Regular’
:? I understood that theyikes did not want to use “sudo”:

theyikes said

Ok i know i can circumvent the issue by using sudo -E filename.gambas. but I'd   love to know if it's possible to do it where it prompts me for a password……. if that makes sense.

Europaeus sum !

<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Online now: No Back to the top

Post

Posted
Rating:
#14
Guru
BruceSteers is in the usergroup ‘Guru’

vuott said

:? I understood that theyikes did not want to use “sudo”:

theyikes said

Ok i know i can circumvent the issue by using sudo -E filename.gambas. but I'd   love to know if it's possible to do it where it prompts me for a password……. if that makes sense.

I think he meant he just did not want to use it himself. (like in a terminal or .desktop file to run the application)

I think his goal here is to run a program as normal user
Then it asks for password to be able to issue multiple root commands without having to type password every time.
Online now: No Back to the top

Post

Posted
Rating:
#15
Avatar
Administrator
gbWilly is in the usergroup ‘unknown’

BruceSteers said

I think his goal here is to run a program as normal user
Then it asks for password to be able to issue multiple root commands without having to type password every time.

I remembered that I once wrote an application named DebianInstaller (started in Gambas2 way back in 2009 or so)
I later imported it to gambas3 and used it a lot.

In the application I had a form to install gdebi-core, a low level .deb package installer that does check dependencies etc.
A long story short, I found the old application somewhere under a thick layer of dust, separated the code in a project and I can run commands with sudo from within a gambas application.
The application itself runs as normal user. This code I from way before Benoit came up with what Bruce is talking about.

You can use Input and Output when working with processes, and thus you just need to check when password is asked and provide it.

Code (gambas)

  1. ' Gambas class file
  2.  
  3.  
  4. Private $hProcess As Process
  5.  
  6. Public Sub Form_Open()
  7.  
  8.   Application.MainWindow = Me
  9.  
  10.   Me.Center
  11.   Me.Caption = Application.Title & (" - run with sudo")
  12.   tbxCommand.SetFocus
  13.  
  14.  
  15.  
  16. Public Sub btnClose_Click()
  17.  
  18.  
  19.  
  20. Public Sub btnInstall_Click()
  21.  
  22.   Dim sCommand As String
  23.  
  24.   btnClose.Enabled = False
  25.   If tbxPass.Text = Null Then
  26.     Message.Warning(("First enter a password"))
  27.     btnClose.Enabled = True
  28.     tbxPass.SetFocus
  29.   Else
  30.     $bFound = False
  31.     $bError = False
  32.          'Tested with command "apt-get install -y gdebi-core" -> -y is to confirm without being asked
  33.          'I made sure it was not present in Synaptic Package Manager before install (so not installed)
  34.          'After running code gdebi-core was installed in Synaptic Package Manager
  35.     sCommand = tbxCommand.Text
  36.     $hProcess = Exec [System.Shell, "-c", "sudo -s " & sCommand] For Input Output As "Process"
  37.  
  38.  
  39.     Error.Clear
  40.  
  41.  
  42. Public Sub Process_Read()
  43.  
  44.   Dim sLine As String
  45.   Dim iB As Integer
  46.  
  47.   sLine = Read #Last, -256
  48.   If Not $bFound Then
  49.     If Len(sLine) <> 0 Then
  50.       iB = InStr(sLine, "password", 1)      'just checking for when password is asked
  51.       If iB > 1 Then                         'we have a request for password
  52.         Print #$hProcess, tbxPass.Text     'we provide password
  53.         $bFound = True
  54.       Endif
  55.     Endif
  56.  
  57.  
  58. Public Sub Process_Error(MyError As String)
  59.    
  60.   If Not IsNull($hProcess) Then
  61.     $hProcess.Kill
  62.     Message.Error("Terminated with reason:\n" & MyError)
  63.   Else
  64.     Message.Error(MyError)
  65.   $bError = True
  66.  
  67.  
  68. Public Sub Process_Kill()
  69.    
  70.   If Not $bError Then
  71.     Message.Info(Subst("&1 run succesfully.", tbxCommand.Text))
  72.   btnClose.Enabled = True
  73.   btnClose.SetFocus
  74.  
  75. '

Attached the project.

Attachment

I tested by:
1. opening Synaptic Package Manager and search for gdebi-core. -> If installed I removed it in Synaptic Package Manager.
2. Close Synaptic Package Manager (important as it unlocks elevated process being used)
3. Started attached project and entered: apt-get install -y gdebi-core -> -y is mportatnt as else it will be asked blocking the code from working
4. Entered sudo password in password field
5. Hit button and waited for the message that the job had been done
6. Opened Synaptic Package Manager to see gdebi-core was installed.

A lot easier to understand IMHO

Enjoy…

gbWilly
- Gambas Dutch translator
- Gambas wiki content contributor
- Gambas debian/ubuntu package recipe contributor
- GambOS, a distro for learning Gambas and more…
- Gambas3 Debian/Ubuntu repositories


… there is always a Catch if things go wrong!
Online now: No Back to the top

Post

Posted
Rating:
#16
Guru
BruceSteers is in the usergroup ‘Guru’
That's not bad , i've done similar in the past.

except for one problem though, if the command happens to print the word "password" anywhere in it's output then your real password will be printed to the screen again only not invisible that time.

hmm 2 problems , it's also only going to work with English language systems as password will probably be a different word.

The trick is to set a unique password prompt of your choice for sudo using the -p arg.
eg.
sudo -s -p "[aska-masudo-passwrd]: "

Then the "[aska-masudo-passwrd]: " string can be explicitly checked for.

Plus I still think it's easier to use Process.Expect  (it's actually quite useful)

With the following you can remove the whole Process_Read event and leave it to the Expect function.
(note the 1st arg of Expect() must not include the trailing space of the prompt)

Code (gambas)

  1.     $hProcess = Exec [System.Shell, "-c", "sudo -s -p '--suuudo--: ' " & sCommand] For Input Output As "Process"
  2.     $hProcess.Expect("--suuudo--:", tbxPass.Text, True)
  3.  
Online now: No Back to the top

Post

Posted
Rating:
#17
Avatar
Administrator
gbWilly is in the usergroup ‘unknown’

BruceSteers said

except for one problem though, if the command happens to print the word "password" anywhere in it's output then your real password will be printed to the screen again only not invisible that time.
Hmmm, 1 problem. The first thing sudo does is ask for password.
If you read my code, it only provides the actual password once…
So, what is the problem exactly?

BruceSteers said

it's also only going to work with English language systems as password will probably be a different word.

That might be true, but is easily solved for someone understanding the code example given. A simple sudo with some command in a terminal on their system will give the proper text to test for.

BruceSteers said

Plus I still think it's easier to use Process.Expect  (it's actually quite useful)

As I stated in my post:

gbWilly said

This code is from way before Benoit came up with what Bruce is talking about.
I haven't seen the code in more than 10 years, neither used it that long. I guess it is from around gambas 3.3 or 3.4.
Just imported a part into a new project, adapted it a bit and posted it here.

Process.Expect is a shortcut build by the man who understands the ins and outs of gambas like no other.

My example is trying to help someone to understand that you can interact using Input Output and actually pass info
It can be useful in more manners than just passing a password and will probably help people like theyikes and other readers, to understand the whole concept better.

A variety of possibilities and different approaches enriches us all…

Enjoy…

gbWilly
- Gambas Dutch translator
- Gambas wiki content contributor
- Gambas debian/ubuntu package recipe contributor
- GambOS, a distro for learning Gambas and more…
- Gambas3 Debian/Ubuntu repositories


… there is always a Catch if things go wrong!
Online now: No Back to the top

Post

Posted
Rating:
#18
Guru
BruceSteers is in the usergroup ‘Guru’
 Aah yes , sorry i guess i didn't read your example well enough and made an assumption.
Online now: No Back to the top
1 guest and 0 members have just viewed this.