1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: Local Security Authority (LSA) Server 4 * FILE: reactos/dll/win32/lsasrv/privileges.c 5 * PURPOSE: Privilege lookup functions 6 * 7 * PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org> 8 */ 9 10 #include "lsasrv.h" 11 #include "resources.h" 12 13 typedef struct 14 { 15 LUID Luid; 16 LPCWSTR Name; 17 INT DisplayNameId; 18 } PRIVILEGE_DATA; 19 20 typedef struct 21 { 22 ULONG Flag; 23 LPCWSTR Name; 24 } RIGHT_DATA; 25 26 27 /* GLOBALS *****************************************************************/ 28 29 static const PRIVILEGE_DATA WellKnownPrivileges[] = 30 { 31 {{SE_CREATE_TOKEN_PRIVILEGE, 0}, SE_CREATE_TOKEN_NAME, IDS_CREATE_TOKEN_PRIVILEGE}, 32 {{SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0}, SE_ASSIGNPRIMARYTOKEN_NAME, IDS_ASSIGNPRIMARYTOKEN_PRIVILEGE}, 33 {{SE_LOCK_MEMORY_PRIVILEGE, 0}, SE_LOCK_MEMORY_NAME, IDS_LOCK_MEMORY_PRIVILEGE}, 34 {{SE_INCREASE_QUOTA_PRIVILEGE, 0}, SE_INCREASE_QUOTA_NAME, IDS_INCREASE_QUOTA_PRIVILEGE}, 35 {{SE_MACHINE_ACCOUNT_PRIVILEGE, 0}, SE_MACHINE_ACCOUNT_NAME, IDS_MACHINE_ACCOUNT_PRIVILEGE}, 36 {{SE_TCB_PRIVILEGE, 0}, SE_TCB_NAME, IDS_TCB_PRIVILEGE}, 37 {{SE_SECURITY_PRIVILEGE, 0}, SE_SECURITY_NAME, IDS_SECURITY_PRIVILEGE}, 38 {{SE_TAKE_OWNERSHIP_PRIVILEGE, 0}, SE_TAKE_OWNERSHIP_NAME, IDS_TAKE_OWNERSHIP_PRIVILEGE}, 39 {{SE_LOAD_DRIVER_PRIVILEGE, 0}, SE_LOAD_DRIVER_NAME, IDS_LOAD_DRIVER_PRIVILEGE}, 40 {{SE_SYSTEM_PROFILE_PRIVILEGE, 0}, SE_SYSTEM_PROFILE_NAME, IDS_SYSTEM_PROFILE_PRIVILEGE}, 41 {{SE_SYSTEMTIME_PRIVILEGE, 0}, SE_SYSTEMTIME_NAME, IDS_SYSTEMTIME_PRIVILEGE}, 42 {{SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0}, SE_PROF_SINGLE_PROCESS_NAME, IDS_PROF_SINGLE_PROCESS_PRIVILEGE}, 43 {{SE_INC_BASE_PRIORITY_PRIVILEGE, 0}, SE_INC_BASE_PRIORITY_NAME, IDS_INC_BASE_PRIORITY_PRIVILEGE}, 44 {{SE_CREATE_PAGEFILE_PRIVILEGE, 0}, SE_CREATE_PAGEFILE_NAME, IDS_CREATE_PAGEFILE_PRIVILEGE}, 45 {{SE_CREATE_PERMANENT_PRIVILEGE, 0}, SE_CREATE_PERMANENT_NAME, IDS_CREATE_PERMANENT_PRIVILEGE}, 46 {{SE_BACKUP_PRIVILEGE, 0}, SE_BACKUP_NAME, IDS_BACKUP_PRIVILEGE}, 47 {{SE_RESTORE_PRIVILEGE, 0}, SE_RESTORE_NAME, IDS_RESTORE_PRIVILEGE}, 48 {{SE_SHUTDOWN_PRIVILEGE, 0}, SE_SHUTDOWN_NAME, IDS_SHUTDOWN_PRIVILEGE}, 49 {{SE_DEBUG_PRIVILEGE, 0}, SE_DEBUG_NAME, IDS_DEBUG_PRIVILEGE}, 50 {{SE_AUDIT_PRIVILEGE, 0}, SE_AUDIT_NAME, IDS_AUDIT_PRIVILEGE}, 51 {{SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0}, SE_SYSTEM_ENVIRONMENT_NAME, IDS_SYSTEM_ENVIRONMENT_PRIVILEGE}, 52 {{SE_CHANGE_NOTIFY_PRIVILEGE, 0}, SE_CHANGE_NOTIFY_NAME, IDS_CHANGE_NOTIFY_PRIVILEGE}, 53 {{SE_REMOTE_SHUTDOWN_PRIVILEGE, 0}, SE_REMOTE_SHUTDOWN_NAME, IDS_REMOTE_SHUTDOWN_PRIVILEGE}, 54 {{SE_UNDOCK_PRIVILEGE, 0}, SE_UNDOCK_NAME, IDS_UNDOCK_PRIVILEGE}, 55 {{SE_SYNC_AGENT_PRIVILEGE, 0}, SE_SYNC_AGENT_NAME, IDS_SYNC_AGENT_PRIVILEGE}, 56 {{SE_ENABLE_DELEGATION_PRIVILEGE, 0}, SE_ENABLE_DELEGATION_NAME, IDS_ENABLE_DELEGATION_PRIVILEGE}, 57 {{SE_MANAGE_VOLUME_PRIVILEGE, 0}, SE_MANAGE_VOLUME_NAME, IDS_MANAGE_VOLUME_PRIVILEGE}, 58 {{SE_IMPERSONATE_PRIVILEGE, 0}, SE_IMPERSONATE_NAME, IDS_IMPERSONATE_PRIVILEGE}, 59 {{SE_CREATE_GLOBAL_PRIVILEGE, 0}, SE_CREATE_GLOBAL_NAME, IDS_CREATE_GLOBAL_PRIVILEGE} 60 }; 61 62 static const RIGHT_DATA WellKnownRights[] = 63 { 64 {SECURITY_ACCESS_INTERACTIVE_LOGON, SE_INTERACTIVE_LOGON_NAME}, 65 {SECURITY_ACCESS_NETWORK_LOGON, SE_NETWORK_LOGON_NAME}, 66 {SECURITY_ACCESS_BATCH_LOGON, SE_BATCH_LOGON_NAME}, 67 {SECURITY_ACCESS_SERVICE_LOGON, SE_SERVICE_LOGON_NAME}, 68 {SECURITY_ACCESS_DENY_INTERACTIVE_LOGON, SE_DENY_INTERACTIVE_LOGON_NAME}, 69 {SECURITY_ACCESS_DENY_NETWORK_LOGON, SE_DENY_NETWORK_LOGON_NAME}, 70 {SECURITY_ACCESS_DENY_BATCH_LOGON, SE_DENY_BATCH_LOGON_NAME}, 71 {SECURITY_ACCESS_DENY_SERVICE_LOGON, SE_DENY_SERVICE_LOGON_NAME}, 72 {SECURITY_ACCESS_REMOTE_INTERACTIVE_LOGON, SE_REMOTE_INTERACTIVE_LOGON_NAME}, 73 {SECURITY_ACCESS_DENY_REMOTE_INTERACTIVE_LOGON, SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME} 74 }; 75 76 77 /* FUNCTIONS ***************************************************************/ 78 79 NTSTATUS 80 LsarpLookupPrivilegeName(PLUID Value, 81 PRPC_UNICODE_STRING *Name) 82 { 83 PRPC_UNICODE_STRING NameBuffer; 84 ULONG Priv; 85 86 if (Value->HighPart != 0 || 87 (Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE || 88 Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE)) 89 { 90 return STATUS_NO_SUCH_PRIVILEGE; 91 } 92 93 for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++) 94 { 95 if (Value->LowPart == WellKnownPrivileges[Priv].Luid.LowPart && 96 Value->HighPart == WellKnownPrivileges[Priv].Luid.HighPart) 97 { 98 NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING)); 99 if (NameBuffer == NULL) 100 return STATUS_NO_MEMORY; 101 102 NameBuffer->Length = (USHORT)wcslen(WellKnownPrivileges[Priv].Name) * sizeof(WCHAR); 103 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR); 104 105 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength); 106 if (NameBuffer->Buffer == NULL) 107 { 108 MIDL_user_free(NameBuffer); 109 return STATUS_NO_MEMORY; 110 } 111 112 wcscpy(NameBuffer->Buffer, WellKnownPrivileges[Priv].Name); 113 114 *Name = NameBuffer; 115 116 return STATUS_SUCCESS; 117 } 118 } 119 120 return STATUS_NO_SUCH_PRIVILEGE; 121 } 122 123 124 NTSTATUS 125 LsarpLookupPrivilegeDisplayName(PRPC_UNICODE_STRING Name, 126 USHORT ClientLanguage, 127 USHORT ClientSystemDefaultLanguage, 128 PRPC_UNICODE_STRING *DisplayName, 129 USHORT *LanguageReturned) 130 { 131 PRPC_UNICODE_STRING DisplayNameBuffer; 132 HINSTANCE hInstance; 133 ULONG Index; 134 UINT nLength; 135 136 TRACE("LsarpLookupPrivilegeDisplayName(%p 0x%04hu 0x%04hu %p %p)\n", 137 Name, ClientLanguage, ClientSystemDefaultLanguage, DisplayName, LanguageReturned); 138 139 if (Name->Length == 0 || Name->Buffer == NULL) 140 return STATUS_INVALID_PARAMETER; 141 142 hInstance = GetModuleHandleW(L"lsasrv.dll"); 143 144 for (Index = 0; Index < ARRAYSIZE(WellKnownPrivileges); Index++) 145 { 146 if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Index].Name) == 0) 147 { 148 TRACE("Index: %u\n", Index); 149 nLength = LsapGetResourceStringLengthEx(hInstance, 150 IDS_CREATE_TOKEN_PRIVILEGE + Index, 151 ClientLanguage); 152 if (nLength != 0) 153 { 154 DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING)); 155 if (DisplayNameBuffer == NULL) 156 return STATUS_NO_MEMORY; 157 158 DisplayNameBuffer->Length = nLength * sizeof(WCHAR); 159 DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR); 160 161 DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength); 162 if (DisplayNameBuffer->Buffer == NULL) 163 { 164 MIDL_user_free(DisplayNameBuffer); 165 return STATUS_NO_MEMORY; 166 } 167 168 LsapLoadStringEx(hInstance, 169 IDS_CREATE_TOKEN_PRIVILEGE + Index, 170 ClientLanguage, 171 DisplayNameBuffer->Buffer, 172 nLength); 173 174 *DisplayName = DisplayNameBuffer; 175 *LanguageReturned = ClientLanguage; 176 } 177 else 178 { 179 nLength = LsapGetResourceStringLengthEx(hInstance, 180 IDS_CREATE_TOKEN_PRIVILEGE + Index, 181 ClientSystemDefaultLanguage); 182 if (nLength != 0) 183 { 184 DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING)); 185 if (DisplayNameBuffer == NULL) 186 return STATUS_NO_MEMORY; 187 188 DisplayNameBuffer->Length = nLength * sizeof(WCHAR); 189 DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR); 190 191 DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength); 192 if (DisplayNameBuffer->Buffer == NULL) 193 { 194 MIDL_user_free(DisplayNameBuffer); 195 return STATUS_NO_MEMORY; 196 } 197 198 LsapLoadStringEx(hInstance, 199 IDS_CREATE_TOKEN_PRIVILEGE + Index, 200 ClientSystemDefaultLanguage, 201 DisplayNameBuffer->Buffer, 202 nLength); 203 204 *DisplayName = DisplayNameBuffer; 205 *LanguageReturned = ClientSystemDefaultLanguage; 206 } 207 else 208 { 209 return STATUS_INVALID_PARAMETER; 210 #if 0 211 nLength = LsapGetResourceStringLengthEx(hInstance, 212 IDS_CREATE_TOKEN_PRIVILEGE + Index, 213 0x409); 214 #endif 215 } 216 } 217 218 return STATUS_SUCCESS; 219 } 220 } 221 222 return STATUS_NO_SUCH_PRIVILEGE; 223 } 224 225 226 PLUID 227 LsarpLookupPrivilegeValue( 228 IN PRPC_UNICODE_STRING Name) 229 { 230 ULONG Priv; 231 232 if (Name->Length == 0 || Name->Buffer == NULL) 233 return NULL; 234 235 for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++) 236 { 237 if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0) 238 return (PLUID)&(WellKnownPrivileges[Priv].Luid); 239 } 240 241 return NULL; 242 } 243 244 245 NTSTATUS 246 LsarpEnumeratePrivileges(DWORD *EnumerationContext, 247 PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer, 248 DWORD PreferedMaximumLength) 249 { 250 PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL; 251 ULONG EnumIndex; 252 ULONG EnumCount = 0; 253 ULONG RequiredLength = 0; 254 ULONG i; 255 BOOLEAN MoreEntries = FALSE; 256 NTSTATUS Status = STATUS_SUCCESS; 257 258 EnumIndex = *EnumerationContext; 259 260 for (; EnumIndex < ARRAYSIZE(WellKnownPrivileges); EnumIndex++) 261 { 262 TRACE("EnumIndex: %lu\n", EnumIndex); 263 TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name); 264 TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name)); 265 266 if ((RequiredLength + 267 wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) + 268 sizeof(UNICODE_NULL) + 269 sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength) 270 { 271 MoreEntries = TRUE; 272 break; 273 } 274 275 RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) + 276 sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF)); 277 EnumCount++; 278 } 279 280 TRACE("EnumCount: %lu\n", EnumCount); 281 TRACE("RequiredLength: %lu\n", RequiredLength); 282 283 if (EnumCount == 0) 284 goto done; 285 286 Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF)); 287 if (Privileges == NULL) 288 { 289 Status = STATUS_INSUFFICIENT_RESOURCES; 290 goto done; 291 } 292 293 EnumIndex = *EnumerationContext; 294 295 for (i = 0; i < EnumCount; i++, EnumIndex++) 296 { 297 Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid; 298 299 Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR); 300 Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL); 301 302 Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength); 303 if (Privileges[i].Name.Buffer == NULL) 304 { 305 Status = STATUS_INSUFFICIENT_RESOURCES; 306 goto done; 307 } 308 309 memcpy(Privileges[i].Name.Buffer, 310 WellKnownPrivileges[EnumIndex].Name, 311 Privileges[i].Name.Length); 312 } 313 314 done: 315 if (NT_SUCCESS(Status)) 316 { 317 EnumerationBuffer->Entries = EnumCount; 318 EnumerationBuffer->Privileges = Privileges; 319 *EnumerationContext += EnumCount; 320 } 321 else 322 { 323 if (Privileges != NULL) 324 { 325 for (i = 0; i < EnumCount; i++) 326 { 327 if (Privileges[i].Name.Buffer != NULL) 328 MIDL_user_free(Privileges[i].Name.Buffer); 329 } 330 331 MIDL_user_free(Privileges); 332 } 333 } 334 335 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 336 Status = STATUS_MORE_ENTRIES; 337 338 return Status; 339 } 340 341 342 NTSTATUS 343 LsapLookupAccountRightName(ULONG RightValue, 344 PRPC_UNICODE_STRING *Name) 345 { 346 PRPC_UNICODE_STRING NameBuffer; 347 ULONG i; 348 349 for (i = 0; i < ARRAYSIZE(WellKnownRights); i++) 350 { 351 if (WellKnownRights[i].Flag == RightValue) 352 { 353 NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING)); 354 if (NameBuffer == NULL) 355 return STATUS_NO_MEMORY; 356 357 NameBuffer->Length = (USHORT)wcslen(WellKnownRights[i].Name) * sizeof(WCHAR); 358 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR); 359 360 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength); 361 if (NameBuffer->Buffer == NULL) 362 { 363 MIDL_user_free(NameBuffer); 364 return STATUS_INSUFFICIENT_RESOURCES; 365 } 366 367 wcscpy(NameBuffer->Buffer, WellKnownRights[i].Name); 368 369 *Name = NameBuffer; 370 371 return STATUS_SUCCESS; 372 } 373 } 374 375 return STATUS_NO_SUCH_PRIVILEGE; 376 } 377 378 379 ACCESS_MASK 380 LsapLookupAccountRightValue( 381 IN PRPC_UNICODE_STRING Name) 382 { 383 ULONG i; 384 385 if (Name->Length == 0 || Name->Buffer == NULL) 386 return 0; 387 388 for (i = 0; i < ARRAYSIZE(WellKnownRights); i++) 389 { 390 if (_wcsicmp(Name->Buffer, WellKnownRights[i].Name) == 0) 391 return WellKnownRights[i].Flag; 392 } 393 394 return 0; 395 } 396 397 /* EOF */ 398