2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/samsrv/user.c
5 * PURPOSE: User specific helper functions
6 * COPYRIGHT: Copyright 2013 Eric Kohl
9 /* INCLUDES ****************************************************************/
13 WINE_DEFAULT_DEBUG_CHANNEL(samsrv
);
16 /* FUNCTIONS ***************************************************************/
19 SampOpenUserObject(IN PSAM_DB_OBJECT DomainObject
,
21 IN ACCESS_MASK DesiredAccess
,
22 OUT PSAM_DB_OBJECT
*UserObject
)
26 TRACE("(%p %lu %lx %p)\n",
27 DomainObject
, UserId
, DesiredAccess
, UserObject
);
29 /* Convert the RID into a string (hex) */
30 swprintf(szRid
, L
"%08lX", UserId
);
32 /* Create the user object */
33 return SampOpenDbObject(DomainObject
,
44 SampAddGroupMembershipToUser(IN PSAM_DB_OBJECT UserObject
,
48 PGROUP_MEMBERSHIP GroupsBuffer
= NULL
;
49 ULONG GroupsCount
= 0;
54 TRACE("(%p %lu %lx)\n",
55 UserObject
, GroupId
, Attributes
);
57 Status
= SampGetObjectAttribute(UserObject
,
62 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
65 GroupsBuffer
= midl_user_allocate(Length
+ sizeof(GROUP_MEMBERSHIP
));
66 if (GroupsBuffer
== NULL
)
68 Status
= STATUS_INSUFFICIENT_RESOURCES
;
72 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
74 Status
= SampGetObjectAttribute(UserObject
,
79 if (!NT_SUCCESS(Status
))
82 GroupsCount
= Length
/ sizeof(GROUP_MEMBERSHIP
);
85 for (i
= 0; i
< GroupsCount
; i
++)
87 if (GroupsBuffer
[i
].RelativeId
== GroupId
)
89 Status
= STATUS_MEMBER_IN_GROUP
;
94 GroupsBuffer
[GroupsCount
].RelativeId
= GroupId
;
95 GroupsBuffer
[GroupsCount
].Attributes
= Attributes
;
96 Length
+= sizeof(GROUP_MEMBERSHIP
);
98 Status
= SampSetObjectAttribute(UserObject
,
105 if (GroupsBuffer
!= NULL
)
106 midl_user_free(GroupsBuffer
);
113 SampRemoveGroupMembershipFromUser(IN PSAM_DB_OBJECT UserObject
,
116 PGROUP_MEMBERSHIP GroupsBuffer
= NULL
;
117 ULONG GroupsCount
= 0;
120 NTSTATUS Status
= STATUS_SUCCESS
;
123 UserObject
, GroupId
);
125 SampGetObjectAttribute(UserObject
,
132 return STATUS_MEMBER_NOT_IN_GROUP
;
134 GroupsBuffer
= midl_user_allocate(Length
);
135 if (GroupsBuffer
== NULL
)
137 Status
= STATUS_INSUFFICIENT_RESOURCES
;
141 Status
= SampGetObjectAttribute(UserObject
,
146 if (!NT_SUCCESS(Status
))
149 Status
= STATUS_MEMBER_NOT_IN_GROUP
;
151 GroupsCount
= Length
/ sizeof(GROUP_MEMBERSHIP
);
152 for (i
= 0; i
< GroupsCount
; i
++)
154 if (GroupsBuffer
[i
].RelativeId
== GroupId
)
156 Length
-= sizeof(GROUP_MEMBERSHIP
);
157 Status
= STATUS_SUCCESS
;
159 if (GroupsCount
- i
- 1 > 0)
161 CopyMemory(&GroupsBuffer
[i
],
162 &GroupsBuffer
[i
+ 1],
163 (GroupsCount
- i
- 1) * sizeof(GROUP_MEMBERSHIP
));
170 if (!NT_SUCCESS(Status
))
173 Status
= SampSetObjectAttribute(UserObject
,
180 if (GroupsBuffer
!= NULL
)
181 midl_user_free(GroupsBuffer
);
188 SampGetUserGroupAttributes(IN PSAM_DB_OBJECT DomainObject
,
191 OUT PULONG GroupAttributes
)
193 PSAM_DB_OBJECT UserObject
= NULL
;
194 PGROUP_MEMBERSHIP GroupsBuffer
= NULL
;
199 Status
= SampOpenUserObject(DomainObject
,
203 if (!NT_SUCCESS(Status
))
208 SampGetObjectAttribute(UserObject
,
215 return STATUS_UNSUCCESSFUL
; /* FIXME */
217 GroupsBuffer
= midl_user_allocate(Length
);
218 if (GroupsBuffer
== NULL
)
220 Status
= STATUS_INSUFFICIENT_RESOURCES
;
224 Status
= SampGetObjectAttribute(UserObject
,
229 if (!NT_SUCCESS(Status
))
232 for (i
= 0; i
< (Length
/ sizeof(GROUP_MEMBERSHIP
)); i
++)
234 if (GroupsBuffer
[i
].RelativeId
== GroupId
)
236 *GroupAttributes
= GroupsBuffer
[i
].Attributes
;
242 if (GroupsBuffer
!= NULL
)
243 midl_user_free(GroupsBuffer
);
245 if (UserObject
!= NULL
)
246 SampCloseDbObject(UserObject
);
253 SampSetUserGroupAttributes(IN PSAM_DB_OBJECT DomainObject
,
256 IN ULONG GroupAttributes
)
258 PSAM_DB_OBJECT UserObject
= NULL
;
259 PGROUP_MEMBERSHIP GroupsBuffer
= NULL
;
264 Status
= SampOpenUserObject(DomainObject
,
268 if (!NT_SUCCESS(Status
))
273 SampGetObjectAttribute(UserObject
,
280 return STATUS_UNSUCCESSFUL
; /* FIXME */
282 GroupsBuffer
= midl_user_allocate(Length
);
283 if (GroupsBuffer
== NULL
)
285 Status
= STATUS_INSUFFICIENT_RESOURCES
;
289 Status
= SampGetObjectAttribute(UserObject
,
294 if (!NT_SUCCESS(Status
))
297 for (i
= 0; i
< (Length
/ sizeof(GROUP_MEMBERSHIP
)); i
++)
299 if (GroupsBuffer
[i
].RelativeId
== GroupId
)
301 GroupsBuffer
[i
].Attributes
= GroupAttributes
;
306 Status
= SampSetObjectAttribute(UserObject
,
313 if (GroupsBuffer
!= NULL
)
314 midl_user_free(GroupsBuffer
);
316 if (UserObject
!= NULL
)
317 SampCloseDbObject(UserObject
);
324 SampRemoveUserFromAllGroups(IN PSAM_DB_OBJECT UserObject
)
326 PGROUP_MEMBERSHIP GroupsBuffer
= NULL
;
327 PSAM_DB_OBJECT GroupObject
;
332 SampGetObjectAttribute(UserObject
,
339 return STATUS_SUCCESS
;
341 GroupsBuffer
= midl_user_allocate(Length
);
342 if (GroupsBuffer
== NULL
)
344 Status
= STATUS_INSUFFICIENT_RESOURCES
;
348 Status
= SampGetObjectAttribute(UserObject
,
353 if (!NT_SUCCESS(Status
))
356 for (i
= 0; i
< (Length
/ sizeof(GROUP_MEMBERSHIP
)); i
++)
358 Status
= SampOpenGroupObject(UserObject
->ParentObject
,
359 GroupsBuffer
[i
].RelativeId
,
362 if (!NT_SUCCESS(Status
))
367 Status
= SampRemoveMemberFromGroup(GroupObject
,
368 UserObject
->RelativeId
);
370 SampCloseDbObject(GroupObject
);
372 if (!NT_SUCCESS(Status
))
379 if (GroupsBuffer
!= NULL
)
380 midl_user_free(GroupsBuffer
);
387 SampSetUserPassword(IN PSAM_DB_OBJECT UserObject
,
388 IN PENCRYPTED_NT_OWF_PASSWORD NtPassword
,
389 IN BOOLEAN NtPasswordPresent
,
390 IN PENCRYPTED_LM_OWF_PASSWORD LmPassword
,
391 IN BOOLEAN LmPasswordPresent
)
393 PENCRYPTED_NT_OWF_PASSWORD NtHistory
= NULL
;
394 PENCRYPTED_LM_OWF_PASSWORD LmHistory
= NULL
;
395 ULONG NtHistoryLength
= 0;
396 ULONG LmHistoryLength
= 0;
397 ULONG CurrentHistoryLength
;
398 ULONG MaxHistoryLength
= 3;
402 /* Get the size of the NT history */
403 SampGetObjectAttribute(UserObject
,
409 CurrentHistoryLength
= Length
/ sizeof(ENCRYPTED_NT_OWF_PASSWORD
);
410 if (CurrentHistoryLength
< MaxHistoryLength
)
412 NtHistoryLength
= (CurrentHistoryLength
+ 1) * sizeof(ENCRYPTED_NT_OWF_PASSWORD
);
416 NtHistoryLength
= MaxHistoryLength
* sizeof(ENCRYPTED_NT_OWF_PASSWORD
);
419 /* Allocate the history buffer */
420 NtHistory
= midl_user_allocate(NtHistoryLength
);
421 if (NtHistory
== NULL
)
422 return STATUS_INSUFFICIENT_RESOURCES
;
426 /* Get the history */
427 Status
= SampGetObjectAttribute(UserObject
,
432 if (!NT_SUCCESS(Status
))
436 /* Get the size of the LM history */
438 SampGetObjectAttribute(UserObject
,
444 CurrentHistoryLength
= Length
/ sizeof(ENCRYPTED_LM_OWF_PASSWORD
);
445 if (CurrentHistoryLength
< MaxHistoryLength
)
447 LmHistoryLength
= (CurrentHistoryLength
+ 1) * sizeof(ENCRYPTED_LM_OWF_PASSWORD
);
451 LmHistoryLength
= MaxHistoryLength
* sizeof(ENCRYPTED_LM_OWF_PASSWORD
);
454 /* Allocate the history buffer */
455 LmHistory
= midl_user_allocate(LmHistoryLength
);
456 if (LmHistory
== NULL
)
457 return STATUS_INSUFFICIENT_RESOURCES
;
461 /* Get the history */
462 Status
= SampGetObjectAttribute(UserObject
,
467 if (!NT_SUCCESS(Status
))
471 /* Set the new password */
472 if (NtPasswordPresent
)
474 Status
= SampSetObjectAttribute(UserObject
,
478 sizeof(ENCRYPTED_NT_OWF_PASSWORD
));
479 if (!NT_SUCCESS(Status
))
484 Status
= SampSetObjectAttribute(UserObject
,
489 if (!NT_SUCCESS(Status
))
493 if (LmPasswordPresent
)
495 Status
= SampSetObjectAttribute(UserObject
,
499 sizeof(ENCRYPTED_LM_OWF_PASSWORD
));
500 if (!NT_SUCCESS(Status
))
505 Status
= SampSetObjectAttribute(UserObject
,
510 if (!NT_SUCCESS(Status
))
514 /* Move the old passwords down by one entry */
515 if (NtHistoryLength
> sizeof(ENCRYPTED_NT_OWF_PASSWORD
))
517 MoveMemory(&(NtHistory
[1]),
519 NtHistoryLength
- sizeof(ENCRYPTED_NT_OWF_PASSWORD
));
522 /* Add the new password on top of the history */
523 if (NtPasswordPresent
)
525 CopyMemory(&(NtHistory
[0]),
527 sizeof(ENCRYPTED_NT_OWF_PASSWORD
));
531 ZeroMemory(&(NtHistory
[0]),
532 sizeof(ENCRYPTED_NT_OWF_PASSWORD
));
535 /* Set the history */
536 Status
= SampSetObjectAttribute(UserObject
,
541 if (!NT_SUCCESS(Status
))
544 /* Move the old passwords down by one entry */
545 if (LmHistoryLength
> sizeof(ENCRYPTED_LM_OWF_PASSWORD
))
547 MoveMemory(&(LmHistory
[1]),
549 LmHistoryLength
- sizeof(ENCRYPTED_LM_OWF_PASSWORD
));
552 /* Add the new password on top of the history */
553 if (LmPasswordPresent
)
555 CopyMemory(&(LmHistory
[0]),
557 sizeof(ENCRYPTED_LM_OWF_PASSWORD
));
561 ZeroMemory(&(LmHistory
[0]),
562 sizeof(ENCRYPTED_LM_OWF_PASSWORD
));
565 /* Set the LM password history */
566 Status
= SampSetObjectAttribute(UserObject
,
571 if (!NT_SUCCESS(Status
))
575 if (NtHistory
!= NULL
)
576 midl_user_free(NtHistory
);
578 if (LmHistory
!= NULL
)
579 midl_user_free(LmHistory
);