Entwickler-Ecke

Windows API - Programm als anderer Benutzer ausführen


Martok - Mo 23.07.07 18:07
Titel: Programm als anderer Benutzer ausführen
Hallo!

Ich möchte mir ein Programm schreiben, dass wie Runas (Unter Win2k) Programme in anderem Kontext starten kann.
Der Befehl auf der Kommandozeile wäre dieser: "C:\>runas /profile /user:Martok cmd.exe". Wie kann ich dieses Verhalten erzeugen?

Ich habe mich bereits mit dem Angehängten (aus der DP mehr oder weniger) versucht, aber kriege ich die Fehlermeldung
Zitat:
Fehler 1314: Der Client besitzt ein erforderliches Recht nicht


Das ganze scheitert schon an LogonUser()...warum? Eigentlich mache ich alles genau nach MSDN, und dass das unter 2K anders als unter NT geht steht da auch nicht.
Ach ja... der aufrufende Nutzer ist Administrator... also eigentlich müssten doch alle Rechte da sein?

Danke schonmal,
Martok


BenBE - Mo 23.07.07 18:09

Kannst Du mal überprüfen, ob Du die erforderlichen Privilegien nicht nur besitzt, sondern auch Aktiviert hast?

IMHO brauchste ImpersonateToken, LogonUser und CreateProcess, bin mir aber nicht sicher (Ist ne Frage für Luckie, welche man dafür brauch).

Deshalb muss man ja auch erst explizit bei nem Shutdown das Privileg aktivieren, dass man die Maschine killen darf ;-)


Martok - Mo 23.07.07 18:14

Ich habe keine Ahnung... die Sicherheitsarchitektur von Windows ist Neuland für mich.

Aber laut diesem Thread hier [http://www.delphipraxis.net/topic79905,0,asc,0.html] müsste es so gehen, oder? Ich meine, Runas geht ja auch...


Narses - Mo 23.07.07 18:17

Moin!

Hab das schonmal mit Suche in: Delphi-Forum, Delphi-Library CREATEPROCESSASUSER gemacht, ging relativ einfach. Hatte user profile iconLuckie nicht auf seiner Page ein Beispiel... ? :gruebel:

cu
Narses


Martok - Mo 23.07.07 18:29

Das von Luckie [http://www.michael-puff.de/Developer/Artikel/2006_06/CreatePrecessWithLogonW.shtml] funktioniert sogar, aber... was wird dann aus dem EnvironmentBlock? Der wird ja extra geholt in meinem Code, und Luckie ignoriert den völlig...

Wenn das trotzdem der richtige wäre, wäre es natürlich extrem einfach. Erklärt zwar den Fehler nicht im geringsten, aber egal..


Delete - Mo 23.07.07 22:29

Hilfe lesen hilft:
Windows SDK hat folgendes geschrieben:
Windows 2000: The process calling LogonUser requires the SE_TCB_NAME privilege. If the calling process does not have this privilege, LogonUser fails and GetLastError returns ERROR_PRIVILEGE_NOT_HELD. In some cases, the process that calls LogonUser must also have the SE_CHANGE_NOTIFY_NAME privilege enabled; otherwise, LogonUser fails and GetLastError returns ERROR_ACCESS_DENIED. This privilege is not required for the local system account or accounts that are members of the administrators group. By default, SE_CHANGE_NOTIFY_NAME is enabled for all users, but some administrators may disable it for everyone. For more information about privileges, see Privileges.

The account specified by lpszUsername, must have the necessary account rights. For example, to log on a user with the LOGON32_LOGON_INTERACTIVE flag, the user (or a group to which the user belongs) must have the SE_INTERACTIVE_LOGON_NAME account right. For a list of the account rights that affect the various logon operations, see Account Rights Constants.

Daran wird es wohl irgendwie liegen.


Martok - Di 24.07.07 17:57

So... der Rest vom Programm ist jetzt soweit dass ich das echt testen konnte.
Die Umgebung brauche ich tatsächlich, also auch LogonUser() also auch das Privileg dazu... Wie komme ich da ran? Ich hab gelesen, dass man dafür ein Service sein müsste... ist doch aber runas auch nicht, dafür gibt es doch den Dienst "Ausführen als", oder?


Delete - Di 24.07.07 23:20

runas nutzt aber den Service "Sekundäre Anmeldung" und CreateProcessWithLogonW ebenfalls.


Martok - Mi 25.07.07 00:16

Und wie könnte ich das?
Oder alternativ: wie komme ich sonst an einen EnvironmentBlock?

Eigentlich gefällt mir das ja nicht, aber ich bin drauf und dran runas mit ShellExecute aufzurufen...

In Richtung WinApi hab ich noch so gut wie nix gemacht, also versteh bitte meine eventuelle Begriffsstutzigkeit ;)


Delete - Mi 25.07.07 00:20

Was gefällt dir an CreateProcessWithLogonW nicht?


Martok - Mi 25.07.07 00:58

Also... die Funktion ist ok.

Aber: das aufgerufene Programm hat nen Bug. Wusste ich aber nicht, und hab deswegen am falschen Ende nach dem Fehler gesucht :motz:

Und zwar hab ich kein Arbeitsverzeichnis gesetzt, damit lag das bei 'C:\winnt\system32'. Normal hätte es aber das Anwendungsverzeichnis sein müssen. Damit hat der seine Konfigurationsdateien dort gesucht, statt in seinem Verzeichnis. Sowas kommt bei raus, wenn man mit relativen Pfaden arbeitet... muss ich mal den Programmieren direkt mal sagen dass das so Mist ist...

Geht jedenfalls so:


Delphi-Quelltext
1:
2:
3:
  CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, PWideChar(s), CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE,
    nil, pchar(CurDir), @si, @pif);


Wieder was gelernt: nicht immer ist das eigne Programm schuld ;)


Halt, eins ist doch noch: warum ist diese Funktion so langsam? Beim Aufruf des ganzen stockt mein Programm immer ne Weile..


Delete - Mi 25.07.07 02:11

user profile iconMartok hat folgendes geschrieben:
Halt, eins ist doch noch: warum ist diese Funktion so langsam? Beim Aufruf des ganzen stockt mein Programm immer ne Weile..

Eventuell muss der Dienst erst noch gestartet werden. Ansonsten musst du mal Microsoft fragen.


Wapiti - Mo 20.08.07 19:55
Titel: CreateProcessWithLogonW ist langsam
Ich ärgerte mich seit Tagen über das gleiche Problem. Beim Aufruf von CreateProcessWithLogonW hing der Aufruf bei mir für fast genau 15 Sekunden. Beim Aufruf eines Programms mit runas in der Console oder Ausführen als... im Explorer startete dieser aber sofort. Wo war der Unterschied???

Lange hatte ich die Flags oder die StartInfo in Verdacht, aber andere Informationen als im SDK waren nirgendwo zu finden. Auf Wie Starten eines Prozesses als einen anderen Benutzer in Visual Basic [http://support.microsoft.com/kb/285879/de] fiel mir dann auf, daß dort lpDomain gesetzt wird.

Zitat:
Parameters
lpUsername
[in] Pointer to a null-terminated string that specifies the name of the user. This is the name of the user account to log on to. If you use the UPN format, user@DNS_domain_name, the lpDomain parameter must be NULL.
The user account must have the Log On Locally permission on the local computer. This permission is granted to all users on workstations and servers, but only to administrators on domain controllers.

lpDomain
[in] Pointer to a null-terminated string that specifies the name of the domain or server whose account database contains the lpUsername account. If this parameter is NULL, the user name must be specified in UPN format.


Laut Parameterbeschreibung ist dies jedoch nicht unbedingt nötig und war bei mir daher auf nil. Den User-Namen hatte ich aber ohne UPN. In dem Moment, wo ich lpDomain verwendete, ging nun der Start unmittelbar. Bei nil für die Domain und den Usernamen im korrekten UPN-Format wird dafür: 'Anmeldung fehlgeschlagen: unbekannter Benutzername oder falsches Kennwort' ausgegeben.

Nun wird es interessant: Setzt man als Domain-Namen irgendetwas beliebiges ein, so erfolgt der Start unverzüglich und es gibt keine Fehlermeldung! Ist der String leer hängt der Start wieder zeitweilig fest. Das gleiche Verhalten ist bei runas in der Console und auch bei Ausführen als.... Bei letzterem klappt es dafür auch mit dem UPN-Usernamen und ohne Domain ohne zu hängen. Wie sich alles verhält bei vorhandenen Domainen kann ich jedoch nicht sagen.

Fazit: Setzt man lpDomain in CreateProcessWithLogonW, dann klappts auch mit dem Start.


Martok - Mo 20.08.07 20:11

Danke für deine Antwort! Hab ich gleich noch eingebaut, und schon ist das Programm gradezu rasant ;)

Eine Mögliche Ursache des Ganzen wäre, dass er ohne angegebene Domain erst eine im Netzwerk gesucht hat... was natürlich scheitert, damit aber den Timeout erreicht.


Narses - Mo 20.08.07 20:15

Moin!

user profile iconMartok hat folgendes geschrieben:
Eine Mögliche Ursache des Ganzen wäre, dass er ohne angegebene Domain erst eine im Netzwerk gesucht hat... was natürlich scheitert, damit aber den Timeout erreicht.

Das würde ich auch so sehen, denn auf den PCs in unserer Domäne läuft das ohne Verzögerung mit NIL-Domain-Parameter; auf meinem Standalone-PC hingegen dauert´s... ;)

cu
Narses


Martok - Di 21.08.07 11:44

Ähm.... kleines Problem: der Prozess wird nicht als anderer User gestartet, sondern als NT-AUTORITÄT/SYSTEM...

Kann das mal einer unter einem eingeschränkten User testen, ob das eventuell eine Rights Escalation ist?