|
Antwort |
Registriert seit: 3. Sep 2004 434 Beiträge Delphi 10.4 Sydney |
#1
Betriebssystem: Win Vista,Win 7
Hallo zusammen,
ich bin mir nicht ganz sicher, aber scheinbar hat es kürzlich ein Windows (7?) Update gegeben, dass die automatische Anmeldung verhindert, sobald ein PC in eine Domäne hinzugefügt wurde. Kennt jemand das Problem bzw. Abhilfe? --- Bisherige Schritte: Unter http://technet.microsoft.com/de-de/l...8WS.10%29.aspx wird beschrieben, wie man den PC (auch Windows 7) dazu bekommt, sich automatisch einzuloggen. Mit "control userpasswords2" kann man einen PC, der _nicht_ in der Domäne registriert ist (<> angemeldet!), dazu bringen, sich zukünftig automatisch anzumelden. Für PCs, die der Domäne hinzugefügt wurden, hat bis ca. Mitte Mai 2011 die Lösung mit der Registry (siehe Link oben) einwandfrei funktioniert. Sowohl für die Anmeldung mit einem Domänen Account, wie auch mit einem Lokalen. Seit den Updates (?) (welche?) kommt nun immer beim Start des PCs die Meldung in etwa "Benutzername und/oder Passwort falsch!". Das Problem tritt bei mehreren Kunden, in verschiedenen Domänen sowohl mit wie auch ohne Gruppenrichtlinien auf. Benutzername und Passwörter sind 10x gegengeprüft, also alles 100% richtig eingetragen. Wenn man nach dem wegklicken der Fehlermeldung das Passwort -wie in der Registry hinterlegt- per Hand eintippt, geht es problemlos weiter. Ich konnte über "Autologon" von Sysinternals (jetzt M$, siehe http://technet.microsoft.com/de-de/s...rnals/bb963905 ) einen Erfolg erringen; die PCs melden sich wieder automatisch an. Laut Beschreibung setzt das Tool einzig und alleine die Registry-Werte, die oben aufgeführt sind. Aller-einzigster Unterschied: der Wert "DefaultPassword" (REG_SZ) ist jetzt versteckt und verschlüsselt, so dass man ihn nur mit dem Tool LSASecretView ansehen kann (<-- wird von AntiVir u.a. als Virus eingestuft, Hersteller: http://www.nirsoft.net/utils/lsa_secrets_view.html). Jetzt ist die Frage: Funktioniert das Programm "Autologon" weil es noch andere unsichtbare/"geheime" Einstellungen für das Logon vornimmt, oder einzig und alleine weil das Logon-Passwort verschlüsselt und versteckt ist, und es damit eine eventuelle, neuartige Sicherheitsvorgabe von M$ o.ä. erfüllt? Es heißt, dass AutoLogon nicht auf x64-Systemen funktioniert. Zudem kann bzw. darf ich es nicht bei jedem Kunden mitliefern. Außerdem muss mein Installer das AutoLogon automatisch setzen können, was mit dem Zusatzprogramm zwar geht, aber wieder unnötigen Installer-Ballast >500kb erzeugt. Kann mir jemand sagen, wie ich mit Delphi den "DefaultPassword" (REG_SZ) Wert in die Windows-Registry so schreiben kann, dass er versteckt und verschlüsselt ist, und somit auch nur mit LSASecretView zu sehen ist? Vielen Dank schonmal im Voraus, zusätzlichen Dank an alle, die Kommentare über die Sinnhaftigkeit von Autologon unterlassen Lg Mathias Edit: Gibt es einen großartigen Unterschied zwischen meinem Code und dem Beispiel in C?
Zitat:
reg.RootKey := HKEY_LOCAL_MACHINE;
if reg.OpenKey('Software\Microsoft\Windows NT\CurrentVersion\Winlogon', True) then begin reg.WriteString('AutoAdminLogon', '1'); reg.WriteString('DefaultUserName', edtUserName.Text); reg.WriteString('DefaultDomainName', edtDomain.Text); reg.WriteString('DefaultUserPassword', edtPassword.Text); reg.CloseKey; end;
Zitat:
if( RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", &hKey ) != ERROR_SUCCESS) {
if( RegSetValueEx( hKey, "DefaultPassword", 0, REG_SZ, Password, strlen(Password)+1 ) != ERROR_SUCCESS ) { Abort( NULL, TEXT("Fehler")); return TRUE; [...]
Zitat:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] "AutoAdminLogon"="1" "DefaultUserName"="Name" "DefaultDomainName"="PCName" "DefaultUserPassword"="12345" Geändert von berens (20. Jun 2011 um 14:31 Uhr) |
Zitat |
Registriert seit: 29. Mai 2002 37.621 Beiträge Delphi 2006 Professional |
#2
Ich verwende bei meinem Usermanager die API Funktion LsaStorePrivateData um das Passwort vom Autologin in der Registry zu speichern.
Michael
Ein Teil meines Codes würde euch verunsichern. |
Zitat |
Registriert seit: 3. Sep 2004 434 Beiträge Delphi 10.4 Sydney |
#3
Hallo zusammen, Danke Luckie für die Tip.
LsaStorePrivateData ist ein guter Ansatz, allerdings wird in der OH ja empfohlen, stattdessen CryptProtectDatazu verwenden. Ich bin nicht wählerisch, und verwende das, was ich irgendwie zum Laufen bekomme. Aus einem deiner anderen Beiträge mit Demo-Projekt war ich so frei, das Ganze mit der Unit lsaapi von Colin Wilson zu testen. Dort sind die Prozeduren und Typen für die LSA-Geschichte in eine Delphi-Unit importiert. Dazu passend habe ich diesen Beitrag in der M$-KB gefunden, der genau mein Problem behandelt (wenn's denn wahr ist): http://msdn.microsoft.com/en-us/library/Aa378826 ; leider in C. Mit meiner naiven Gemüt habt ich das nun nach Delphi übersetzt. Generell scheint es zu klappen, aber wenn ich die Ausgaben von LSASecretsView mit denen von Sysinternals' Autologon vergleiche, merke ich schon, dass ich an mehreren Stellen wohl die Typen falsch übersetzt habe (Passwort: 1234567890; Wenn ich mit LsaStorePrivateData speichere: "1234567890..U..3.Uh."; Sysinternal Autologon: "1.2.3.4.5.6.7.8.9.0.".) Ausserdem muss an die Stellen im folgenden Code, an den die Variable "t" steht, NULL / NIL hin. Mit NULL, NIL, 0 oder '' will er aber nicht compilieren. Bitte werft mal einen Blick auf meine "Übersetzung" (Original) und nennt mir die Korrekturen. Dafür wäre ich sehr Dankbar. Mit dem ganzen Pointer-Gedöns von C komme ich eh nicht klar, deshalb bitte auch die Stellen genau ansehen, bei denen die Variablen/Pointer im Original mit &Undzeichen beginnen. Danke. Übersetzung:
Delphi-Quellcode:
uses lsaapi;
TLSAObjectAttributes = packed record Length : ULONG; RootDirectory : THandle; ObjectName : PLSAUnicodeString; Attributes : ULONG; SecurityDescriptor : pointer; // Points to type SECURITY_DESCRIPTOR SecurityQualityOfService : pointer; // Points to type SECURITY_QUALITY_OF_SERVICE end; LSA_HANDLE = pointer; PLSA_HANDLE = ^LSA_HANDLE; TLSAUnicodeString = packed record Length : WORD; MaximumLength : WORD; Buffer : PWideChar end; PLSAUnicodeString = ^TLSAUnicodeString; NTStatus = Integer; //DWORD; // ^-- Auszüge aus der lsaapi // THX to: http://msdn.microsoft.com/en-us/library/Aa378826 function StoreAutoLogonPassword(_Password: string = ''): DWORD; var ObjectAttributes: TLSAObjectAttributes; LsaPolicyHandle: LSA_HANDLE; lusSecretName: TLSAUnicodeString; lusSecretData: TLSAUnicodeString; SecretNameLength: Word; SecretDataLength: Word; ntsResult: NTStatus; dwRetCode: DWORD; t: TLSAUnicodeString; begin LsaPolicyHandle := NIL; SecretNameLength := 0; SecretDataLength := 0; ntsResult := STATUS_SUCCESS; dwRetCode := ERROR_SUCCESS; // Object attributes are reserved, so initialize to zeros. ZeroMemory(@ObjectAttributes, SizeOf(ObjectAttributes)); // Get a handle to the Policy object. ntsResult := LsaOpenPolicy( t, // local Machine ObjectAttributes, POLICY_CREATE_SECRET, LsaPolicyHandle); if (STATUS_SUCCESS <> ntsResult) then begin // An error occurred. Display it as a win32 error code. dwRetCode := LsaNtStatusToWinError(ntsResult); ShowMessage('Failed call to LsaOpenPolicy: ' + IntToStr(dwRetCode)); Result := dwRetCode; Exit; end; // Initialize an LSA_UNICODE_STRING for the name of the // private data ("DefaultPassword"). SecretNameLength := word(length('DefaultPassword')); lusSecretName.Buffer := 'DefaultPassword'; lusSecretName.Length := SecretNameLength * sizeof(WCHAR); lusSecretName.MaximumLength := (SecretNameLength+1) * sizeof(WCHAR); // If the pwszSecret parameter is NULL, then clear the secret. if(_Password = '') then begin ShowMessage('Clearing the secret...'); ntsResult := LsaStorePrivateData( LsaPolicyHandle, lusSecretName, t); dwRetCode := LsaNtStatusToWinError(ntsResult); end else begin ShowMessage('Setting the secret...'); // Initialize an LSA_UNICODE_STRING for the value // of the private data. SecretDataLength := word(length(_Password)); lusSecretData.Buffer := pwidechar(_Password); lusSecretData.Length := SecretDataLength * sizeof(WCHAR); lusSecretData.MaximumLength := (SecretDataLength+1) * sizeof(WCHAR); ntsResult := LsaStorePrivateData( LsaPolicyHandle, lusSecretName, lusSecretData); dwRetCode := LsaNtStatusToWinError(ntsResult); end; LsaClose(LsaPolicyHandle); if (dwRetCode <> ERROR_SUCCESS) then begin writeln('Failed call to LsaStorePrivateData: ' + IntToStr(dwRetCode)); end; Result := dwRetCode; end; procedure TForm1.Button1Click(Sender: TObject); begin StoreAutoLogonPassword('1234567890'); end; |
Zitat |
Registriert seit: 29. Mai 2002 37.621 Beiträge Delphi 2006 Professional |
#4
Die Unit habe ich auch benutzt oder die von Oliver. Aber schlag mich tot, ich finde im Code vom Usermanager nicht mehr die Stelle, an der ich den Autologin setze.
Puh, ich dachte schon, ich hätte unsauberen Code geschrieben, will sagen, habe sie gefunden:
Delphi-Quellcode:
function SetWinlogonPassword(const Server, Password: WideString): Boolean;
var oa : TLSAObjectAttributes; hPolicy : LSA_HANDLE; usServer : TLSAUnicodeString; usKeyName : TLSAUnicodeString; usPassWord : TLSAUnicodeString; Status : NTSTATUS; begin ZeroMemory(@oa, sizeof(oa)); oa.Length := sizeof(oa); try RtlInitUnicodeString(@usServer, PWideChar(Server)); Status := LsaOpenPolicy(usServer, oa, POLICY_CREATE_SECRET, hPolicy); if (NT_SUCCESS(Status)) then begin RtlInitUnicodeString(@usKeyName, 'DefaultPassword'); RtlInitUnicodeString(@usPassWord, PWideChar(Password)); Status := LsaStorePrivateData(hPolicy, usKeyName, usPassword); end; finally LsaClose(hPolicy); end; Result := NT_SUCCESS(Status); end; //////////////////////////////////////////////////////////////////////////////// function SetAutoWinlogon(Server: WideString; Activate: Boolean; Username, Password: WideString): Boolean; var usPassword : TLSAUnicodeString; usServer : TLSAUnicodeString; reg : TMpuRegistry; begin Result := False; reg := TMpuRegistry.CreateW(Server, HKEY_LOCAL_MACHINE); if (Assigned(reg)) then try reg.Connect; if reg.OpenKeyW('Software\Microsoft\Windows NT\CurrentVersion\Winlogon', KEY_WRITE) = 0 then begin // Username if Username <> '' then reg.WriteStringW('DefaultUserName', Username) else reg.DeleteValueName('DefaultUserName'); // Domain if Server <> '' then // TODO: full unicode support reg.WriteStringW('DefaultDomainName', Server) else reg.DeleteValueName('DefaultDomainName'); // Init unicode string RtlInitUnicodeString(@usPassword, PWideChar(Password)); RtlInitUnicodeString(@usServer, PWideChar(Server)); // Set the password in secret stash if SetWinlogonPassword(usServer.Buffer, usPassword.Buffer) then begin Result := True; end; reg.DeleteValueName('DefaultPassword'); // Activate autologon reg.WriteString('AutoAdminLogon', IntToStr(ord(Activate))); end; finally reg.Free; end; end;
Michael
Ein Teil meines Codes würde euch verunsichern. Geändert von Luckie (22. Jun 2011 um 13:36 Uhr) |
Zitat |
Registriert seit: 3. Sep 2004 434 Beiträge Delphi 10.4 Sydney |
#5
Hi Luckie,
danke für den Code. Wie ich mir schon gedacht habe, war bei mir die Umwandlung in Unicode das eigentliche Problem. Die von Dir verwendete Funktion RtlInitUnicodeString habe ich unverschämterweise durch LsaInitUnicodeString aus diesen Thread ersetzt ( http://www.delphipraxis.net/97466-ls...komplexes.html ), da ich spontan für RtlInitUnicodeString die Unit nicht ausfindig machen konnte. Da der Init-Code jedoch große Ähnlichkeit mit dem hat, den ich oben bereits gepostet habe, hoffe ich, dass er stimmt. Vielleicht mag jemand hier nochmal kurz drüberschauen, ob das Alles seine Richtigkeit hat:
Delphi-Quellcode:
Insgesamt scheint es erst Mal zu funktionieren (in LSASectresView steht nun der selbe String wie mit Sysinternal Autologon).
Procedure LsaInitUnicodeString(Var LsaString: TLsaUnicodeString; Const WS:
WideString); Begin FillChar(LsaString, SizeOf(LsaString), 0); If WS <> '' Then Begin LsaString.Length:=Length(WS) * SizeOf(WideChar); LsaString.MaximumLength:=LsaString.Length + SizeOf(WideChar); LsaString.Buffer:=PWideChar(WS); End; End; function SetWinlogonPassword(const Password: WideString): Boolean; var oa : TLSAObjectAttributes; hPolicy : LSA_HANDLE; usServer : TLSAUnicodeString; usKeyName : TLSAUnicodeString; usPassWord : TLSAUnicodeString; Status : NTSTATUS; begin ZeroMemory(@oa, sizeof(oa)); oa.Length := sizeof(oa); try LsaInitUnicodeString(usServer, ''); // Ich schreibe immer nur auf LocalHost, deshalb muss usServer leer bleiben Status := LsaOpenPolicy(usServer, oa, POLICY_CREATE_SECRET, hPolicy); if (0 = Status) then // 0 = STATUS_SUCCESS begin LsaInitUnicodeString(usKeyName, 'DefaultPassword'); LsaInitUnicodeString(usPassWord, PWideChar(Password)); Status := LsaStorePrivateData(hPolicy, usKeyName, usPassword); end; finally LsaClose(hPolicy); end; Result := Status = 0; end; procedure TForm1.Button1Click(Sender: TObject); begin SetWinlogonPassword('1234567890'); end; Falls jemand von Euch zuhuuuufällig über ein verständliches Delphi-Beispiel für CryptProtectData oder die Updatebeschreibung (oder Gruppenrichtlinie?) von M$ stolpert, in der erklärt wird, dass seit dann-und-dann tatsächlich Plain-Text Passwörter für Autologon nicht mehr akzeptiert werden, wäre ich natürlich sehr dankbar um das Thema komplett abzurunden. Vielen Dank speziell nochmal an Luckie, der -mal wieder- das Wochenende gerettet hat. Lg Mathias Edit1: Nach weiterer Suche bin ich auf dieser Seite auf folgende Info gestoßen: AutoLogon prüft erst, ob mit LSA ein Passwort hinterlegt ist, und wenn nicht, wird als Notlösung der Plaintextwert aus der Registry genommen (Software\Microsoft\Windows NT\CurrentVersion\Winlogon). Das würde einiges erklären: Vielleicht habe ich vor der letzten Image-Erstellung versehentlich einmal "control userpasswords2" verwendet, und damit das LSA-Kennwort gesetzt. Damit war es dann egal, was unter WinLogon steht. Es erklärt auch, warum das Problem erst kürzlich bei allen (Neu-)Kunden zeitgleich aufgetaucht ist; das Problem gibt es wohl generell schon länger (s.u.). Mal gespannt, wie es mit der o.g. LSA-Lösung über Delphi sich in Zukunft verhält... Quelle: http://social.technet.microsoft.com/...6-bf61d18b1a5c
Zitat:
July 06, 2010 3:30 PM MrBeatnik:
We have been having a similar problem, and have made some progress. It seems the DefaultPassword entry in the registry is the 2nd place it checks for a password, but only if it cannot find a password in the 1st location. The 1st location is the LSA secret area (HKLM\Security\Policy\Secret\DefaultPassword). It seems, in our case, that there was a LSA secret password. This was being used to autologin, but it was the wrong password. Any attmepts to fill in the DefaultPassword key were useless because it never checked there. Using the control userpasswords2 allowed us to change the password... you may not be able to do this on the domain, but I assume this is due to group policy, since we are on the domain and don't have that issue. I managed to use a tool called autologon.exe (from the MS Shell team) to supply the correct password from the DefaultPassword key to the LSA. Unfortunately I know of no real way to clear the LSA password without an extra tool. You can test if this is the problem by: 1) Creating a local account and setting the registry manually to autologon with the DefaultPassword key. This should fail. 2) Now using userpasswords2, set the local account in the way described (if you can). This should remove the DefaultPassword key from the registry (proof that it is using the LSA). Now let it autologon. Good luck! I will be creating a new thread about clearing the LSA in Win7. Edit2: -.- Eben ist mir zusätzlich aufgefallen, dass ich in der Registry und meinem Quellcode fälschlicherweise den Wert "DefaultUserPassword" anstelle von dem korrekten "DefaultPassword" verwendet habe. Das wird auch seine Schuldigkeit zu dem Problem getan haben. Hier nochmal die korrekte Version:
Zitat:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] "AutoAdminLogon"="1" "DefaultUserName"="MeinUsername" "DefaultDomainName"="MeinPCNameOderDomain" "DefaultPassword"="1234567890" Geändert von berens (24. Jun 2011 um 16:31 Uhr) Grund: Weitere Info über mögliche Ursache des Problems |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |