AccountInfo.cpp revision fcb5e646e4d775539e348fa21ba13307f2695bf5
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
4b6dc226f78862286daa69fba761eac9fd5da16aAutomatic Updater * Portions Copyright (C) 2001, 2002, 2004, 2007, 2009, 2013, 2016 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * License, v. 2.0. If a copy of the MPL was not distributed with this
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews/* $Id: AccountInfo.cpp,v 1.10 2009/09/29 23:48:04 tbox Exp $ */
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews/* Compiled with UNICODE */
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews#include "stdafx.h"
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews#include <windows.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <lm.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <ntsecapi.h>
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/ntgroups.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <isc/result.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include "AccountInfo.h"
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define MAX_NAME_LENGTH 256
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
12ff7274fe2ea531ecca6a71fb9f7e1ae92da389Mark AndrewsNTSTATUS
12ff7274fe2ea531ecca6a71fb9f7e1ae92da389Mark AndrewsOpenPolicy(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPWSTR ServerName, /* machine to open policy on (Unicode) */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews DWORD DesiredAccess, /* desired access to policy */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews PLSA_HANDLE PolicyHandle /* resultant policy handle */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews );
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark AndrewsBOOL
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsGetAccountSid(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPTSTR SystemName, /* where to lookup account */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPTSTR AccountName, /* account of interest */
0da29be670f6fa5b2a6320d9d843bc8b802c153aMark Andrews PSID *Sid /* resultant buffer containing SID */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews );
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsNTSTATUS
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsSetPrivilegeOnAccount(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LSA_HANDLE PolicyHandle, /* open policy handle */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PSID AccountSid, /* SID to grant privilege to */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews BOOL bEnable /* enable or disable */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews );
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsNTSTATUS
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsGetPrivilegesOnAccount(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LSA_HANDLE PolicyHandle, /* open policy handle */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PSID AccountSid, /* SID to grant privilege to */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews wchar_t **PrivList, /* Ptr to List of Privileges found */
1676408640d8283c9f17eec0b183e1302ea7fd70Mark Andrews unsigned int *PrivCount /* total number of Privileges in list */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews );
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsNTSTATUS
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsAddPrivilegeToAcccount(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPTSTR AccountName, /* Name of the account */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPWSTR PrivilegeName /* Privilege to Add */
0da29be670f6fa5b2a6320d9d843bc8b802c153aMark Andrews );
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0da29be670f6fa5b2a6320d9d843bc8b802c153aMark Andrewsvoid
0da29be670f6fa5b2a6320d9d843bc8b802c153aMark AndrewsInitLsaString(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PLSA_UNICODE_STRING LsaString, /* destination */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPWSTR String /* source (Unicode) */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews );
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsvoid
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsDisplayNtStatus(
1676408640d8283c9f17eec0b183e1302ea7fd70Mark Andrews LPSTR szAPI, /* pointer to function name (ANSI) */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NTSTATUS Status /* NTSTATUS error value */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews );
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsvoid
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsDisplayWinError(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LPSTR szAPI, /* pointer to function name (ANSI) */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DWORD WinError /* DWORD WinError */
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews );
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews#ifndef STATUS_SUCCESS
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews#endif
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews/*
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * Note that this code only retrieves the list of privileges of the
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * requested account or group. However, all accounts belong to the
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * Everyone group even though that group is not returned by the
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * calls to get the groups to which that account belongs.
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews * The Everyone group has two privileges associated with it:
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * SeChangeNotifyPrivilege and SeNetworkLogonRight
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews * It is not advisable to disable or remove these privileges
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews * from the group nor can the account be removed from the Everyone
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * group
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The None group has no privileges associated with it and is the group
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * to which an account belongs if it is associated with no group.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsint
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsGetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char **Accounts, unsigned int *totalAccounts,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int maxAccounts)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LSA_HANDLE PolicyHandle;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews TCHAR AccountName[256]; /* static account name buffer */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PSID pSid;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int i;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NTSTATUS Status;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t istatus;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int iRetVal = RTN_ERROR; /* assume error from main */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int n;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Open the policy on the target machine.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((Status = OpenPolicy(NULL,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews POLICY_LOOKUP_NAMES,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &PolicyHandle)) != STATUS_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_ERROR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Let's see if the account exists. Return if not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (n < 0 || (size_t)n >= sizeof(AccountName)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_ERROR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (!GetAccountSid(NULL, AccountName, &pSid)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_NOACCOUNT);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Find out what groups the account belongs to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews totalAccounts);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (istatus == ISC_R_NOMEMORY) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_NOMEMORY);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else if (istatus != ISC_R_SUCCESS) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_ERROR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews Accounts[*totalAccounts] = name; /* Add the account to the list */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (*totalAccounts)++;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Loop through each Account to get the list of privileges
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews for (i = 0; i < *totalAccounts; i++) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"),
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews Accounts[i]);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews if (n < 0 || (size_t)n >= sizeof(AccountName)) {
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews continue;
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews }
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews /* Obtain the SID of the user/group. */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews if (!GetAccountSid(NULL, AccountName, &pSid)) {
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews continue; /* Try the next one */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews }
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews /* Get the Privileges allocated to this SID */
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PrivList, PrivCount)) == STATUS_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews {
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews iRetVal=RTN_OK;
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews if (pSid != NULL)
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews HeapFree(GetProcessHeap(), 0, pSid);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews } else {
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews if (pSid != NULL)
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews HeapFree(GetProcessHeap(), 0, pSid);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews continue; /* Try the next one */
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews }
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews }
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews /*
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews * Close the policy handle.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (*totalAccounts)--; /* Correct for the number of groups */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return iRetVal;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsBOOL
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsCreateServiceAccount(char *name, char *password) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NTSTATUS retstat;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews USER_INFO_1 ui;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DWORD dwLevel = 1;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DWORD dwError = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NET_API_STATUS nStatus;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews size_t namelen = strlen(name);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews size_t passwdlen = strlen(password);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews wchar_t AccountName[MAX_NAME_LENGTH];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews wchar_t AccountPassword[MAX_NAME_LENGTH];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews mbstowcs(AccountName, name, namelen + 1);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews mbstowcs(AccountPassword, password, passwdlen + 1);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Set up the USER_INFO_1 structure.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * USER_PRIV_USER: name is required here when creating an account
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * rather than an administrator or a guest.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_name = (LPWSTR) &AccountName;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_password = (LPWSTR) &AccountPassword;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_priv = USER_PRIV_USER;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_home_dir = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_comment = L"ISC BIND Service Account";
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews UF_SCRIPT;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ui.usri1_script_path = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Call the NetUserAdd function, specifying level 1.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews if (nStatus != NERR_Success)
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews return (FALSE);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews return (TRUE);
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews}
37dee1ff94960a61243f611c0f87f8c316815c53Mark Andrews
37dee1ff94960a61243f611c0f87f8c316815c53Mark AndrewsNTSTATUS
37dee1ff94960a61243f611c0f87f8c316815c53Mark AndrewsAddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews LSA_HANDLE PolicyHandle;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews TCHAR AccountName[256]; /* static account name buffer */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PSID pSid;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NTSTATUS Status;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned long err;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int n;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Open the policy on the target machine.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews != STATUS_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_ERROR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Let's see if the account exists. Return if not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews n = wnsprintf(AccountName, sizeof(AccountName), TEXT("%hS"), name);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (n < 0 || (size_t)n >= sizeof(AccountName)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_ERROR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (!GetAccountSid(NULL, AccountName, &pSid)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_NOACCOUNT);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews pSid, PrivilegeName, TRUE));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaClose(PolicyHandle);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (err == ERROR_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (RTN_OK);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (err);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsvoid
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsInitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews size_t StringLength;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (String == NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->Buffer = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->Length = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->MaximumLength = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews StringLength = wcslen(String);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->Buffer = String;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsNTSTATUS
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsOpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LSA_OBJECT_ATTRIBUTES ObjectAttributes;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LSA_UNICODE_STRING ServerString;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PLSA_UNICODE_STRING Server = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Always initialize the object attributes to all zeroes.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (ServerName != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews InitLsaString(&ServerString, ServerName);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews Server = &ServerString;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Attempt to open the policy.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PolicyHandle));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark AndrewsBOOL
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark AndrewsGetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews LPTSTR ReferencedDomain = NULL;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews DWORD cbSid = 128; /* initial allocation attempt */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews DWORD cbReferencedDomain = 16; /* initial allocation size */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews SID_NAME_USE peUse;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews BOOL bSuccess = FALSE; /* assume this function will fail */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews __try {
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews /*
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews * initial memory allocations
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews __leave;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews cbReferencedDomain)) == NULL) __leave;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews /*
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews * Obtain the SID of the specified account on the specified system.
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews ReferencedDomain, &cbReferencedDomain,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews &peUse))
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews {
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews /* reallocate memory */
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews *Sid, cbSid)) == NULL) __leave;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
GetProcessHeap(), 0, ReferencedDomain,
cbReferencedDomain)) == NULL)
__leave;
}
else
__leave;
}
bSuccess = TRUE;
} /* finally */
__finally {
/* Cleanup and indicate failure, if appropriate. */
HeapFree(GetProcessHeap(), 0, ReferencedDomain);
if (!bSuccess) {
if (*Sid != NULL) {
HeapFree(GetProcessHeap(), 0, *Sid);
*Sid = NULL;
}
}
}
return (bSuccess);
}
NTSTATUS
SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
LPWSTR PrivilegeName, BOOL bEnable)
{
LSA_UNICODE_STRING PrivilegeString;
/* Create a LSA_UNICODE_STRING for the privilege name. */
InitLsaString(&PrivilegeString, PrivilegeName);
/* grant or revoke the privilege, accordingly */
if (bEnable)
return (LsaAddAccountRights(PolicyHandle, AccountSid,
&PrivilegeString, 1));
else
return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
FALSE, &PrivilegeString, 1));
}
NTSTATUS
GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
wchar_t **PrivList, unsigned int *PrivCount)
{
NTSTATUS Status;
LSA_UNICODE_STRING *UserRights;
ULONG CountOfRights;
unsigned int retlen = 0;
DWORD i, j;
int found;
Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
&UserRights, &CountOfRights);
/* Only continue if there is something */
if (UserRights == NULL || Status != STATUS_SUCCESS)
return (Status);
for (i = 0; i < CountOfRights; i++) {
found = -1;
retlen = UserRights[i].Length/sizeof(wchar_t);
for (j = 0; j < *PrivCount; j++) {
found = wcsncmp(PrivList[j], UserRights[i].Buffer,
retlen);
if (found == 0)
break;
}
if (found != 0) {
PrivList[*PrivCount] =
(wchar_t *)malloc(UserRights[i].MaximumLength);
if (PrivList[*PrivCount] == NULL)
return (RTN_NOMEMORY);
wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
retlen);
PrivList[*PrivCount][retlen] = L'\0';
(*PrivCount)++;
}
}
return (Status);
}
void
DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
/* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
}
void
DisplayWinError(LPSTR szAPI, DWORD WinError) {
LPSTR MessageBuffer;
DWORD dwBufferLength;
if (dwBufferLength=FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WinError, GetUserDefaultLangID(),
(LPSTR) &MessageBuffer, 0, NULL)){
DWORD dwBytesWritten; /* unused */
/* Output message string on stderr. */
WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
dwBufferLength, &dwBytesWritten, NULL);
/* Free the buffer allocated by the system. */
LocalFree(MessageBuffer);
}
}