home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / winnt / disptrus / disptrus.c next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  13.8 KB  |  572 lines

  1. /*++
  2.  
  3. Copyright 1996 - 1997 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     disptrus.c
  8.  
  9. Abstract:
  10.  
  11.     This sample enumerates the trusted domains on the target machine, and
  12.     displays them on stdout.  This list matches (minus sorting) the list of
  13.     domains presents by the WinNT Dacl editor.  For practical applications,
  14.     replace the AddTrustToList() function with linked-list management code
  15.     and then use the resultant list later on in the application.
  16.  
  17.     The optional target machine is specified as argv[1], eg, lsatrust \\winbase
  18.  
  19.     For a WinNT workstation which is not a member of a domain, the only
  20.     relevant trusted domain is the account domain of the machine.  We detect
  21.     a non-member workstation by checking if the primary domain Sid is NULL.
  22.  
  23.     For a WinNT workstation which is a member of a domain, the relevant trusted
  24.     domain is the account domain, the primary domain, and the trusted domain(s)
  25.     of the primary domain.
  26.  
  27.     For a WinNT Domain controller, the account domain and the trusted domains.
  28.  
  29. Author:
  30.  
  31.     Scott Field (sfield) 16-Mar-96
  32.  
  33. --*/
  34.  
  35. #include <windows.h>
  36. #include <lm.h>
  37. #include "ntsecapi.h" // \mstools\samples\win32\winnt\security\include\ntsecapi.h
  38.  
  39. #include <stdio.h>
  40.  
  41. BOOL
  42. BuildTrustList(
  43.     LPWSTR Target
  44.     );
  45.  
  46. BOOL
  47. IsDomainController(
  48.     LPWSTR Server,
  49.     LPBOOL bDomainController
  50.     );
  51.  
  52. BOOL
  53. EnumTrustedDomains(
  54.     LSA_HANDLE PolicyHandle
  55.     );
  56.  
  57. BOOL
  58. AddTrustToList(
  59.     PLSA_UNICODE_STRING UnicodeString
  60.     );
  61.  
  62. //
  63. // helper functions
  64. //
  65.  
  66. void
  67. InitLsaString(
  68.     PLSA_UNICODE_STRING LsaString,
  69.     LPWSTR String
  70.     );
  71.  
  72. NTSTATUS
  73. OpenPolicy(
  74.     LPWSTR ServerName,
  75.     DWORD DesiredAccess,
  76.     PLSA_HANDLE PolicyHandle
  77.     );
  78.  
  79. void
  80. DisplayWinError(
  81.     LPSTR szAPI,        // pointer to Ansi function name
  82.     DWORD dwLastError   // DWORD WinError
  83.     );
  84.  
  85. #define RTN_OK 0
  86. #define RTN_ERROR 13
  87.  
  88. //
  89. // if you have the ddk, include ntstatus.h
  90. //
  91. #ifndef STATUS_SUCCESS
  92. #define STATUS_SUCCESS                  ((NTSTATUS)0x00000000L)
  93. #define STATUS_MORE_ENTRIES             ((NTSTATUS)0x00000105L)
  94. #define STATUS_NO_MORE_ENTRIES          ((NTSTATUS)0x8000001AL)
  95. #endif
  96.  
  97.  
  98. #define ELEMENT_COUNT 64    // number of array elements to allocate
  99.  
  100. LPWSTR *g_TrustList;        // array of trust elements
  101. DWORD g_TrustCount;         // number of elements in g_TrustList
  102.  
  103. //
  104. // Unicode entry point and argv
  105. //
  106.  
  107. int
  108. __cdecl
  109. wmain(
  110.     int argc,
  111.     wchar_t *argv[]
  112.     )
  113. {
  114.     LPWSTR TargetComputer;
  115.     DWORD i;
  116.  
  117.     g_TrustCount = 0;
  118.     g_TrustList = (LPWSTR *)HeapAlloc(
  119.         GetProcessHeap(), HEAP_ZERO_MEMORY,
  120.         ELEMENT_COUNT * sizeof(LPWSTR)
  121.         );
  122.  
  123.     if(g_TrustList == NULL) {
  124.         printf("HeapAlloc error!\n");
  125.         return RTN_ERROR;
  126.     }
  127.  
  128.     //
  129.     // if a target computer was specified, get it
  130.     //
  131.     if(argc == 2)
  132.         TargetComputer = argv[1];
  133.     else
  134.         TargetComputer = NULL; // default to local machine
  135.  
  136.     //
  137.     // build the trust list, and display it if successful
  138.     //
  139.     if(!BuildTrustList(TargetComputer)) {
  140.         DisplayWinError("BuildTrustList", GetLastError());
  141.     } else {
  142.  
  143.         //
  144.         // display trust list
  145.         //
  146.         for(i = 0 ; i < g_TrustCount ; i++)
  147.             printf("%ls\n", g_TrustList[i]);
  148.     }
  149.  
  150.     //
  151.     // free trust list
  152.     //
  153.     for(i = 0 ; i < g_TrustCount ; i++) {
  154.         if(g_TrustList[i] != NULL)
  155.             HeapFree(GetProcessHeap(), 0, g_TrustList[i]);
  156.     }
  157.  
  158.     HeapFree(GetProcessHeap(), 0, g_TrustList);
  159.  
  160.     return RTN_OK;
  161. }
  162.  
  163. BOOL
  164. BuildTrustList(
  165.     LPWSTR Target
  166.     )
  167. {
  168.     LSA_HANDLE PolicyHandle;
  169.     NTSTATUS Status;
  170.  
  171.     PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomain;
  172.     BOOL bDC;
  173.     NET_API_STATUS nas = NERR_Success; // assume success
  174.  
  175.     BOOL bSuccess = FALSE; // assume this function will fail
  176.  
  177.     //
  178.     // open the policy on the specified machine
  179.     //
  180.     Status = OpenPolicy(
  181.                 Target,
  182.                 POLICY_VIEW_LOCAL_INFORMATION,
  183.                 &PolicyHandle
  184.                 );
  185.  
  186.     if(Status != STATUS_SUCCESS) {
  187.         SetLastError( LsaNtStatusToWinError(Status) );
  188.         return FALSE;
  189.     }
  190.  
  191.     //
  192.     // obtain the AccountDomain, which is common to all three cases
  193.     //
  194.     Status = LsaQueryInformationPolicy(
  195.                 PolicyHandle,
  196.                 PolicyAccountDomainInformation,
  197.                 &AccountDomain
  198.                 );
  199.  
  200.     if(Status != STATUS_SUCCESS)
  201.         goto cleanup;
  202.  
  203.     //
  204.     // Note: AccountDomain->DomainSid will contain binary Sid
  205.     //
  206.     AddTrustToList(&AccountDomain->DomainName);
  207.  
  208.     //
  209.     // free memory allocated for account domain
  210.     //
  211.     LsaFreeMemory(AccountDomain);
  212.  
  213.     //
  214.     // find out if the target machine is a domain controller
  215.     //
  216.     if(!IsDomainController(Target, &bDC)) {
  217.         ////
  218.         goto cleanup;
  219.     }
  220.  
  221.     if(!bDC) {
  222.         PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain;
  223.         LPWSTR szPrimaryDomainName = NULL;
  224.         LPWSTR DomainController = NULL;
  225.  
  226.         //
  227.         // get the primary domain
  228.         //
  229.         Status = LsaQueryInformationPolicy(
  230.                 PolicyHandle,
  231.                 PolicyPrimaryDomainInformation,
  232.                 &PrimaryDomain
  233.                 );
  234.  
  235.         if(Status != STATUS_SUCCESS)
  236.             goto cleanup;
  237.  
  238.         //
  239.         // if the primary domain Sid is NULL, we are a non-member, and
  240.         // our work is done.
  241.         //
  242.         if(PrimaryDomain->Sid == NULL) {
  243.             LsaFreeMemory(PrimaryDomain);
  244.             bSuccess = TRUE;
  245.             goto cleanup;
  246.         }
  247.  
  248.         AddTrustToList(&PrimaryDomain->Name);
  249.  
  250.         //
  251.         // build a copy of what we just added.  This is necessary in order
  252.         // to lookup the domain controller for the specified domain.
  253.         // the Domain name must be NULL terminated for NetGetDCName(),
  254.         // and the LSA_UNICODE_STRING buffer is not necessarilly NULL
  255.         // terminated.  Note that in a practical implementation, we
  256.         // could just extract the element we added, since it ends up
  257.         // NULL terminated.
  258.         //
  259.  
  260.         szPrimaryDomainName = (LPWSTR)HeapAlloc(
  261.             GetProcessHeap(), 0,
  262.             PrimaryDomain->Name.Length + sizeof(WCHAR) // existing length + NULL
  263.             );
  264.  
  265.         if(szPrimaryDomainName != NULL) {
  266.             //
  267.             // copy the existing buffer to the new storage, appending a NULL
  268.             //
  269.             lstrcpynW(
  270.                 szPrimaryDomainName,
  271.                 PrimaryDomain->Name.Buffer,
  272.                 (PrimaryDomain->Name.Length / sizeof(WCHAR)) + 1
  273.                 );
  274.         }
  275.  
  276.         LsaFreeMemory(PrimaryDomain);
  277.  
  278.         if(szPrimaryDomainName == NULL) goto cleanup;
  279.  
  280.         //
  281.         // get the primary domain controller computer name
  282.         //
  283.         nas = NetGetDCName(
  284.             NULL,
  285.             szPrimaryDomainName,
  286.             (LPBYTE *)&DomainController
  287.             );
  288.  
  289.         HeapFree(GetProcessHeap(), 0, szPrimaryDomainName);
  290.  
  291.         if(nas != NERR_Success)
  292.             goto cleanup;
  293.  
  294.         //
  295.         // close the policy handle, because we don't need it anymore
  296.         // for the workstation case, as we open a handle to a DC
  297.         // policy below
  298.         //
  299.         LsaClose(PolicyHandle);
  300.         PolicyHandle = INVALID_HANDLE_VALUE; // invalidate handle value
  301.  
  302.         //
  303.         // open the policy on the domain controller
  304.         //
  305.         Status = OpenPolicy(
  306.                     DomainController,
  307.                     POLICY_VIEW_LOCAL_INFORMATION,
  308.                     &PolicyHandle
  309.                     );
  310.  
  311.         //
  312.         // free the domaincontroller buffer
  313.         //
  314.         NetApiBufferFree(DomainController);
  315.  
  316.         if(Status != STATUS_SUCCESS)
  317.             goto cleanup;
  318.     }
  319.  
  320.     //
  321.     // build additional trusted domain(s) list and indicate if successful
  322.     //
  323.     bSuccess = EnumTrustedDomains(PolicyHandle);
  324.  
  325. cleanup:
  326.  
  327.     //
  328.     // close the policy handle
  329.     //
  330.     if(PolicyHandle != INVALID_HANDLE_VALUE)
  331.         LsaClose(PolicyHandle);
  332.  
  333.     if(!bSuccess) {
  334.         if(Status != STATUS_SUCCESS)
  335.             SetLastError( LsaNtStatusToWinError(Status) );
  336.         else if(nas != NERR_Success)
  337.             SetLastError( nas );
  338.     }
  339.  
  340.     return bSuccess;
  341. }
  342.  
  343. BOOL
  344. EnumTrustedDomains(
  345.     LSA_HANDLE PolicyHandle
  346.     )
  347. {
  348.     LSA_ENUMERATION_HANDLE lsaEnumHandle=0; // start an enum
  349.     PLSA_TRUST_INFORMATION TrustInfo;
  350.     ULONG ulReturned;               // number of items returned
  351.     ULONG ulCounter;                // counter for items returned
  352.     NTSTATUS Status;
  353.  
  354.     do {
  355.         Status = LsaEnumerateTrustedDomains(
  356.                         PolicyHandle,   // open policy handle
  357.                         &lsaEnumHandle, // enumeration tracker
  358.                         &TrustInfo,     // buffer to receive data
  359.                         32000,          // recommended buffer size
  360.                         &ulReturned     // number of items returned
  361.                         );
  362.         //
  363.         // get out if an error occurred
  364.         //
  365.         if( (Status != STATUS_SUCCESS) &&
  366.             (Status != STATUS_MORE_ENTRIES) &&
  367.             (Status != STATUS_NO_MORE_ENTRIES)
  368.             ) {
  369.             SetLastError( LsaNtStatusToWinError(Status) );
  370.             return FALSE;
  371.         }
  372.  
  373.         //
  374.         // Display results
  375.         // Note: Sids are in TrustInfo[ulCounter].Sid
  376.         //
  377.         for(ulCounter = 0 ; ulCounter < ulReturned ; ulCounter++)
  378.             AddTrustToList(&TrustInfo[ulCounter].Name);
  379.  
  380.         //
  381.         // free the buffer
  382.         //
  383.         LsaFreeMemory(TrustInfo);
  384.  
  385.     } while (Status != STATUS_NO_MORE_ENTRIES);
  386.  
  387.     return TRUE;
  388. }
  389.  
  390. BOOL
  391. IsDomainController(
  392.     LPWSTR Server,
  393.     LPBOOL bDomainController
  394.     )
  395. {
  396.     PSERVER_INFO_101 si101;
  397.     NET_API_STATUS nas;
  398.  
  399.     nas = NetServerGetInfo(
  400.         Server,
  401.         101,    // info-level
  402.         (LPBYTE *)&si101
  403.         );
  404.  
  405.     if(nas != NERR_Success) {
  406.         SetLastError(nas);
  407.         return FALSE;
  408.     }
  409.  
  410.     if( (si101->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
  411.         (si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
  412.         //
  413.         // we are dealing with a DC
  414.         //
  415.         *bDomainController = TRUE;
  416.     } else {
  417.         *bDomainController = FALSE;
  418.     }
  419.  
  420.     NetApiBufferFree(si101);
  421.  
  422.     return TRUE;
  423. }
  424.  
  425. BOOL
  426. AddTrustToList(
  427.     PLSA_UNICODE_STRING UnicodeString
  428.     )
  429. {
  430.     if(g_TrustCount >= ELEMENT_COUNT) return FALSE;
  431.  
  432.     //
  433.     // allocate storage for array element
  434.     //
  435.     g_TrustList[g_TrustCount] = (LPWSTR)HeapAlloc(
  436.         GetProcessHeap(), 0,
  437.         UnicodeString->Length + sizeof(WCHAR) // existing length + NULL
  438.         );
  439.  
  440.     if(g_TrustList[g_TrustCount] == NULL) return FALSE;
  441.  
  442.     //
  443.     // copy the existing buffer to the new storage, appending a NULL
  444.     //
  445.     lstrcpynW(
  446.         g_TrustList[g_TrustCount],
  447.         UnicodeString->Buffer,
  448.         (UnicodeString->Length / sizeof(WCHAR)) + 1
  449.         );
  450.  
  451.     g_TrustCount++; // increment the trust count
  452.  
  453.     return TRUE;
  454. }
  455.  
  456. void
  457. InitLsaString(
  458.     PLSA_UNICODE_STRING LsaString,
  459.     LPWSTR String
  460.     )
  461. {
  462.     DWORD StringLength;
  463.  
  464.     if (String == NULL) {
  465.         LsaString->Buffer = NULL;
  466.         LsaString->Length = 0;
  467.         LsaString->MaximumLength = 0;
  468.  
  469.         return;
  470.     }
  471.  
  472.     StringLength = lstrlenW(String);
  473.     LsaString->Buffer = String;
  474.     LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  475.     LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
  476. }
  477.  
  478. NTSTATUS
  479. OpenPolicy(
  480.     LPWSTR ServerName,
  481.     DWORD DesiredAccess,
  482.     PLSA_HANDLE PolicyHandle
  483.     )
  484. {
  485.     LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  486.     LSA_UNICODE_STRING ServerString;
  487.     PLSA_UNICODE_STRING Server;
  488.  
  489.     //
  490.     // Always initialize the object attributes to all zeroes
  491.     //
  492.     ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  493.  
  494.     if(ServerName != NULL) {
  495.         //
  496.         // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  497.         //
  498.         InitLsaString(&ServerString, ServerName);
  499.  
  500.         Server = &ServerString;
  501.     } else {
  502.         Server = NULL;
  503.     }
  504.  
  505.     //
  506.     // Attempt to open the policy
  507.     //
  508.     return LsaOpenPolicy(
  509.                 Server,
  510.                 &ObjectAttributes,
  511.                 DesiredAccess,
  512.                 PolicyHandle
  513.                 );
  514. }
  515.  
  516. void
  517. DisplayWinError(
  518.     LPSTR szAPI,    // pointer to failed API name
  519.     DWORD dwLastError
  520.     )
  521. {
  522.     HMODULE hModule = NULL;
  523.     LPSTR MessageBuffer;
  524.     DWORD dwBufferLength;
  525.  
  526.     fprintf(stderr,"%s error! (rc=%lu)\n", szAPI, dwLastError);
  527.  
  528.     if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
  529.         hModule = LoadLibraryEx(
  530.             TEXT("netmsg.dll"),
  531.             NULL,
  532.             LOAD_LIBRARY_AS_DATAFILE
  533.             );
  534.     }
  535.  
  536.     if(dwBufferLength=FormatMessageA(
  537.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  538.         FORMAT_MESSAGE_IGNORE_INSERTS |
  539.         FORMAT_MESSAGE_FROM_SYSTEM |
  540.         ((hModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0),
  541.         hModule, // module to get message from
  542.         dwLastError,
  543.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
  544.         (LPSTR) &MessageBuffer,
  545.         0,
  546.         NULL
  547.         ))
  548.     {
  549.         DWORD dwBytesWritten;
  550.  
  551.         //
  552.         // Output message string on stderr
  553.         //
  554.         WriteFile(
  555.             GetStdHandle(STD_ERROR_HANDLE),
  556.             MessageBuffer,
  557.             dwBufferLength,
  558.             &dwBytesWritten,
  559.             NULL
  560.             );
  561.  
  562.         //
  563.         // free the buffer allocated by the system
  564.         //
  565.         LocalFree(MessageBuffer);
  566.     }
  567.  
  568.     if(hModule != NULL)
  569.         FreeLibrary(hModule);
  570. }
  571.  
  572.