2011-01-17 6 views
5

Ich muss bestimmte Funktionen einer Anwendung basierend auf dem Standort des aktuell angemeldeten Benutzers beschränken. Da ich diese Logik in Delphi implementieren muss, würde ich es vorziehen, nicht mit vollen Active Directory/LDAP-Abfragen über Bord zu gehen.Wie kann mein Programm feststellen, ob es auf einer bestimmten Domain läuft?

Mein aktueller Gedanke ist die Verwendung von DsGetDcName und die Verwendung der in der Struktur DOMAIN_CONTROLLER_INFO zurückgegebenen GUID und den Vergleich mit einer fest codierten Konstante. Es scheint, dass eine Domänen-GUID sich nur ändert, wenn die Domäne neu erstellt wird, sodass dies die Funktionalität bietet, die ich mit begrenztem Overhead wünsche. Meine einzige Sorge ist, dass ich keine Dokumentation auf MSDN finden kann, die meine Annahme bestätigt.

type 
    EAccessDenied = Exception; 
    EInvalidOwner = Exception; 
    EInsufficientBuffer = Exception; 
    ELibraryNotFound = Exception; 

    NET_API_STATUS = Integer; 

    TDomainControllerInfoA = record 
    DomainControllerName: LPSTR; 
    DomainControllerAddress: LPSTR; 
    DomainControllerAddressType: ULONG; 
    DomainGuid: TGUID; 
    DomainName: LPSTR; 
    DnsForestName: LPSTR; 
    Flags: ULONG; 
    DcSiteName: LPSTR; 
    ClientSiteName: LPSTR; 
    end; 
    PDomainControllerInfoA = ^TDomainControllerInfoA; 

const 
    NERR_Success = 0; 

procedure NetCheck(ErrCode: NET_API_STATUS); 
begin 
    if ErrCode <> NERR_Success then 
    begin 
    case ErrCode of 
     ERROR_ACCESS_DENIED: 
     raise EAccessDenied.Create('Access is Denied'); 
     ERROR_INVALID_OWNER: 
     raise EInvalidOwner.Create('Cannot assign the owner of this object.'); 
     ERROR_INSUFFICIENT_BUFFER: 
     raise EInsufficientBuffer.Create('Buffer passed was too small'); 
     else 
     raise Exception.Create('Error Code: ' + IntToStr(ErrCode) + #13 + 
      SysErrorMessage(ErrCode)); 
    end; 
    end; 
end; 

function IsInternalDomain: Boolean; 
var 
    NTNetDsGetDcName: function(ComputerName, DomainName: PChar; DomainGuid: PGUID; SiteName: PChar; Flags: ULONG; var DomainControllerInfo: PDomainControllerInfoA): NET_API_STATUS; stdcall; 
    NTNetApiBufferFree: function (lpBuffer: Pointer): NET_API_STATUS; stdcall; 
    LibHandle: THandle; 
    DomainControllerInfo: PDomainControllerInfoA; 
    ErrMode: Word; 
const 
    NTlib = 'NETAPI32.DLL'; 
    DS_IS_FLAT_NAME = $00010000; 
    DS_RETURN_DNS_NAME = $40000000; 
    INTERNAL_DOMAIN_GUID: TGUID = '{????????-????-????-????-????????????}'; 
begin 
if Win32Platform = VER_PLATFORM_WIN32_NT then 
    begin 
    ErrMode := SetErrorMode(SEM_NOOPENFILEERRORBOX); 
    LibHandle := LoadLibrary(NTlib); 
    SetErrorMode(ErrMode); 
    if LibHandle = 0 then 
     raise ELibraryNotFound.Create('Unable to map library: ' + NTlib); 
    try 
     @NTNetDsGetDcName := GetProcAddress(Libhandle, 'DsGetDcNameA'); 
     @NTNetApiBufferFree  := GetProcAddress(Libhandle,'NetApiBufferFree'); 
     try 
     NetCheck(NTNetDsGetDcName(nil, nil, nil, nil, DS_IS_FLAT_NAME or DS_RETURN_DNS_NAME, DomainControllerInfo)); 
     Result := (DomainControllerInfo.DomainName = 'foo.com') and (CompareMem(@DomainControllerInfo.DomainGuid,@INTERNAL_DOMAIN_GUID, SizeOf(TGuid)));//WideCharToString(pDomain); 
     finally 
     NetCheck(NTNetApiBufferFree(DomainControllerInfo)); 
     end; 
    finally 
     FreeLibrary(LibHandle); 
    end; 
    end 
else 
    Result := False; 
end; 

Added eine ähnliche Frage auf ServerFault wie vorgeschlagen.

Gefunden eine andere interessante lesen auf Technet, die auch darauf hindeutet, dass ich richtig zu sein, ist aber nicht speziell auf Domäne SIDs beschränkt.

+0

Ich würde zustimmen, dass die GUID nicht geändert wird, aber ich möchte darauf hinweisen, dass Sie sicherlich eine andere GUID erhalten würden, wenn der Domänencontroller ändert. –

+1

Beachten Sie, dass ich die Domänen-GUID verwende, nicht die DC-GUID. Als solches (würde man meinen) müssten alle DCs und Workstations degradiert/entfernt und in eine neue Domain migriert werden. Ich gehe davon aus, dass die Domänen-GUID erstellt wird, wenn Sie den ersten Server auf einen Domänencontroller heraufstufen und dann für die gesamte Lebensdauer der Domäne bestehen. – jchoover

+0

Ok, mein Schade, tut mir leid. Ich stimme Ihrer Vermutung zu, leider habe ich nirgendwo anders gesehen. Vielleicht möchten Sie dies bei [serverfault] (http://serverfault.com/) fragen. –

Antwort

1

Wenn ich Ihre Anforderung richtig verstehe, ist die beste API in Ihrem Fall GetUserNameEx. Sie können den Wert NameFormat des Typs EXTENDED_NAME_FORMAT auswählen, den Sie besser überprüfen können. Eine weitere Funktion GetComputerNameEx ist hilfreich, wenn Sie zusätzlich die Informationen über den Computer überprüfen möchten, auf dem das Programm ausgeführt wird.

+0

Ich versuche jedoch nicht, den Benutzer direkt hier zu validieren. Während ich eine Vielzahl von Antworten zurückbekommen konnte, ist die zugrunde liegende Paranoia, die ich habe, jemand, der immer noch einen internen Pseudo-Domain-Namen mit dem gleichen Namen generieren und falsche Ergebnisse erzielen kann. Wenn ich basierend auf der Domänen-SID einschränken kann, würde ich mich viel sicherer fühlen (vielleicht falsch). – jchoover

0

Ich habe die Notwendigkeit, spezifische Funktionen einer Anwendung auf die Lage des aktuell angemeldeten Benutzers basierend zu beschränken

Wenn Sie den Speicherort des aktuell angemeldeten, um herauszufinden, versuchen, in Benutzer, sollten Sie nicht verwenden DsGetDcName.

Ihr Computer kann mit domainA verbunden werden. Ihr Anmeldebenutzer kann von domainB sein. DsGetDcName Aufruf auf Ihrem Computer nicht Sie geben domainB GUID aber es wird Ihnen domainA GUID

Deshalb glaube ich, Sie LookupAccountName stattdessen verwenden sollten. Der LookupAccountName gibt Ihnen die SID des aktuell angemeldeten Benutzers. Anschließend können Sie die Domänen-SID aus der Benutzer-SID extrahieren. Diese Domänen-SID ist wirklich die Domäne, von der dieser Benutzer stammt. Die Details zum Extrahieren einer Domänen-SID aus einer Benutzer-SID finden Sie unter here

In Bezug auf Ihre ursprüngliche Frage über die Eindeutigkeit der Domänen-GUID, tut mir leid, dass ich keine Antwort darauf habe. AFAIK, es gibt kein Tool, mit dem Sie die Domänen-SID oder die GUID ändern können. Ich bin mir nicht sicher, wie schwer es ist, sich hineinzuhacken und es zu ändern.

+0

Ich hatte diese Route nicht in Betracht gezogen, aber Domain-SIDs sind nur in einem einzigen Unternehmen garantiert einzigartig. Ich habe den Eindruck, dass eine Domain-GUID weltweit einheitlich sein sollte, da die Wahrscheinlichkeit, dass ein CoCreateGUID-Aufruf eine doppelte GUID zurückgibt, sehr gering ist. Vielleicht sollte ich eine Kombination der beiden Methoden verwenden, die Domain-GUID-Prüfung, um die richtige Domain (keine Ghosted/Dummy) zu gewährleisten, und dann LookupAccountName verwenden, um sicherzustellen, dass der aktuelle Benutzer ein Mitglied dieser Domain ist? – jchoover

+0

@jchoover Ja, ich denke ich verstehe was du dir Sorgen machst. Sie möchten nicht, dass jemand eine Dummy-Domäne mit demselben Domänennamen und derselben Domänen-SID einrichtet. Wie gesagt, ich sehe kein Tool, mit dem Sie sichergehen können, wie eine Domänen-SID aussehen wird. Wenn er die Domänen-SID ändern kann (z. B. durch direktes Ändern der NTDS.DIT-Datei), kann er wahrscheinlich denselben Trick verwenden, um auch die Domänen-GUID zu ändern. Ich denke du bist gerade über paranoid. Hacker kann auch einfach Ihren Code zerlegen und Ihren Code mit der eigenen Domain-GUID abgleichen. –

+0

@jchoover BTW, ich stimme zu, dass GUID ist weniger wahrscheinlich zufällig als SID identisch. –

2

Erstellen Sie ein Dienstkonto für die Domäne.

Holen Sie die GUID des Dienstkontos und verschlüsseln Sie es und speichern Sie es irgendwo (Registrierung) möglicherweise als Teil des Unternehmensinstallationsprozesses, um eine Lizenzvereinbarung zu validieren.

Beim Start der Client-Anwendung Abfrage für die Domain Service Account GUID und validieren Sie es mit der gespeicherten GUID.

Oder erstellen Sie Ihren eigenen Unternehmensschlüsselserver.

Eine LDAP-Abfrage ist einfacher als alle Domänencontroller Mist zu tun.

Verwandte Themen