int main(void) { // GetCurrentProcess cannot fail HANDLE hProcess = GetCurrentProcess(); if (OpenProcessToken(hProcess, TOKEN_READ, &hProcess)) { LUID seCreateSymbolicLinkPrivilege; if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege)) { DWORD length; printf("SeCreateSymbolicLinkPrivilege = %ld, %ld\n", seCreateSymbolicLinkPrivilege.HighPart, seCreateSymbolicLinkPrivilege.LowPart); if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)malloc(length); if (GetTokenInformation(hProcess, TokenPrivileges, privileges, length, &length)) { BOOL found = FALSE; DWORD count = privileges->PrivilegeCount; printf("User has %ld privileges\n", count); if (count > 0) { LUID_AND_ATTRIBUTES* privs = privileges->Privileges; while (count-- > 0 && !luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege)) privs++; found = (count > 0); } printf("User does%s have the SeCreateSymbolicLinkPrivilege\n", (found ? "" : "n't")); } else { fprintf(stderr, "Second GetTokenInformation failed\n"); } free(privileges); } else { fprintf(stderr, "First GetTokenInformation failed\n"); } } else { fprintf(stderr, "Impossible output from GetTokenInformation\n"); } } else { fprintf(stderr, "LookupPrivilegeValue failed\n"); } CloseHandle(hProcess); } else { fprintf(stderr, "OpenProcessToken failed\n"); } LSA_HANDLE hPolicy; NTSTATUS r; LSA_OBJECT_ATTRIBUTES attributes = {0, NULL, NULL, 0, NULL, NULL}; attributes.Length = sizeof(attributes); LUID seCreateSymbolicLinkPrivilege; if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege)) { // POLICY_LOOKUP_NAMES: LsaLookupNames2, LsaEnumerateAccountRights, LsaLookupSids, LsaAddAccountRights // POLICY_VIEW_LOCAL_INFORMATION: LsaEnumerateAccountsWithUserRight // Elevation: LsaEnumerateAccountRights, LsaEnumerateAccountsWithUserRight, LsaRemoveAccountRights, LsaAddAccountRights if (NT_SUCCESS(r = LsaOpenPolicy(NULL, &attributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy))) { LSA_REFERENCED_DOMAIN_LIST* referencedDomains; LSA_TRANSLATED_SID2* sids; LSA_UNICODE_STRING name; name.Buffer = L"Users"; name.Length = wcslen(name.Buffer) * sizeof(WCHAR); name.MaximumLength = name.Length + sizeof(WCHAR); if (NT_SUCCESS(r = LsaLookupNames2(hPolicy, LSA_LOOKUP_ISOLATED_AS_LOCAL, 1, &name, &referencedDomains, &sids))) { LSA_UNICODE_STRING* rights; ULONG count; LsaFreeMemory(referencedDomains); if (NT_SUCCESS(r = LsaEnumerateAccountRights(hPolicy, sids->Sid, &rights, &count))) { LSA_UNICODE_STRING* right = rights; printf("%ld right%s found\n", count, PLURAL(count)); while (count-- > 0) { printf(" %.*S\n", right->Length / 2, right->Buffer); right++; } LsaFreeMemory(rights); LSA_ENUMERATION_INFORMATION* allSidsRaw; LSA_UNICODE_STRING lsaCreateSymbolicLinkPrivilege; lsaCreateSymbolicLinkPrivilege.Buffer = SE_CREATE_SYMBOLIC_LINK_NAME; lsaCreateSymbolicLinkPrivilege.Length = wcslen(lsaCreateSymbolicLinkPrivilege.Buffer) * sizeof(WCHAR); lsaCreateSymbolicLinkPrivilege.MaximumLength = lsaCreateSymbolicLinkPrivilege.Length + sizeof(WCHAR); if (NT_SUCCESS(r = LsaEnumerateAccountsWithUserRight(hPolicy, &lsaCreateSymbolicLinkPrivilege, (void**)&allSidsRaw, &count))) { LSA_ENUMERATION_INFORMATION* sid = allSidsRaw; PSID* allSids; PSID* p; PLSA_TRANSLATED_NAME names; ULONG i = count; printf("%ld SID%s found\n", count, PLURAL(count)); p = allSids = (PSID*)malloc(count * sizeof(PSID)); while (i-- > 0) *p++ = (sid++)->Sid; if (NT_SUCCESS(r = LsaLookupSids(hPolicy, count, allSids, &referencedDomains, &names))) { PLSA_TRANSLATED_NAME name = names; BOOL usersAssigned = FALSE; LsaFreeMemory(referencedDomains); while (count-- > 0) { LPTSTR sidString; USHORT len = name->Name.Length / 2; ConvertSidToStringSid(*allSids++, &sidString); printf(" %.*S (%S)\n", len, name->Name.Buffer, sidString); usersAssigned |= (len > 4 && !wcsncmp(L"Users", name->Name.Buffer, len)); name++; LocalFree(sidString); } printf("Users had%s got SeCreateSymbolicLinkPrivilege\n", (usersAssigned ? "" : "n't")); if (usersAssigned) { if (!NT_SUCCESS(r = LsaRemoveAccountRights(hPolicy, sids->Sid, FALSE, &lsaCreateSymbolicLinkPrivilege, 1))) { fprintf(stderr, "Lsa failed with code %x\n", r); } } else { if (!NT_SUCCESS(r = LsaAddAccountRights(hPolicy, sids->Sid, &lsaCreateSymbolicLinkPrivilege, 1))) { fprintf(stderr, "LsaAddAccountRights failed with code %x\n", r); } } LsaFreeMemory(names); } else { fprintf(stderr, "LsaLookupSids2 failed with code %x\n", r); } LsaFreeMemory(allSidsRaw); free(allSids); } else { fprintf(stderr, "LsaEnumerateAccountsWithUserRight failed with code %x\n", r); } } else { fprintf(stderr, "LsaEnumerateAccountRights failed with code %x\n", r); } LsaFreeMemory(sids); } else { fprintf(stderr, "LsaLookupNames2 failed with code %x\n", r); } LsaClose(hPolicy); } else { fprintf(stderr, "LsaOpenPolicy failed with code %x\n", r); } } else { fprintf(stderr, "LookupPrivilegeValue failed\n"); } }
BOOL lsp_add(LSA_HANDLE lsa_handle, LPTSTR user, LPTSTR privilegeConstant) { LSA_ACCOUNT account; NTSTATUS nt_status; LSA_UNICODE_STRING privilege; PSID sid; BOOL success = TRUE; if (!valid_privilege(&privilege, privilegeConstant)) return FALSE; if (!valid_user(lsa_handle, &sid, user)) return FALSE; if (!lsa_account_from_sid(lsa_handle, sid, &account)) { FreeSid(sid); return FALSE; } print_string(L"Adding %s to ", privilegeConstant); print_account(&account); print_string(L".\n"); nt_status = LsaAddAccountRights(lsa_handle, sid, &privilege, 1); if (nt_status != STATUS_SUCCESS) { FreeSid(sid); return lsa_error(nt_status, L"LsaAddAccountRights"); } FreeSid(sid); return TRUE; }
static VOID AddImpersonatePrivilege(VOID) { /* S-1-5-6 -- "Service" group */ static SID ServiceSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } }; NTSTATUS Status; LSA_HANDLE PolicyHandle; LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_UNICODE_STRING RightString; ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle); if (!NT_SUCCESS(Status)) { ERR("LsaOpenPolicy() failed with Status 0x%08lx\n", Status); return; } RtlInitUnicodeString(&RightString, L"SeImpersonatePrivilege"); Status = LsaAddAccountRights(PolicyHandle, &ServiceSid, &RightString, 1); if (!NT_SUCCESS(Status)) { ERR("LsaAddAccountRights(\"S-1-5-6\", \"%wZ\") failed with Status 0x%08lx\n", Status, &RightString); } LsaClose(PolicyHandle); }
HRESULT TCUserAccount::SetRight(LPTSTR pszPrivilege) { // Not supported under Windows9x if (IsWin9x()) return S_FALSE; // Fail if Init has not been called successfully if (!m_hPolicy || m_spSIDPrincipal.IsNull()) return E_UNEXPECTED; // Fail if the specified pointer is NULL if (!pszPrivilege) return E_POINTER; // Get a pointer to a UNICODE version of the specified privilege USES_CONVERSION; LPWSTR pszWidePrivilege = T2W(pszPrivilege); // Create an LSA_UNICODE_STRING for the specified privilege name LSA_UNICODE_STRING lsaString; lsaString.Length = (USHORT)(wcslen(pszWidePrivilege) * sizeof(WCHAR)); lsaString.MaximumLength = (USHORT)(lsaString.Length + sizeof(WCHAR)); lsaString.Buffer = pszWidePrivilege; // Attempt to add the specified privilege to the current user RETURN_FAILED(LsaAddAccountRights(m_hPolicy, m_spSIDPrincipal, &lsaString, 1)); // Indicate success return S_OK; }
/** * @brief * add_privilege - add_privilege: returns 0 if privname has been added for account * referenced by sid; otherwise, 1. * * @param[in] sid - The security identifier (SID) structure is a variable-length structure * used to uniquely identify users or groups. * @param[in] privname - privilege name * * @return int * @retval 1 : if privname has not been added for account referenced by sid * @retval 0 : if privname has been added for account referenced by sid */ int add_privilege(SID *sid, char *privname) { LSA_UNICODE_STRING rights; LSA_HANDLE h_policy = INVALID_HANDLE_VALUE; LSA_OBJECT_ATTRIBUTES obj_attrs; NTSTATUS lsa_stat; BOOL rval = 1; WCHAR *privnameW = NULL; int priv_len = 0; if (privname == NULL) { fprintf(stderr, "add_privilege: NULL privname\n"); return (1); } if (!IsValidSid(sid)) { fprintf(stderr, "add_privilege: Not a valid sid\n"); return (1); } priv_len = strlen(privname) + 1; privnameW = (WCHAR *)malloc(priv_len * sizeof(WCHAR)); if (privnameW == NULL) { fprintf(stderr, "add_privilege: malloc failed\n"); return (1); } mbstowcs(privnameW, privname, priv_len); init_lsa_string(&rights, privnameW); ZeroMemory(&obj_attrs, sizeof(obj_attrs)); if( LsaOpenPolicy(NULL, &obj_attrs, POLICY_ALL_ACCESS, &h_policy) \ != ERROR_SUCCESS ) { fprintf(stderr, "add_privilege: Unable to open policy!\n"); goto add_privilege_end; } if( (lsa_stat=LsaAddAccountRights( h_policy, sid, &rights, 1 )) != \ ERROR_SUCCESS ) { fprintf(stderr, "add_privilege: adding privilege %s failed! - err %d\n", privname, LsaNtStatusToWinError(lsa_stat)); goto add_privilege_end; } printf("\tadded %s\n", privname); rval = 0; add_privilege_end: if (h_policy != INVALID_HANDLE_VALUE) LsaClose(h_policy); if (privnameW != NULL) (void)free(privnameW); return (rval); }
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)); }
void GrantPrivilege(PSID sid, LPCWSTR userRight) { LSA_HANDLE hPolicy = OpenPolicy(POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT); try { LSA_UNICODE_STRING lsaUserRight; InitLsaString(&lsaUserRight, (LPWSTR)userRight); CheckRetVal(LsaAddAccountRights(hPolicy, sid, &lsaUserRight, 1)); LsaClose(hPolicy); } catch (const std::exception&) { LsaClose(hPolicy); throw; } }
static BOOL ObtainLockPagesPrivilege() { HANDLE token; PTOKEN_USER user = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) { DWORD size = 0; GetTokenInformation(token, TokenUser, NULL, 0, &size); if (size) { user = (PTOKEN_USER) LocalAlloc(LPTR, size); } GetTokenInformation(token, TokenUser, user, size, &size); CloseHandle(token); } if (!user) { return FALSE; } LSA_HANDLE handle; LSA_OBJECT_ATTRIBUTES attributes; ZeroMemory(&attributes, sizeof(attributes)); BOOL result = FALSE; if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) { LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) { LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it"); result = TRUE; } LsaClose(handle); } LocalFree(user); return result; }
NTSTATUS SetPrivilegeOnAccount( LSA_HANDLE PolicyHandle, // open policy handle PSID AccountSid, // SID to grant privilege to LPWSTR PrivilegeName, // privilege to grant (Unicode) BOOL bEnable // enable or disable ) { 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, // open policy handle AccountSid, // target SID &PrivilegeString, // privileges 1 // privilege count ); } else { return LsaRemoveAccountRights( PolicyHandle, // open policy handle AccountSid, // target SID FALSE, // do not disable all rights &PrivilegeString, // privileges 1 // privilege count ); } }
USHORT SERVICES_grant_privilege(const TEXT* account, pfnSvcError err_handler, const WCHAR* privilege) { /*************************************************** * * S E R V I C E _ g r a n t _ l o g o n _ r i g h t * *************************************************** * * Functional description * Grants the "Log on as a service" right to account. * This is a Windows NT, 2000, XP, 2003 security thing. * To run a service under an account other than LocalSystem, the account * must have this right. To succeed granting the right, the current user * must be an Administrator. * Returns FB_SUCCESS when actually granted the right. * Returns FB_LOGON_SRVC_RIGHT_ALREADY_DEFINED if right was already granted * to the user. * Returns FB_FAILURE on any error. * * OM - AUG 2003 - Initial implementation * OM - SEP 2003 - Control flow revision, no functional change * ***************************************************/ LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle; // Open the policy on the local machine. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); NTSTATUS lsaErr = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &PolicyHandle); if (lsaErr != (NTSTATUS) 0) return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaOpenPolicy", NULL); // Obtain the SID of the user/group. // First, dummy call to LookupAccountName to get the required buffer sizes. DWORD cbSid; DWORD cchDomain; cbSid = cchDomain = 0; SID_NAME_USE peUse; LookupAccountName(NULL, account, NULL, &cbSid, NULL, &cchDomain, &peUse); PSID pSid = (PSID) LocalAlloc(LMEM_ZEROINIT, cbSid); if (pSid == 0) { DWORD err = GetLastError(); LsaClose(PolicyHandle); return (*err_handler)(err, "LocalAlloc(Sid)", NULL); } TEXT* pDomain = (LPTSTR) LocalAlloc(LMEM_ZEROINIT, cchDomain); if (pDomain == 0) { DWORD err = GetLastError(); LsaClose(PolicyHandle); LocalFree(pSid); return (*err_handler)(err, "LocalAlloc(Domain)", NULL); } // Now, really obtain the SID of the user/group. if (LookupAccountName(NULL, account, pSid, &cbSid, pDomain, &cchDomain, &peUse) == 0) { DWORD err = GetLastError(); LsaClose(PolicyHandle); LocalFree(pSid); LocalFree(pDomain); return (*err_handler)(err, "LookupAccountName", NULL); } PLSA_UNICODE_STRING UserRights; ULONG CountOfRights = 0; NTSTATUS ntStatus = LsaEnumerateAccountRights(PolicyHandle, pSid, &UserRights, &CountOfRights); if (ntStatus == (NTSTATUS) 0xC0000034L) //STATUS_OBJECT_NAME_NOT_FOUND CountOfRights = 0; // Check if the seServiceLogonRight is already granted ULONG i; for (i = 0; i < CountOfRights; i++) { if (wcscmp(UserRights[i].Buffer, privilege) == 0) break; } LsaFreeMemory(UserRights); // Don't leak LSA_UNICODE_STRING PrivilegeString; if (CountOfRights == 0 || i == CountOfRights) { // Grant the SeServiceLogonRight to users represented by pSid. const int string_buff_size = 100; WCHAR tempStr[string_buff_size]; wcsncpy(tempStr, privilege, string_buff_size - 1); tempStr[string_buff_size - 1] = 0; PrivilegeString.Buffer = tempStr; PrivilegeString.Length = wcslen(tempStr) * sizeof(WCHAR); PrivilegeString.MaximumLength = sizeof(tempStr); if ((lsaErr = LsaAddAccountRights(PolicyHandle, pSid, &PrivilegeString, 1)) != (NTSTATUS) 0) { LsaClose(PolicyHandle); LocalFree(pSid); LocalFree(pDomain); return (*err_handler)(LsaNtStatusToWinError(lsaErr), "LsaAddAccountRights", NULL); } } else { LsaClose(PolicyHandle); LocalFree(pSid); LocalFree(pDomain); return FB_PRIVILEGE_ALREADY_GRANTED; } LsaClose(PolicyHandle); LocalFree(pSid); LocalFree(pDomain); return FB_SUCCESS; }
static DWORD ProcessAddRemoveAccountRights( IN PRPC_PARAMETERS pRpcParams, IN BOOLEAN Add, IN PSTR AccountRights, IN BOOLEAN RemoveAll, IN PSTR AccountName ) { DWORD err = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; LSA_BINDING hLsa = NULL; LW_PIO_CREDS pCreds = NULL; WCHAR wszSysName[] = {'\\', '\\', '\0'}; DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS | LSA_ACCESS_CREATE_SPECIAL_ACCOUNTS; POLICY_HANDLE hPolicy = NULL; PSID pAccountSid = NULL; PSTR *ppszAccountRightNames = NULL; DWORD numAccountRightNames = 0; PWSTR *ppwszAccountRightNames = NULL; DWORD i = 0; err = CreateRpcCredentials(pRpcParams, &pCreds); BAIL_ON_LSA_ERROR(err); err = CreateLsaRpcBinding(pRpcParams, pCreds, &hLsa); BAIL_ON_LSA_ERROR(err); ntStatus = LsaOpenPolicy2(hLsa, wszSysName, NULL, policyAccessMask, &hPolicy); BAIL_ON_NT_STATUS(ntStatus); err = ResolveAccountNameToSid( hLsa, AccountName, &pAccountSid); BAIL_ON_LSA_ERROR(err); if (AccountRights) { err = GetStringListFromString( AccountRights, SEPARATOR_CHAR, &ppszAccountRightNames, &numAccountRightNames); BAIL_ON_LSA_ERROR(err); err = LwAllocateMemory( sizeof(ppwszAccountRightNames[0]) * numAccountRightNames, OUT_PPVOID(&ppwszAccountRightNames)); BAIL_ON_LSA_ERROR(err); for (i = 0; i < numAccountRightNames; i++) { err = LwMbsToWc16s(ppszAccountRightNames[i], &ppwszAccountRightNames[i]); BAIL_ON_LSA_ERROR(err); } } if (Add) { ntStatus = LsaAddAccountRights( hLsa, hPolicy, pAccountSid, ppwszAccountRightNames, numAccountRightNames); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "Successfully added account rights to %s\n", AccountName); } else { ntStatus = LsaRemoveAccountRights( hLsa, hPolicy, pAccountSid, RemoveAll, ppwszAccountRightNames, numAccountRightNames); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "Successfully removed account rights from %s\n", AccountName); } error: if (ntStatus || err) { PCSTR errName = LwNtStatusToName(ntStatus); PCSTR errDescription = LwNtStatusToDescription(ntStatus); if (ntStatus) { errName = LwNtStatusToName(ntStatus); errDescription = LwNtStatusToDescription(ntStatus); } else { errName = LwWin32ErrorToName(err); errDescription = LwWin32ErrorToDescription(err); } fprintf(stderr, "Error: %s (%s)\n", LSA_SAFE_LOG_STRING(errName), LSA_SAFE_LOG_STRING(errDescription)); } if (hPolicy) { LsaClose(hLsa, hPolicy); } if (hLsa) { LsaFreeBinding(&hLsa); } if (pCreds) { LwIoDeleteCreds(pCreds); } for (i = 0; i < numAccountRightNames; i++) { LW_SAFE_FREE_MEMORY(ppwszAccountRightNames[i]); LW_SAFE_FREE_MEMORY(ppszAccountRightNames[i]); } LW_SAFE_FREE_MEMORY(ppwszAccountRightNames); LW_SAFE_FREE_MEMORY(ppszAccountRightNames); if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }