"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.12.3-P1/bin/win32/BINDInstall/AccountInfo.cpp" (7 Dec 2018, 11733 Bytes) of package /linux/misc/dns/bind9/9.12.3-P1/bind-9.12.3-P1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /* Compiled with UNICODE */
   13 
   14 #include "stdafx.h"
   15 
   16 #include <windows.h>
   17 #include <lm.h>
   18 #include <ntsecapi.h>
   19 
   20 #include <isc/ntgroups.h>
   21 #include <isc/result.h>
   22 #include "AccountInfo.h"
   23 
   24 #define MAX_NAME_LENGTH 256
   25 
   26 NTSTATUS
   27 OpenPolicy(
   28     LPWSTR ServerName,      /* machine to open policy on (Unicode) */
   29     DWORD DesiredAccess,    /* desired access to policy */
   30     PLSA_HANDLE PolicyHandle    /* resultant policy handle */
   31     );
   32 
   33 BOOL
   34 GetAccountSid(
   35     LPTSTR SystemName,      /* where to lookup account */
   36     LPTSTR AccountName,     /* account of interest */
   37     PSID *Sid           /* resultant buffer containing SID */
   38     );
   39 
   40 NTSTATUS
   41 SetPrivilegeOnAccount(
   42     LSA_HANDLE PolicyHandle,    /* open policy handle */
   43     PSID AccountSid,        /* SID to grant privilege to */
   44     LPWSTR PrivilegeName,   /* privilege to grant (Unicode) */
   45     BOOL bEnable        /* enable or disable */
   46     );
   47 
   48 NTSTATUS
   49 GetPrivilegesOnAccount(
   50     LSA_HANDLE PolicyHandle,    /* open policy handle */
   51     PSID AccountSid,        /* SID to grant privilege to */
   52     wchar_t **PrivList,     /* Ptr to List of Privileges found */
   53     unsigned int *PrivCount /* total number of Privileges in list */
   54     );
   55 
   56 NTSTATUS
   57 AddPrivilegeToAcccount(
   58     LPTSTR AccountName,     /* Name of the account */
   59     LPWSTR PrivilegeName    /* Privilege to Add */
   60     );
   61 
   62 void
   63 InitLsaString(
   64     PLSA_UNICODE_STRING LsaString,  /* destination */
   65     LPWSTR String           /* source (Unicode) */
   66     );
   67 
   68 void
   69 DisplayNtStatus(
   70     LPSTR szAPI,        /* pointer to function name (ANSI) */
   71     NTSTATUS Status     /* NTSTATUS error value */
   72     );
   73 
   74 void
   75 DisplayWinError(
   76     LPSTR szAPI,        /* pointer to function name (ANSI) */
   77     DWORD WinError      /* DWORD WinError */
   78     );
   79 
   80 #ifndef STATUS_SUCCESS
   81 #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
   82 #endif
   83 
   84 /*
   85  * Note that this code only retrieves the list of privileges of the
   86  * requested account or group. However, all accounts belong to the
   87  * Everyone group even though that group is not returned by the
   88  * calls to get the groups to which that account belongs.
   89  * The Everyone group has two privileges associated with it:
   90  * SeChangeNotifyPrivilege and SeNetworkLogonRight
   91  * It is not advisable to disable or remove these privileges
   92  * from the group nor can the account be removed from the Everyone
   93  * group
   94  * The None group has no privileges associated with it and is the group
   95  * to which an account belongs if it is associated with no group.
   96  */
   97 
   98 int
   99 GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
  100              char **Accounts, unsigned int *totalAccounts,
  101              int maxAccounts)
  102 {
  103     LSA_HANDLE PolicyHandle;
  104     TCHAR AccountName[256];     /* static account name buffer */
  105     PSID pSid;
  106     unsigned int i;
  107     NTSTATUS Status;
  108     isc_result_t istatus;
  109     int iRetVal = RTN_ERROR;    /* assume error from main */
  110     int n;
  111 
  112     /*
  113      * Open the policy on the target machine.
  114      */
  115     if ((Status = OpenPolicy(NULL,
  116                  POLICY_LOOKUP_NAMES,
  117                  &PolicyHandle)) != STATUS_SUCCESS)
  118         return (RTN_ERROR);
  119 
  120     /*
  121      * Let's see if the account exists. Return if not
  122      */
  123     n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
  124     if (n < 0 || (size_t)n >= sizeof(AccountName)) {
  125         LsaClose(PolicyHandle);
  126         return (RTN_ERROR);
  127     }
  128 
  129     if (!GetAccountSid(NULL, AccountName, &pSid)) {
  130         LsaClose(PolicyHandle);
  131         return (RTN_NOACCOUNT);
  132     }
  133 
  134     /*
  135      * Find out what groups the account belongs to
  136      */
  137     istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
  138                           totalAccounts);
  139     if (istatus == ISC_R_NOMEMORY) {
  140         LsaClose(PolicyHandle);
  141         return (RTN_NOMEMORY);
  142     } else if (istatus != ISC_R_SUCCESS) {
  143         LsaClose(PolicyHandle);
  144         return (RTN_ERROR);
  145     }
  146 
  147     Accounts[*totalAccounts] = name; /* Add the account to the list */
  148     (*totalAccounts)++;
  149 
  150     /*
  151      * Loop through each Account to get the list of privileges
  152      */
  153     for (i = 0; i < *totalAccounts; i++) {
  154         n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"),
  155                   Accounts[i]);
  156         if (n < 0 || (size_t)n >= sizeof(AccountName)) {
  157             continue;
  158         }
  159 
  160         /* Obtain the SID of the user/group. */
  161         if (!GetAccountSid(NULL, AccountName, &pSid)) {
  162             continue;   /* Try the next one */
  163         }
  164 
  165         /* Get the Privileges allocated to this SID */
  166         if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
  167             PrivList, PrivCount)) == STATUS_SUCCESS)
  168         {
  169             iRetVal=RTN_OK;
  170             if (pSid != NULL)
  171                 HeapFree(GetProcessHeap(), 0, pSid);
  172         } else {
  173             if (pSid != NULL)
  174                 HeapFree(GetProcessHeap(), 0, pSid);
  175             continue;   /* Try the next one */
  176         }
  177     }
  178 
  179     /*
  180      * Close the policy handle.
  181      */
  182     LsaClose(PolicyHandle);
  183 
  184     (*totalAccounts)--; /* Correct for the number of groups */
  185     return iRetVal;
  186 }
  187 
  188 BOOL
  189 CreateServiceAccount(char *name, char *password) {
  190     NTSTATUS retstat;
  191     USER_INFO_1 ui;
  192     DWORD dwLevel = 1;
  193     DWORD dwError = 0;
  194     NET_API_STATUS nStatus;
  195 
  196     size_t namelen = strlen(name);
  197     size_t passwdlen = strlen(password);
  198     wchar_t AccountName[MAX_NAME_LENGTH];
  199     wchar_t AccountPassword[MAX_NAME_LENGTH];
  200 
  201     mbstowcs(AccountName, name, namelen + 1);
  202     mbstowcs(AccountPassword, password, passwdlen + 1);
  203 
  204     /*
  205      * Set up the USER_INFO_1 structure.
  206      * USER_PRIV_USER: name is required here when creating an account
  207      * rather than an administrator or a guest.
  208      */
  209 
  210     ui.usri1_name = (LPWSTR) &AccountName;
  211     ui.usri1_password = (LPWSTR) &AccountPassword;
  212     ui.usri1_priv = USER_PRIV_USER;
  213     ui.usri1_home_dir = NULL;
  214     ui.usri1_comment = L"ISC BIND Service Account";
  215     ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
  216              UF_SCRIPT;
  217     ui.usri1_script_path = NULL;
  218     /*
  219      * Call the NetUserAdd function, specifying level 1.
  220      */
  221     nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
  222 
  223     if (nStatus != NERR_Success)
  224         return (FALSE);
  225 
  226     retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
  227     return (TRUE);
  228 }
  229 
  230 NTSTATUS
  231 AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
  232     LSA_HANDLE PolicyHandle;
  233     TCHAR AccountName[256];     /* static account name buffer */
  234     PSID pSid;
  235     NTSTATUS Status;
  236     unsigned long err;
  237     int n;
  238 
  239     /*
  240      * Open the policy on the target machine.
  241      */
  242     if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
  243         != STATUS_SUCCESS)
  244         return (RTN_ERROR);
  245 
  246     /*
  247      * Let's see if the account exists. Return if not
  248      */
  249     n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
  250     if (n < 0 || (size_t)n >= sizeof(AccountName)) {
  251         LsaClose(PolicyHandle);
  252         return (RTN_ERROR);
  253     }
  254 
  255     if (!GetAccountSid(NULL, AccountName, &pSid)) {
  256         LsaClose(PolicyHandle);
  257         return (RTN_NOACCOUNT);
  258     }
  259 
  260     err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
  261         pSid, PrivilegeName, TRUE));
  262 
  263     LsaClose(PolicyHandle);
  264     if (err == ERROR_SUCCESS)
  265         return (RTN_OK);
  266     else
  267         return (err);
  268 }
  269 
  270 void
  271 InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
  272     size_t StringLength;
  273 
  274     if (String == NULL) {
  275         LsaString->Buffer = NULL;
  276         LsaString->Length = 0;
  277         LsaString->MaximumLength = 0;
  278         return;
  279     }
  280 
  281     StringLength = wcslen(String);
  282     LsaString->Buffer = String;
  283     LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  284     LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
  285 }
  286 
  287 NTSTATUS
  288 OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
  289     LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  290     LSA_UNICODE_STRING ServerString;
  291     PLSA_UNICODE_STRING Server = NULL;
  292 
  293     /*
  294      * Always initialize the object attributes to all zeroes.
  295      */
  296     ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  297 
  298     if (ServerName != NULL) {
  299         /*
  300          * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  301          */
  302         InitLsaString(&ServerString, ServerName);
  303         Server = &ServerString;
  304     }
  305 
  306     /*
  307      * Attempt to open the policy.
  308      */
  309     return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
  310         PolicyHandle));
  311 }
  312 
  313 BOOL
  314 GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
  315     LPTSTR ReferencedDomain = NULL;
  316     DWORD cbSid = 128;    /* initial allocation attempt */
  317     DWORD cbReferencedDomain = 16; /* initial allocation size */
  318     SID_NAME_USE peUse;
  319     BOOL bSuccess = FALSE; /* assume this function will fail */
  320 
  321     __try {
  322         /*
  323          * initial memory allocations
  324          */
  325         if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
  326             __leave;
  327 
  328         if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
  329                        cbReferencedDomain)) == NULL) __leave;
  330 
  331         /*
  332          * Obtain the SID of the specified account on the specified system.
  333          */
  334         while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
  335                       ReferencedDomain, &cbReferencedDomain,
  336                       &peUse))
  337         {
  338             if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  339                 /* reallocate memory */
  340                 if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
  341                     *Sid, cbSid)) == NULL) __leave;
  342 
  343                 if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
  344                     GetProcessHeap(), 0, ReferencedDomain,
  345                     cbReferencedDomain)) == NULL)
  346                 __leave;
  347             }
  348             else
  349                 __leave;
  350         }
  351         bSuccess = TRUE;
  352     } /* finally */
  353     __finally {
  354 
  355         /* Cleanup and indicate failure, if appropriate. */
  356 
  357         HeapFree(GetProcessHeap(), 0, ReferencedDomain);
  358 
  359         if (!bSuccess) {
  360             if (*Sid != NULL) {
  361                 HeapFree(GetProcessHeap(), 0, *Sid);
  362                 *Sid = NULL;
  363             }
  364         }
  365 
  366     }
  367 
  368     return (bSuccess);
  369 }
  370 
  371 NTSTATUS
  372 SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
  373               LPWSTR PrivilegeName, BOOL bEnable)
  374 {
  375     LSA_UNICODE_STRING PrivilegeString;
  376 
  377     /* Create a LSA_UNICODE_STRING for the privilege name. */
  378     InitLsaString(&PrivilegeString, PrivilegeName);
  379 
  380     /* grant or revoke the privilege, accordingly */
  381     if (bEnable)
  382         return (LsaAddAccountRights(PolicyHandle, AccountSid,
  383             &PrivilegeString, 1));
  384     else
  385         return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
  386             FALSE, &PrivilegeString, 1));
  387 }
  388 
  389 NTSTATUS
  390 GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
  391                wchar_t **PrivList, unsigned int *PrivCount)
  392 {
  393     NTSTATUS Status;
  394     LSA_UNICODE_STRING *UserRights;
  395     ULONG CountOfRights;
  396     unsigned int retlen = 0;
  397     DWORD i, j;
  398     int found;
  399 
  400     Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
  401         &UserRights, &CountOfRights);
  402     /* Only continue if there is something */
  403     if (UserRights == NULL || Status != STATUS_SUCCESS)
  404         return (Status);
  405 
  406     for (i = 0; i < CountOfRights; i++) {
  407         found = -1;
  408         retlen = UserRights[i].Length/sizeof(wchar_t);
  409         for (j = 0; j < *PrivCount; j++) {
  410             found = wcsncmp(PrivList[j], UserRights[i].Buffer,
  411                     retlen);
  412             if (found == 0)
  413                 break;
  414         }
  415         if (found != 0) {
  416             PrivList[*PrivCount] =
  417                 (wchar_t *)malloc(UserRights[i].MaximumLength);
  418             if (PrivList[*PrivCount] == NULL)
  419                 return (RTN_NOMEMORY);
  420 
  421             wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
  422                 retlen);
  423             PrivList[*PrivCount][retlen] = L'\0';
  424             (*PrivCount)++;
  425         }
  426 
  427     }
  428 
  429     return (Status);
  430 }
  431 
  432 void
  433 DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
  434     /* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
  435     DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
  436 }
  437 
  438 void
  439 DisplayWinError(LPSTR szAPI, DWORD WinError) {
  440     LPSTR MessageBuffer;
  441     DWORD dwBufferLength;
  442 
  443     if (dwBufferLength=FormatMessageA(
  444         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  445         NULL, WinError, GetUserDefaultLangID(),
  446         (LPSTR) &MessageBuffer, 0, NULL)){
  447         DWORD dwBytesWritten; /* unused */
  448 
  449         /* Output message string on stderr. */
  450         WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
  451               dwBufferLength, &dwBytesWritten, NULL);
  452 
  453         /* Free the buffer allocated by the system. */
  454         LocalFree(MessageBuffer);
  455     }
  456 }