2011-01-17 26 views
5

मुझे वर्तमान में लॉग इन किए गए उपयोगकर्ता के स्थान के आधार पर किसी एप्लिकेशन के विशिष्ट कार्यों को प्रतिबंधित करने की आवश्यकता है। जैसा कि मुझे डेल्फी में इस तर्क को लागू करना है, मैं पूर्ण सक्रिय निर्देशिका/एलडीएपी प्रश्नों के साथ ओवरबोर्ड नहीं जाना पसंद करूंगा।मेरा प्रोग्राम कैसे पता लगा सकता है कि यह किसी विशेष डोमेन पर चल रहा है या नहीं?

मेरा इलाज विचार DsGetDcName का उपयोग करना है, और GUID का उपयोग DOMAIN_CONTROLLER_INFO संरचना में वापस किया गया है और इसकी तुलना हार्ड कोडित स्थिरांक से करें। ऐसा लगता है कि डोमेन GUID केवल तभी बदल जाएगा जब डोमेन पुनर्निर्मित हो, इसलिए यह कार्यक्षमता प्रदान करेगा जो मैं सीमित ओवरहेड के साथ चाहता हूं। मेरी एकमात्र चिंता यह है कि मुझे अपनी धारणा की पुष्टि करने वाले एमएसडीएन पर कोई दस्तावेज नहीं मिल रहा है।

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; 

जोड़ा गया ServerFault पर एक संबंधित सवाल के रूप में सुझाव दिया।

Technet पर एक और दिलचस्प पठन मिला जो मुझे सही होने पर संकेत देता है, लेकिन विशेष रूप से डोमेन एसआईडी पर स्कॉप्ड नहीं किया गया है।

+0

मैं सहमत हूं कि GUID नहीं बदलेगा, लेकिन मैं यह इंगित करना चाहता हूं कि यदि डोमेन नियंत्रक बदलता है तो आपको निश्चित रूप से एक अलग GUID प्राप्त होगा। –

+1

नोटिंग मैं डोमेन GUID का उपयोग कर रहा हूं, डीसी गाइड नहीं। जैसे (कोई सोचता है) इसे सभी डीसी और वर्कस्टेशन को डिमोट करने/हटाने की आवश्यकता होगी, और उन्हें एक नए डोमेन में माइग्रेट करना होगा। मैं इस धारणा के तहत हूं कि जब आप डोमेन नियंत्रक को पहले सर्वर को बढ़ावा देते हैं, तो डोमेन GUID बनाया जाता है, और फिर यह डोमेन के जीवन के लिए रहता है। – jchoover

+0

ठीक है, मेरे बुरे, क्षमा करें। मैं आपकी धारणा से सहमत हूं, दुर्भाग्य से मैंने इसे कहीं भी नहीं देखा है। हो सकता है कि आप इसे [serverfault] (http://serverfault.com/) पर पूछना चाहें। –

उत्तर

1

यदि मैं आपकी आवश्यकता को समझता हूं तो आपके मामले में सबसे अच्छा एपीआई GetUserNameEx है। आप पैरामीटर EXTENDED_NAME_FORMAT के मानदंड का चयन कर सकते हैं, जिसे आप बेहतर तरीके से सत्यापित कर सकते हैं। एक और फ़ंक्शन GetComputerNameEx सहायक है यदि आप कंप्यूटर के बारे में जानकारी को अतिरिक्त रूप से सत्यापित करना चाहते हैं जहां प्रोग्राम चल रहा है।

+0

हालांकि, मैं सीधे उपयोगकर्ता को सत्यापित करने का प्रयास नहीं कर रहा हूं। जबकि मैं विभिन्न प्रतिक्रियाओं को वापस प्राप्त कर सकता हूं, मेरे पास अंतर्निहित परावर्तक है कि कोई भी इस नाम के साथ एक डमी आंतरिक डोमेन नाम उत्पन्न कर सकता है और गलत परिणाम प्राप्त कर सकता है। यदि मैं डोमेन एसआईडी के आधार पर प्रतिबंधित कर सकता हूं, तो मैं अधिक सुरक्षित महसूस कर सकता हूं (शायद गलत तरीके से)। – jchoover

0

मैं वर्तमान के स्थान उपयोगकर्ता

में लॉग इन आप में से वर्तमान में लॉग इन स्थान पता लगाने के लिए कोशिश कर रहे हैं के आधार पर एक आवेदन के विशिष्ट कार्यों को प्रतिबंधित करने की जरूरत है उपयोगकर्ता, आपको DsGetDcName का उपयोग नहीं करना चाहिए।

आपका कंप्यूटर डोमेन ए में शामिल हो सकता है। आपका लॉगऑन उपयोगकर्ता डोमेन बी से हो सकता है। आपके कंप्यूटर पर DsGetDcName कॉलिंग आप domainB GUID नहीं देता है, लेकिन यह आप domainA GUID

इसलिए दे देंगे, मुझे लगता है कि आप LookupAccountName बजाय का उपयोग करना चाहिए। LookupAccountName आपको वर्तमान में उपयोगकर्ता के SID में लॉग इन करता है। फिर, आप उपयोगकर्ता एसआईडी से डोमेन एसआईडी निकाल सकते हैं। वह डोमेन एसआईडी वास्तव में वह डोमेन है जहां से यह उपयोगकर्ता आ रहा है। उपयोगकर्ता एसआईडी से डोमेन एसआईडी निकालने के विवरण के लिए, कृपया here

डोमेन GUID की विशिष्टता के बारे में आपके मूल प्रश्न के बारे में, मुझे खेद है कि मुझे इसका जवाब नहीं है। AFAIK, कोई उपकरण उपलब्ध नहीं है जिससे आप डोमेन एसआईडी और न ही GUID को बदल सकें। मुझे यकीन नहीं है कि इसमें हैक करना कितना मुश्किल है और इसे बदलना कितना मुश्किल है।

+0

मैंने उस मार्ग को नहीं माना था, हालांकि डोमेन एसआईडी केवल एक ही उद्यम में अद्वितीय होने की गारंटी है। मैं इस धारणा के तहत हूं कि एक डोमेन GUID दुनिया भर में unqqe होना चाहिए, क्योंकि एक CoCreateGUID कॉल की एक डुप्लिकेट GUID लौटने की संभावना बहुत पतली है। हो सकता है कि मुझे 2 डोमेन, डोमेन GUID चेक का उचित उपयोग सुनिश्चित करने के लिए उचित डोमेन (एक भूत/डमी नहीं) सुनिश्चित करने के लिए, और फिर LookupAccountName का उपयोग करके यह सुनिश्चित करने के लिए कि वर्तमान उपयोगकर्ता उस डोमेन का सदस्य है? – jchoover

+0

@jchoover हाँ, मुझे लगता है कि मैं समझता हूं कि आप क्या चिंता कर रहे हैं। आप नहीं चाहते कि किसी को एक ही डोमेन नाम और एक ही डोमेन एसआईडी के साथ एक डमी डोमेन सेट अप करें। जैसा कि मैंने कहा, मुझे यह सुनिश्चित करने में कोई भी टूल नहीं दिख रहा है कि डोमेन एसआईडी कैसा दिख रहा है। यदि वह डोमेन एसआईडी (उदा। एनटीडीएस.डीआईटी फ़ाइल को सीधे बदलकर) बदल सकता है, तो वह शायद डोमेन GUID को बदलने के लिए एक ही चाल का उपयोग कर सकता है। मुझे लगता है कि आप सिर्फ पागल हो गए हैं। हैकर भी आपके कोड को अलग कर सकता है और अपने कोड को अपने डोमेन GUID के विरुद्ध जांचने के लिए पैच कर सकता है। –

+0

@jchoover बीटीडब्ल्यू, मैं मानता हूं कि एसआईडी की तुलना में GUID दुर्घटना से समान होने की संभावना कम है। –

2

डोमेन पर एक सेवा खाता बनाएं;

सेवा खाते का GUID प्राप्त करें और उसे एन्क्रिप्ट करें और इसे लाइसेंस अनुबंध को मान्य करने के लिए एंटरप्राइज़ इंस्टॉल प्रक्रिया के हिस्से के रूप में कहीं कहीं (रजिस्ट्री) को सहेजें।

डोमेन सेवा खाता GUID के लिए क्लाइंट ऐप क्वेरी के स्टार्टअप पर और सहेजे गए GUID के साथ इसे सत्यापित करें।

या अपना खुद का एंटरप्राइज़ 'कुंजी' सर्वर बनाएं।

एलडीएपी क्वेरी करना सभी डोमेन नियंत्रक बकवास करने से आसान है।

संबंधित मुद्दे

 संबंधित मुद्दे