[Python]Password naar terminal zenden

Pagina: 1
Acties:
  • 293 views sinds 30-01-2008
  • Reageer

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik ben fijn geholpen in [Python]Laadt geen gtk window, maar hier heb ik een ander probleem (niet-gui gebonden).

Wat ik aan het maken ben, is een interface die met vpnc een vpn verbinding kan opzetten. Ik ben zover dat je met een combobox de profielen uit /etc/vpnc/ kan kiezen, om vervolgens met het gekozen profiel een vpn verbinding aan te gaan. Zo'n profiel ziet er als volgt uit:
code:
1
2
3
4
5
IPSec gateway [hier de gateway naam]
IPSec ID [hier de groep]
IPSec secret [hier het password]
Xauth username [hier je eigen username]
Xauth password [hier je eigen password]

Nu is de laatste regel niet nodig: voor de veiligheid kan je het password ook elke keer meegeven in de promt, dit ziet er dan zo uit:
jurian@karlijn:~$ sudo vpnc-connect [profiel].conf
Enter password for [username]@[gateway]: 
VPNC started in background (pid: 9888)...
jurian@karlijn:~$ 
Het gaat wel lukken als het wachtwoord in het profiel staat, maar hoe kan ik met python input geven aan de terminal als ik de verbinding wil opzetten? Dit wachtwoord is gewoon een Text Entry van de standaard gtk toolkit, maar het gaat hier niet om de grafische schil. Het password heb ik gewoon als variabele.

Wat ik doe met het connecten is dit:
Python:
1
2
3
4
5
6
7
print "Connecting..."
try:
    os.system('vpnc-connect ' + self.profile + '&')
except:
    print "No connection could be made, aborting connection attempt"
else:
    print "Connection succesful to " + self.profile + "\n"
Maar, nu moet ik dus os.system('vpnc-connect ' + self.profile + '&') laten uitvoeren, met tussentijds het invoeren van het password: kan iemand mij hier meer inzicht over geven?

[ Voor 9% gewijzigd door mithras op 23-10-2006 21:35 ]


Verwijderd

Volgens mij kun je met os.system niet met een ander proces communiceren, alleen maar opstarten.
Ik denk dat je het beste even kunt kijken naar pexpect:
http://pexpect.sourceforge.net/


Succes,

Arjen

  • mithras
  • Registratie: Maart 2003
  • Niet online
Verwijderd schreef op dinsdag 24 oktober 2006 @ 08:56:
Volgens mij kun je met os.system niet met een ander proces communiceren, alleen maar opstarten.
Ik denk dat je het beste even kunt kijken naar pexpect:
http://pexpect.sourceforge.net/


Succes,

Arjen
Ah, dat ziet er mooi uit! Het lijkt erop dat dit precies is wat ik nodig heb!

Alleen als ik dat probeer krijg ik een SyntaxError:
Python:
1
2
3
child = pexpect.spawn('vpnc-connect ' + re.escape(profile))
child.expect('Enter password for wb1264222@http://luchtbrug.tudelft.nl:')
child.sendline (password)
root@karlijn:~/Dialer# python gDialer.py
  File "gDialer.py", line 110
    child.expect('Enter password for wb1264222@http://luchtbrug.tudelft.nl:')
        ^
SyntaxError: invalid syntax
root@karlijn:~/Dialer#
Ik heb het exact overgenomen van de API documentation. Alleen de commands binnen die methods veranderd. Verder zit ik wel in een class, Connection. Ik weet niet of dat uitmaakt, maar alles naar self.child omzetten werkt dan ook niet.

offtopic:
Sorry voor de misschien domme vragen, maar echt makkelijk is het niet te vinden op internet. Nu ben ik zondag begonnen met Python, en het lukt wel aardig, alleen moet ik wel dit soort dingen allemaal uitvinden :p

Verwijderd

child.expect verwacht een regular expression, ik denk dat je kunt volstaan met:
child.expect('password')

Misschien dat het daar aan ligt, omdat je een punt (.) dan zou moeten escapen (\.).

Maar ik weet dat niet zeker, daarvoor zou ik denk ik meer code moeten zien.

Groeten,

Arjen

  • mithras
  • Registratie: Maart 2003
  • Niet online
Verwijderd schreef op dinsdag 24 oktober 2006 @ 10:46:
child.expect verwacht een regular expression, ik denk dat je kunt volstaan met:
child.expect('password')

Misschien dat het daar aan ligt, omdat je een punt (.) dan zou moeten escapen (\.).
Dank voor je uitleg. Ik heb het veranderd naar 'password', maar dat mocht niet baten. Je hebt wel gelijk dat het een regex moest zijn, maar ik heb zelfs een fout daarvóór. De error heeft ook een pijltje bij de 'd' van child, alsof python geen '.expect' verwacht. Als ik echter dir(child) print, blijkt dat in die lijst wel 'expect' voorkomt 8)7
Maar ik weet dat niet zeker, daarvoor zou ik denk ik meer code moeten zien.

Groeten,

Arjen
Dit is mijn gehele klasse:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Connection:
    def __init__(self,profile,password=None):
        import re
        print "Connecting..."
        try:
            child = pexpect.spawn('vpnc-connect ' + re.escape(profile))
            child.expect('password')
            child.sendline (password)
        except:
            print "No connection could be made, aborting connection attempt"
        else:
            print "Connection succesful to " + profile + "\n"
            
    def __del__(self):
        print "Disconnecting..."
        os.system('vpnc-disconnect')
De connection maak ik aan met
Python:
1
self.connection = Connection(self.profile, self.password)
Hierbij wordt nog niet gekeken of er wel een password wordt meegegeven (en of die wel nodig is), maar dat probleem wil ik pas later oplossen. In dit geval geef ik elke keer een password mee.

[ Voor 5% gewijzigd door mithras op 24-10-2006 10:55 ]


Verwijderd

Je kunt het complete commando beter even printen, misschien gaat er in het comando wat fout.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Connection(object:
    def __init__(self,profile,password=None):
        import re
        print "Connecting..."
        try:
            command = 'vpnc-connect ' + re.escape(profile)
            print command
            self.child = pexpect.spawn(command) ## Je wil het overal in
            self.child.expect('password')                                             ## je klasse aan kunnen roepen
            selfchild.sendline (password)                       ## dus: self.child
        except: 
            print "No connection could be made, aborting connection attempt"
        else:
            print "Connection succesful to " + profile + "\n"
            
    def __del__(self):
        print "Disconnecting..."
        os.system('vpnc-disconnect')


succes

  • mithras
  • Registratie: Maart 2003
  • Niet online
Op een of andere manier is het commando wel goed, alleen wordt de klasse verkeerd aangemaakt.Zou ik namelijk dit doen:
Python:
1
2
3
4
5
6
7
8
try:
    command = 'vpnc-connect ' + re.escape(profile)
    print command
    self.child = pexpect.spawn(command)
except:
    print "No connection could be made, aborting connection attempt"
else:
    print "Connection succesful to " + profile + "\n"
Krijg ik dit (het programma start dan wel op):
Connecting...
vpnc-connect tudelft\ withpass\.conf
Connection succesful to tudelft withpass.conf
maar het proces vpnc-connect is niet gestart!

Zet ik de regels expect en sendline erbij, krijg ik gelijk (het programma start dus niet op)
root@karlijn:~/Dialer# python gDialer.py
  File "gDialer.py", line 99
    self.child.expect('password')
       ^
SyntaxError: invalid syntax
root@karlijn:~/Dialer# 
En als ik expect weghaal, gebeurt hetzelfde voor de sendline.

Ik ken nu nog te weinig van Python om te zeggen waar de fout in zou kunnen zitten. Voor mij lijkt het er namelijk wel op dat de fout niet in de pexpect module zit, aangezien de fout vóór de .expect method zit.

[ Voor 31% gewijzigd door mithras op 24-10-2006 11:37 ]


  • mithras
  • Registratie: Maart 2003
  • Niet online
Heeft niemand meer een idee? Zelf heb ik geen idee wat ik nu fout heb gedaan, maar voor de volledigheid, ik heb hier het programma online gezet.
Je hebt gtk wel nodig om te kunnen runnen, maar misschien ziet de kenner de fout ook zo wel in de source...

Verwijderd

Tja, ik dacht al dat ik de code zien moest :)

self.command = 'vpnc-connect ' + re.escape(profile)
self.child = pexpect.spawn(self.command)
self.child.expect('password')
self.child.sendline (password)

deze regels moeten echt allemaal net zo veel spatie/tabs vanaf het begin staan.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Connection:
    def __init__(self,profile,password=None):
        import re, pexpect
        print "Connecting..."
        self.profile = profile
        self.profile_text = open("/etc/vpnc/" + self.profile, "r").read()
        #Determine if configuration has already a password assigned 
        if re.search("Xauth\ password",self.profile_text)!=None:
            try:
                os.system("vpnc-connect " + re.escape(self.profile))
            except:
                print "Connection failed"
                vpnDialer.statusbar.new_message("Connection failed")
            else:
                print "Connection succesful to " + self.profile + "\n"
                vpnDialer.statusbar.new_message("Connection succesful to " + self.profile)
                vpnDialer.tray.set_from_stock("gtk-connect")
                vpnDialer.tray.set_tooltip("vpnDialer (connected)")
        else:
            try:
                self.command = 'vpnc-connect ' + re.escape(profile)
                self.child = pexpect.spawn(self.command)
                                self.child.expect('password')
                                self.child.sendline (password)
            except:
                print "Connection failed"
                vpnDialer.statusbar.new_message("Connection failed")
            else:
                print "Connection succesful to " + self.profile + "\n"
                vpnDialer.statusbar.new_message("Connection succesful to " + self.profile)
                vpnDialer.tray.set_from_stock("gtk-connect")
                vpnDialer.tray.set_tooltip("vpnDialer (connected)")
    def __del__(self):
        print "Disconnecting..."
        os.system("vpnc-disconnect")
        print "Connection succesful closed from " + self.profile + "\n"
        vpnDialer.statusbar.new_message("Connection succesful closed from " + self.profile)
        vpnDialer.tray.set_from_stock("gtk-disconnect")
        vpnDialer.tray.set_tooltip("vpnDialer")

  • mithras
  • Registratie: Maart 2003
  • Niet online
Als dat de fout is |:( :X

Ik kijk er vanmiddag thuis naar, maar dan sla ik mezelf op mn kop :p Iig bedankt, waarschijnlijk ben ik dan in de fout gegaan met copy/paste van de api documentation site, waarna ik het verschil tussen tabs (wat ik gebruik) en spaties (op een site) over het hoofd heb gezien.

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik ga het topic toch nog even omhoog schoppen. Na gewoon een hele stomme fout die ik over het hoofd heb gezien, stuit ik tegen een ander probleem. Misschien achteraf even stom, maar dat weet ik nu nog niet :)

Volgens mij werkt het programma'tje, op een significant punt na: de connectie wordt gelijk verbroken. Na self.child.sendline (password) wordt het proces gekilled. vpnc wordt wel degelijk gestart, omdat ik wel output krijg van vpnc dat het wordt gestart. Echter staat het proces niet in mijn processenlijst.

Volgens mij zorgt een spawn() ervoor dat er een subthread gestart wordt. Maar hoe kan ik vpnc en mijn programma loskoppelen van elkaar? Met een terminate() wordt het subprocess sowieso gekilled. Een close(False) geeft ook niet het gewenste resultaat. Met interact() blijft er een koppeling bestaan tussen script & subproces, en gaat het script niet door. Dat is niet de bedoeling.
Nu heb ik gekeken naar Kill(), waarmee misschien een signaal naar de subthread verzonden kan worden waarmee het zich loskoppelt van de thread waarin het programma draait, maar daar kwam ik niet uit.

Zou zoiets kunnen? [google=detach subprocess] geeft niet echt de juiste informatie namelijk en dit probleem heb ik niet kunnen extraheren uit de examples die met de pexpect module meekomen.
Verder heeft het forceren van vpnc als daemon met een & aan het einde van spawn() ook niet veel zin, aangezien het er juist om ging een password te kunnen sturen.

Nu las ik dit op de pexpect homepage:
Threads

On Linux (RH 8) you cannot spawn a child from a different thread and pass the handle back to a worker thread. The child is successfully spawned but you can't interact with it. The only way to make it work is to spawn and interact with the child all in the same thread. [Adam Kerrison]
Betekent dit dat wat ik wil, door deze bug niet kan? Want dat zou vrij jammer zijn ;(

  • mithras
  • Registratie: Maart 2003
  • Niet online
Een schopje, want heeft niemand een idee? Ik heb het ook op ubuntuforums.org geprobeerd, maar daar weet men er ook geen raad mee :|

Het vreemde is dat dus vpnc een daemon moet opstarten, en je de promt teruggeeft. Echter gebeurt dat dus niet als ik pexpect gebruik om vpnc op te starten.
Zijn er anders misschien andere oplossingen om een password naar de terminal te zenden, want wat op internet zoeken geeft ook informatie over pipes met popen, alleen heb ik geen idee wat het doet en hoe je dat zou kunnen gebruiken.

De laatste updates van het script is trouwens hier te vinden, maar het probleem wat hierboven beschreven staat blijft (dus is de nieuwe source niet echt nodig)

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik heb nu inmiddels door dat het waarschijnlijk aan de sendline() method ligt:
root@karlijn:/usr/lib/vpndialer# python
Python 2.4.4c1 (#2, Oct 11 2006, 21:51:02) 
[GCC 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pexpect
>>> child = pexpect.spawn("vpnc-connect tudelft\ nopass.conf")
>>> child.expect(".* password .*: ")
0
>>> child.sendline("[hier_mijn_wachtwoord]")
7
Hierbij retourneert child.sendline dus een exit code 7. Ik heb hier een voorbeeld gevonden waar ook pexpect in de actieve promt werd gebruikt, en daar retourneerde sendline een exit code 10. Wat het betekent weet ik niet, wat ik wel weet is dat 7 != 10 :p

Verder is mijn ingevoerde wachtwoord zeker weten goed. Zijn hier wat python (en pexpect) experts die hier wat over kunnen zeggen? Misschien moet ik het anders over de python mailinglist gooien, want daar bereik ik een betere doelgroep?

edit:
Ow, de kick is binnen 24h :X I hope you don't mind ;)

[ Voor 3% gewijzigd door mithras op 28-10-2006 23:16 ]

Pagina: 1