1 /* 2 * PROJECT: Local Security Authority Server DLL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/samsrv/alias.c 5 * PURPOSE: Alias specific helper functions 6 * COPYRIGHT: Copyright 2013 Eric Kohl 7 */ 8 9 #include "samsrv.h" 10 11 /* FUNCTIONS ***************************************************************/ 12 13 NTSTATUS 14 SampOpenAliasObject(IN PSAM_DB_OBJECT DomainObject, 15 IN ULONG AliasId, 16 IN ACCESS_MASK DesiredAccess, 17 OUT PSAM_DB_OBJECT *AliasObject) 18 { 19 WCHAR szRid[9]; 20 21 TRACE("(%p %lu %lx %p)\n", 22 DomainObject, AliasId, DesiredAccess, AliasObject); 23 24 /* Convert the RID into a string (hex) */ 25 swprintf(szRid, L"%08lX", AliasId); 26 27 /* Create the user object */ 28 return SampOpenDbObject(DomainObject, 29 L"Aliases", 30 szRid, 31 AliasId, 32 SamDbAliasObject, 33 DesiredAccess, 34 AliasObject); 35 } 36 37 38 NTSTATUS 39 SampAddMemberToAlias(IN PSAM_DB_OBJECT AliasObject, 40 IN PRPC_SID MemberId) 41 { 42 LPWSTR MemberIdString = NULL; 43 HANDLE MembersKeyHandle = NULL; 44 HANDLE MemberKeyHandle = NULL; 45 ULONG MemberIdLength; 46 NTSTATUS Status; 47 48 TRACE("(%p %p)\n", 49 AliasObject, MemberId); 50 51 ConvertSidToStringSidW(MemberId, &MemberIdString); 52 TRACE("Member SID: %S\n", MemberIdString); 53 54 MemberIdLength = RtlLengthSid(MemberId); 55 56 Status = SampRegCreateKey(AliasObject->KeyHandle, 57 L"Members", 58 KEY_WRITE, 59 &MembersKeyHandle); 60 if (!NT_SUCCESS(Status)) 61 { 62 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status); 63 goto done; 64 } 65 66 Status = SampRegSetValue(MembersKeyHandle, 67 MemberIdString, 68 REG_BINARY, 69 MemberId, 70 MemberIdLength); 71 if (!NT_SUCCESS(Status)) 72 { 73 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status); 74 goto done; 75 } 76 77 Status = SampRegCreateKey(AliasObject->MembersKeyHandle, 78 MemberIdString, 79 KEY_WRITE, 80 &MemberKeyHandle); 81 if (!NT_SUCCESS(Status)) 82 { 83 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status); 84 goto done; 85 } 86 87 Status = SampRegSetValue(MemberKeyHandle, 88 AliasObject->Name, 89 REG_BINARY, 90 MemberId, 91 MemberIdLength); 92 if (!NT_SUCCESS(Status)) 93 { 94 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status); 95 goto done; 96 } 97 98 done: 99 SampRegCloseKey(&MemberKeyHandle); 100 SampRegCloseKey(&MembersKeyHandle); 101 102 if (MemberIdString != NULL) 103 LocalFree(MemberIdString); 104 105 return Status; 106 } 107 108 109 NTSTATUS 110 NTAPI 111 SampRemoveMemberFromAlias(IN PSAM_DB_OBJECT AliasObject, 112 IN PRPC_SID MemberId) 113 { 114 LPWSTR MemberIdString = NULL; 115 HANDLE MembersKeyHandle = NULL; 116 HANDLE MemberKeyHandle = NULL; 117 ULONG ulValueCount; 118 NTSTATUS Status; 119 120 TRACE("(%p %p)\n", 121 AliasObject, MemberId); 122 123 ConvertSidToStringSidW(MemberId, &MemberIdString); 124 TRACE("Member SID: %S\n", MemberIdString); 125 126 Status = SampRegOpenKey(AliasObject->MembersKeyHandle, 127 MemberIdString, 128 KEY_WRITE | KEY_QUERY_VALUE, 129 &MemberKeyHandle); 130 if (!NT_SUCCESS(Status)) 131 { 132 TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status); 133 goto done; 134 } 135 136 Status = SampRegDeleteValue(MemberKeyHandle, 137 AliasObject->Name); 138 if (!NT_SUCCESS(Status)) 139 { 140 TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status); 141 goto done; 142 } 143 144 Status = SampRegQueryKeyInfo(MemberKeyHandle, 145 NULL, 146 &ulValueCount); 147 if (!NT_SUCCESS(Status)) 148 { 149 TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status); 150 goto done; 151 } 152 153 if (ulValueCount == 0) 154 { 155 SampRegCloseKey(&MemberKeyHandle); 156 157 Status = SampRegDeleteKey(AliasObject->MembersKeyHandle, 158 MemberIdString); 159 if (!NT_SUCCESS(Status)) 160 { 161 TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status); 162 goto done; 163 } 164 } 165 166 Status = SampRegOpenKey(AliasObject->KeyHandle, 167 L"Members", 168 KEY_WRITE | KEY_QUERY_VALUE, 169 &MembersKeyHandle); 170 if (!NT_SUCCESS(Status)) 171 { 172 TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status); 173 goto done; 174 } 175 176 Status = SampRegDeleteValue(MembersKeyHandle, 177 MemberIdString); 178 if (!NT_SUCCESS(Status)) 179 { 180 TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status); 181 goto done; 182 } 183 184 Status = SampRegQueryKeyInfo(MembersKeyHandle, 185 NULL, 186 &ulValueCount); 187 if (!NT_SUCCESS(Status)) 188 { 189 TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status); 190 goto done; 191 } 192 193 if (ulValueCount == 0) 194 { 195 SampRegCloseKey(&MembersKeyHandle); 196 197 Status = SampRegDeleteKey(AliasObject->KeyHandle, 198 L"Members"); 199 if (!NT_SUCCESS(Status)) 200 { 201 TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status); 202 goto done; 203 } 204 } 205 206 done: 207 SampRegCloseKey(&MemberKeyHandle); 208 SampRegCloseKey(&MembersKeyHandle); 209 210 if (MemberIdString != NULL) 211 LocalFree(MemberIdString); 212 213 return Status; 214 } 215 216 217 NTSTATUS 218 SampGetMembersInAlias(IN PSAM_DB_OBJECT AliasObject, 219 OUT PULONG MemberCount, 220 OUT PSAMPR_SID_INFORMATION *MemberArray) 221 { 222 HANDLE MembersKeyHandle = NULL; 223 PSAMPR_SID_INFORMATION Members = NULL; 224 ULONG Count = 0; 225 ULONG DataLength; 226 ULONG Index; 227 NTSTATUS Status; 228 229 /* Open the members key of the alias object */ 230 Status = SampRegOpenKey(AliasObject->KeyHandle, 231 L"Members", 232 KEY_READ, 233 &MembersKeyHandle); 234 if (!NT_SUCCESS(Status)) 235 { 236 ERR("SampRegOpenKey failed with status 0x%08lx\n", Status); 237 goto done; 238 } 239 240 /* Get the number of members */ 241 Status = SampRegQueryKeyInfo(MembersKeyHandle, 242 NULL, 243 &Count); 244 if (!NT_SUCCESS(Status)) 245 { 246 ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status); 247 goto done; 248 } 249 250 /* Allocate the member array */ 251 Members = midl_user_allocate(Count * sizeof(SAMPR_SID_INFORMATION)); 252 if (Members == NULL) 253 { 254 Status = STATUS_INSUFFICIENT_RESOURCES; 255 goto done; 256 } 257 258 /* Enumerate the members */ 259 Index = 0; 260 while (TRUE) 261 { 262 /* Get the size of the next SID */ 263 DataLength = 0; 264 Status = SampRegEnumerateValue(MembersKeyHandle, 265 Index, 266 NULL, 267 NULL, 268 NULL, 269 NULL, 270 &DataLength); 271 if (!NT_SUCCESS(Status)) 272 { 273 if (Status == STATUS_NO_MORE_ENTRIES) 274 Status = STATUS_SUCCESS; 275 break; 276 } 277 278 /* Allocate a buffer for the SID */ 279 Members[Index].SidPointer = midl_user_allocate(DataLength); 280 if (Members[Index].SidPointer == NULL) 281 { 282 Status = STATUS_INSUFFICIENT_RESOURCES; 283 goto done; 284 } 285 286 /* Read the SID into the buffer */ 287 Status = SampRegEnumerateValue(MembersKeyHandle, 288 Index, 289 NULL, 290 NULL, 291 NULL, 292 (PVOID)Members[Index].SidPointer, 293 &DataLength); 294 if (!NT_SUCCESS(Status)) 295 { 296 goto done; 297 } 298 299 Index++; 300 } 301 302 if (NT_SUCCESS(Status)) 303 { 304 *MemberCount = Count; 305 *MemberArray = Members; 306 } 307 308 done: 309 return Status; 310 } 311 312 313 NTSTATUS 314 SampRemoveAllMembersFromAlias(IN PSAM_DB_OBJECT AliasObject) 315 { 316 HANDLE MembersKeyHandle = NULL; 317 PSAMPR_SID_INFORMATION MemberArray = NULL; 318 ULONG MemberCount = 0; 319 ULONG Index; 320 NTSTATUS Status; 321 322 TRACE("(%p)\n", AliasObject); 323 324 /* Open the members key of the alias object */ 325 Status = SampRegOpenKey(AliasObject->KeyHandle, 326 L"Members", 327 KEY_READ, 328 &MembersKeyHandle); 329 if (!NT_SUCCESS(Status)) 330 { 331 ERR("SampRegOpenKey failed (Status 0x%08lx)\n", Status); 332 goto done; 333 } 334 335 /* Get a list of all members of the alias */ 336 Status = SampGetMembersInAlias(AliasObject, 337 &MemberCount, 338 &MemberArray); 339 if (!NT_SUCCESS(Status)) 340 { 341 ERR("SampGetMembersInAlias failed (Status 0x%08lx)\n", Status); 342 goto done; 343 } 344 345 /* Remove all members from the alias */ 346 for (Index = 0; Index < MemberCount; Index++) 347 { 348 Status = SampRemoveMemberFromAlias(AliasObject, 349 MemberArray[Index].SidPointer); 350 if (!NT_SUCCESS(Status)) 351 goto done; 352 } 353 354 done: 355 if (MemberArray != NULL) 356 { 357 for (Index = 0; Index < MemberCount; Index++) 358 { 359 if (MemberArray[Index].SidPointer != NULL) 360 midl_user_free(MemberArray[Index].SidPointer); 361 } 362 363 midl_user_free(MemberArray); 364 } 365 366 SampRegCloseKey(&MembersKeyHandle); 367 368 return Status; 369 } 370 371 /* EOF */ 372