2 Unix SMB/CIFS implementation.
4 Copyright (C) Guenther Deschner <gd@samba.org> 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/passwd.h"
22 #include "libnet/libnet_dssync.h"
23 #include "../libcli/security/security.h"
24 #include "../libds/common/flags.h"
25 #include "../librpc/gen_ndr/ndr_drsuapi.h"
27 #include "dbwrap/dbwrap.h"
28 #include "../libds/common/flag_mapping.h"
31 /****************************************************************
32 ****************************************************************/
34 struct dssync_passdb
{
35 struct pdb_methods
*methods
;
36 struct db_context
*all
;
37 struct db_context
*aliases
;
38 struct db_context
*groups
;
41 struct dssync_passdb_obj
{
42 struct dssync_passdb_obj
*self
;
44 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
47 struct db_context
*members
;
50 struct dssync_passdb_mem
{
51 struct dssync_passdb_mem
*self
;
53 struct drsuapi_DsReplicaObjectIdentifier3
*cur
;
54 struct dssync_passdb_obj
*obj
;
59 static NTSTATUS
dssync_insert_obj(struct dssync_passdb
*pctx
,
60 struct db_context
*db
,
61 struct dssync_passdb_obj
*obj
)
64 struct db_record
*rec
;
66 rec
= db
->fetch_locked(db
, talloc_tos(), obj
->key
);
68 return NT_STATUS_NO_MEMORY
;
70 if (rec
->value
.dsize
!= 0) {
74 status
= rec
->store(rec
, obj
->data
, TDB_INSERT
);
75 if (!NT_STATUS_IS_OK(status
)) {
83 static struct dssync_passdb_obj
*dssync_parse_obj(const TDB_DATA data
)
85 struct dssync_passdb_obj
*obj
;
87 if (data
.dsize
!= sizeof(obj
)) {
92 * we need to copy the pointer to avoid alignment problems
95 memcpy(&obj
, data
.dptr
, sizeof(obj
));
97 return talloc_get_type_abort(obj
, struct dssync_passdb_obj
);
100 static struct dssync_passdb_obj
*dssync_search_obj_by_guid(struct dssync_passdb
*pctx
,
101 struct db_context
*db
,
102 const struct GUID
*guid
)
104 struct dssync_passdb_obj
*obj
;
109 key
= make_tdb_data((const uint8_t *)(const void *)guid
,
112 ret
= db
->fetch(db
, talloc_tos(), key
, &data
);
117 obj
= dssync_parse_obj(data
);
121 static NTSTATUS
dssync_create_obj(struct dssync_passdb
*pctx
,
122 struct db_context
*db
,
124 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
125 struct dssync_passdb_obj
**_obj
)
128 struct dssync_passdb_obj
*obj
;
130 obj
= talloc_zero(pctx
, struct dssync_passdb_obj
);
132 return NT_STATUS_NO_MEMORY
;
137 obj
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->object
.identifier
->guid
,
138 sizeof(cur
->object
.identifier
->guid
));
139 obj
->data
= make_tdb_data((const uint8_t *)(void *)&obj
->self
,
142 obj
->members
= db_open_rbt(obj
);
143 if (obj
->members
== NULL
) {
144 return NT_STATUS_NO_MEMORY
;
147 status
= dssync_insert_obj(pctx
, db
, obj
);
148 if (!NT_STATUS_IS_OK(status
)) {
156 static NTSTATUS
dssync_insert_mem(struct dssync_passdb
*pctx
,
157 struct dssync_passdb_obj
*obj
,
158 struct dssync_passdb_mem
*mem
)
161 struct db_record
*rec
;
163 rec
= obj
->members
->fetch_locked(obj
->members
, talloc_tos(), mem
->key
);
165 return NT_STATUS_NO_MEMORY
;
167 if (rec
->value
.dsize
!= 0) {
171 status
= rec
->store(rec
, mem
->data
, TDB_INSERT
);
172 if (!NT_STATUS_IS_OK(status
)) {
180 static NTSTATUS
dssync_create_mem(struct dssync_passdb
*pctx
,
181 struct dssync_passdb_obj
*obj
,
183 struct drsuapi_DsReplicaObjectIdentifier3
*cur
,
184 struct dssync_passdb_mem
**_mem
)
187 struct dssync_passdb_mem
*mem
;
189 mem
= talloc_zero(pctx
, struct dssync_passdb_mem
);
191 return NT_STATUS_NO_MEMORY
;
195 mem
->active
= active
;
197 mem
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->guid
,
199 mem
->data
= make_tdb_data((const uint8_t *)(void *)&mem
->self
,
202 status
= dssync_insert_mem(pctx
, obj
, mem
);
203 if (!NT_STATUS_IS_OK(status
)) {
211 static struct dssync_passdb_mem
*dssync_parse_mem(const TDB_DATA data
)
213 struct dssync_passdb_mem
*mem
;
215 if (data
.dsize
!= sizeof(mem
)) {
220 * we need to copy the pointer to avoid alignment problems
223 memcpy(&mem
, data
.dptr
, sizeof(mem
));
225 return talloc_get_type_abort(mem
, struct dssync_passdb_mem
);
228 static NTSTATUS
passdb_startup(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
229 struct replUpToDateVectorBlob
**pold_utdv
)
232 struct dssync_passdb
*pctx
;
234 pctx
= talloc_zero(mem_ctx
, struct dssync_passdb
);
236 return NT_STATUS_NO_MEMORY
;
239 if (ctx
->output_filename
) {
240 status
= make_pdb_method_name(&pctx
->methods
, ctx
->output_filename
);
242 status
= make_pdb_method_name(&pctx
->methods
, lp_passdb_backend());
245 if (!NT_STATUS_IS_OK(status
)) {
249 pctx
->all
= db_open_rbt(pctx
);
250 if (pctx
->all
== NULL
) {
251 return NT_STATUS_NO_MEMORY
;
253 pctx
->aliases
= db_open_rbt(pctx
);
254 if (pctx
->aliases
== NULL
) {
255 return NT_STATUS_NO_MEMORY
;
257 pctx
->groups
= db_open_rbt(pctx
);
258 if (pctx
->groups
== NULL
) {
259 return NT_STATUS_NO_MEMORY
;
262 ctx
->private_data
= pctx
;
267 /****************************************************************
268 ****************************************************************/
270 struct dssync_passdb_traverse_amembers
{
271 struct dssync_context
*ctx
;
272 struct dssync_passdb_obj
*obj
;
277 struct dssync_passdb_traverse_aliases
{
278 struct dssync_context
*ctx
;
283 static int dssync_passdb_traverse_amembers(struct db_record
*rec
,
286 struct dssync_passdb_traverse_amembers
*state
=
287 (struct dssync_passdb_traverse_amembers
*)private_data
;
288 struct dssync_passdb
*pctx
=
289 talloc_get_type_abort(state
->ctx
->private_data
,
290 struct dssync_passdb
);
291 struct dssync_passdb_mem
*mem
;
293 struct dom_sid alias_sid
;
294 struct dom_sid member_sid
;
295 const char *member_dn
;
298 struct dom_sid
*members
;
299 bool is_member
= false;
304 alias_sid
= state
->obj
->cur
->object
.identifier
->sid
;
306 mem
= dssync_parse_mem(rec
->value
);
311 member_sid
= mem
->cur
->sid
;
312 member_dn
= mem
->cur
->dn
;
314 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
315 if (mem
->obj
== NULL
) {
316 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
317 sid_string_dbg(&alias_sid
),
318 is_null_sid(&member_sid
)?
319 sid_string_dbg(&member_sid
):
324 switch (mem
->obj
->type
) {
325 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
326 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
327 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
328 sid_string_dbg(&alias_sid
),
335 DEBUG(0,("alias[%s] member[%s]\n",
336 sid_string_dbg(&alias_sid
),
337 sid_string_dbg(&member_sid
)));
339 status
= pdb_enum_aliasmem(&alias_sid
, talloc_tos(),
340 &members
, &num_members
);
341 if (!NT_STATUS_IS_OK(status
)) {
342 DEBUG(0, ("Could not find current alias members %s - %s\n",
343 sid_string_dbg(&alias_sid
),
348 for (i
=0; i
< num_members
; i
++) {
351 match
= dom_sid_equal(&members
[i
], &member_sid
);
358 status
= NT_STATUS_OK
;
360 if (!is_member
&& mem
->active
) {
362 pdb_add_aliasmem(&alias_sid
, &member_sid
);
363 } else if (is_member
&& !mem
->active
) {
365 pdb_del_aliasmem(&alias_sid
, &member_sid
);
367 if (!NT_STATUS_IS_OK(status
)) {
368 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
370 sid_string_dbg(&member_sid
),
371 sid_string_dbg(&alias_sid
),
379 static int dssync_passdb_traverse_aliases(struct db_record
*rec
,
382 struct dssync_passdb_traverse_aliases
*state
=
383 (struct dssync_passdb_traverse_aliases
*)private_data
;
384 struct dssync_passdb
*pctx
=
385 talloc_get_type_abort(state
->ctx
->private_data
,
386 struct dssync_passdb
);
387 struct dssync_passdb_traverse_amembers mstate
;
388 struct dssync_passdb_obj
*obj
;
392 if (pctx
->methods
== NULL
) {
396 obj
= dssync_parse_obj(rec
->value
);
402 mstate
.ctx
= state
->ctx
;
403 mstate
.name
= "members";
405 ret
= obj
->members
->traverse_read(obj
->members
,
406 dssync_passdb_traverse_amembers
,
415 struct dssync_passdb_traverse_gmembers
{
416 struct dssync_context
*ctx
;
417 struct dssync_passdb_obj
*obj
;
422 struct dssync_passdb_traverse_groups
{
423 struct dssync_context
*ctx
;
428 static int dssync_passdb_traverse_gmembers(struct db_record
*rec
,
431 struct dssync_passdb_traverse_gmembers
*state
=
432 (struct dssync_passdb_traverse_gmembers
*)private_data
;
433 struct dssync_passdb
*pctx
=
434 talloc_get_type_abort(state
->ctx
->private_data
,
435 struct dssync_passdb
);
436 struct dssync_passdb_mem
*mem
;
438 char *nt_member
= NULL
;
440 struct dom_sid group_sid
;
441 struct dom_sid member_sid
;
442 struct samu
*member
= NULL
;
443 const char *member_dn
= NULL
;
447 bool is_unix_member
= false;
451 group_sid
= state
->obj
->cur
->object
.identifier
->sid
;
453 status
= dom_sid_split_rid(talloc_tos(), &group_sid
, NULL
, &rid
);
454 if (!NT_STATUS_IS_OK(status
)) {
458 mem
= dssync_parse_mem(rec
->value
);
463 member_sid
= mem
->cur
->sid
;
464 member_dn
= mem
->cur
->dn
;
466 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
467 if (mem
->obj
== NULL
) {
468 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
469 sid_string_dbg(&group_sid
),
470 is_null_sid(&member_sid
)?
471 sid_string_dbg(&member_sid
):
476 member_sid
= mem
->obj
->cur
->object
.identifier
->sid
;
477 member_dn
= mem
->obj
->cur
->object
.identifier
->dn
;
479 switch (mem
->obj
->type
) {
480 case ATYPE_SECURITY_LOCAL_GROUP
:
481 case ATYPE_SECURITY_GLOBAL_GROUP
:
482 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
483 sid_string_dbg(&group_sid
),
484 sid_string_dbg(&member_sid
)));
487 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
488 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
489 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
490 sid_string_dbg(&group_sid
),
497 if (!get_domain_group_from_sid(group_sid
, &map
)) {
498 DEBUG(0, ("Could not find global group %s\n",
499 sid_string_dbg(&group_sid
)));
500 //return NT_STATUS_NO_SUCH_GROUP;
504 if (!(grp
= getgrgid(map
.gid
))) {
505 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map
.gid
));
506 //return NT_STATUS_NO_SUCH_GROUP;
510 DEBUG(0,("Group members of %s: ", grp
->gr_name
));
512 if ( !(member
= samu_new(talloc_tos())) ) {
513 //return NT_STATUS_NO_MEMORY;
517 if (!pdb_getsampwsid(member
, &member_sid
)) {
518 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
519 sid_string_tos(&member_sid
), grp
->gr_name
));
524 if (pdb_get_group_rid(member
) == rid
) {
525 DEBUGADD(0,("%s(primary),", pdb_get_username(member
)));
530 DEBUGADD(0,("%s,", pdb_get_username(member
)));
531 nt_member
= talloc_strdup(talloc_tos(), pdb_get_username(member
));
536 unix_members
= grp
->gr_mem
;
538 while (*unix_members
) {
539 if (strcmp(*unix_members
, nt_member
) == 0) {
540 is_unix_member
= true;
546 if (!is_unix_member
&& mem
->active
) {
547 smb_add_user_group(grp
->gr_name
, nt_member
);
548 } else if (is_unix_member
&& !mem
->active
) {
549 smb_delete_user_group(grp
->gr_name
, nt_member
);
555 static int dssync_passdb_traverse_groups(struct db_record
*rec
,
558 struct dssync_passdb_traverse_groups
*state
=
559 (struct dssync_passdb_traverse_groups
*)private_data
;
560 struct dssync_passdb
*pctx
=
561 talloc_get_type_abort(state
->ctx
->private_data
,
562 struct dssync_passdb
);
563 struct dssync_passdb_traverse_gmembers mstate
;
564 struct dssync_passdb_obj
*obj
;
568 if (pctx
->methods
== NULL
) {
572 obj
= dssync_parse_obj(rec
->value
);
578 mstate
.ctx
= state
->ctx
;
579 mstate
.name
= "members";
581 ret
= obj
->members
->traverse_read(obj
->members
,
582 dssync_passdb_traverse_gmembers
,
591 static NTSTATUS
passdb_finish(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
592 struct replUpToDateVectorBlob
*new_utdv
)
594 struct dssync_passdb
*pctx
=
595 talloc_get_type_abort(ctx
->private_data
,
596 struct dssync_passdb
);
597 struct dssync_passdb_traverse_aliases astate
;
598 struct dssync_passdb_traverse_groups gstate
;
603 astate
.name
= "aliases";
604 ret
= pctx
->aliases
->traverse_read(pctx
->aliases
,
605 dssync_passdb_traverse_aliases
,
608 return NT_STATUS_INTERNAL_ERROR
;
613 gstate
.name
= "groups";
614 ret
= pctx
->groups
->traverse_read(pctx
->groups
,
615 dssync_passdb_traverse_groups
,
618 return NT_STATUS_INTERNAL_ERROR
;
621 TALLOC_FREE(pctx
->methods
);
627 /****************************************************************
628 ****************************************************************/
630 static NTSTATUS
smb_create_user(TALLOC_CTX
*mem_ctx
,
633 struct passwd
**passwd_p
)
635 struct passwd
*passwd
;
636 char *add_script
= NULL
;
638 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
644 /* Create appropriate user */
645 if (acct_flags
& ACB_NORMAL
) {
646 add_script
= talloc_strdup(mem_ctx
, lp_adduser_script());
647 } else if ( (acct_flags
& ACB_WSTRUST
) ||
648 (acct_flags
& ACB_SVRTRUST
) ||
649 (acct_flags
& ACB_DOMTRUST
) ) {
650 add_script
= talloc_strdup(mem_ctx
, lp_addmachine_script());
652 DEBUG(1, ("Unknown user type: %s\n",
653 pdb_encode_acct_ctrl(acct_flags
, NEW_PW_FORMAT_SPACE_PADDED_LEN
)));
654 return NT_STATUS_UNSUCCESSFUL
;
658 return NT_STATUS_NO_MEMORY
;
663 add_script
= talloc_all_string_sub(mem_ctx
, add_script
,
666 return NT_STATUS_NO_MEMORY
;
668 add_ret
= smbrun(add_script
, NULL
);
669 DEBUG(add_ret
? 0 : 1,("fetch_account: Running the command `%s' "
670 "gave %d\n", add_script
, add_ret
));
672 smb_nscd_flush_user_cache();
676 /* try and find the possible unix account again */
677 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
679 return NT_STATUS_NO_SUCH_USER
;
687 static struct drsuapi_DsReplicaAttribute
*find_drsuapi_attr(
688 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
693 for (i
= 0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
694 struct drsuapi_DsReplicaAttribute
*attr
;
696 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
698 if (attr
->attid
== attid
) {
706 static NTSTATUS
find_drsuapi_attr_string(TALLOC_CTX
*mem_ctx
,
707 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
712 struct drsuapi_DsReplicaAttribute
*attr
;
716 attr
= find_drsuapi_attr(cur
, attid
);
718 return NT_STATUS_PROPSET_NOT_FOUND
;
721 array
= talloc_array(mem_ctx
, char *, attr
->value_ctr
.num_values
);
723 return NT_STATUS_NO_MEMORY
;
726 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
727 const DATA_BLOB
*blob
;
730 blob
= attr
->value_ctr
.values
[a
].blob
;
733 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
736 ret
= pull_string_talloc(array
, NULL
, 0, &array
[a
],
737 blob
->data
, blob
->length
,
741 return NT_STATUS_INTERNAL_ERROR
;
745 *_count
= attr
->value_ctr
.num_values
;
750 static NTSTATUS
find_drsuapi_attr_int32(TALLOC_CTX
*mem_ctx
,
751 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
756 struct drsuapi_DsReplicaAttribute
*attr
;
760 attr
= find_drsuapi_attr(cur
, attid
);
762 return NT_STATUS_PROPSET_NOT_FOUND
;
765 array
= talloc_array(mem_ctx
, int32_t, attr
->value_ctr
.num_values
);
767 return NT_STATUS_NO_MEMORY
;
770 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
771 const DATA_BLOB
*blob
;
773 blob
= attr
->value_ctr
.values
[a
].blob
;
776 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
779 if (blob
->length
!= 4) {
780 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
783 array
[a
] = IVAL(blob
->data
, 0);
786 *_count
= attr
->value_ctr
.num_values
;
791 static NTSTATUS
find_drsuapi_attr_blob(TALLOC_CTX
*mem_ctx
,
792 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
797 struct drsuapi_DsReplicaAttribute
*attr
;
801 attr
= find_drsuapi_attr(cur
, attid
);
803 return NT_STATUS_PROPSET_NOT_FOUND
;
806 array
= talloc_array(mem_ctx
, DATA_BLOB
, attr
->value_ctr
.num_values
);
808 return NT_STATUS_NO_MEMORY
;
811 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
812 const DATA_BLOB
*blob
;
814 blob
= attr
->value_ctr
.values
[a
].blob
;
817 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
820 array
[a
] = data_blob_talloc(array
, blob
->data
, blob
->length
);
821 if (array
[a
].length
!= blob
->length
) {
822 return NT_STATUS_NO_MEMORY
;
825 *_count
= attr
->value_ctr
.num_values
;
830 static NTSTATUS
find_drsuapi_attr_int64(TALLOC_CTX
*mem_ctx
,
831 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
836 struct drsuapi_DsReplicaAttribute
*attr
;
840 attr
= find_drsuapi_attr(cur
, attid
);
842 return NT_STATUS_PROPSET_NOT_FOUND
;
845 array
= talloc_array(mem_ctx
, int64_t, attr
->value_ctr
.num_values
);
847 return NT_STATUS_NO_MEMORY
;
850 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
851 const DATA_BLOB
*blob
;
853 blob
= attr
->value_ctr
.values
[a
].blob
;
856 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
859 if (blob
->length
!= 8) {
860 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
863 array
[a
] = BVAL(blob
->data
, 0);
865 *_count
= attr
->value_ctr
.num_values
;
870 static NTSTATUS
find_drsuapi_attr_dn(TALLOC_CTX
*mem_ctx
,
871 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
874 struct drsuapi_DsReplicaObjectIdentifier3
**_array
)
876 struct drsuapi_DsReplicaAttribute
*attr
;
877 struct drsuapi_DsReplicaObjectIdentifier3
*array
;
880 attr
= find_drsuapi_attr(cur
, attid
);
882 return NT_STATUS_PROPSET_NOT_FOUND
;
885 array
= talloc_array(mem_ctx
,
886 struct drsuapi_DsReplicaObjectIdentifier3
,
887 attr
->value_ctr
.num_values
);
889 return NT_STATUS_NO_MEMORY
;
892 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
893 const DATA_BLOB
*blob
;
894 enum ndr_err_code ndr_err
;
897 blob
= attr
->value_ctr
.values
[a
].blob
;
900 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
903 /* windows sometimes sends an extra two pad bytes here */
904 ndr_err
= ndr_pull_struct_blob(blob
, array
, &array
[a
],
905 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
906 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
907 status
= ndr_map_error2ntstatus(ndr_err
);
911 *_count
= attr
->value_ctr
.num_values
;
916 #define GET_BLOB_EX(attr, needed) do { \
919 DATA_BLOB *_vals = NULL; \
920 attr = data_blob_null; \
921 _status = find_drsuapi_attr_blob(mem_ctx, cur, \
922 DRSUAPI_ATTID_ ## attr, \
924 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
926 _status = NT_STATUS_OK; \
930 if (!NT_STATUS_IS_OK(_status)) { \
931 DEBUG(0,(__location__ "attr[%s] %s\n", \
932 #attr, nt_errstr(_status))); \
937 talloc_free(_vals); \
938 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
939 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
941 } else if (_cnt > 1) { \
942 talloc_free(_vals); \
943 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
944 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
947 (void)talloc_steal(mem_ctx, _vals[0].data); \
949 talloc_free(_vals); \
952 #define GET_STRING_EX(attr, needed) do { \
955 char **_vals = NULL; \
957 _status = find_drsuapi_attr_string(mem_ctx, cur, \
958 DRSUAPI_ATTID_ ## attr, \
960 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
962 _status = NT_STATUS_OK; \
966 if (!NT_STATUS_IS_OK(_status)) { \
967 DEBUG(0,(__location__ "attr[%s] %s\n", \
968 #attr, nt_errstr(_status))); \
973 talloc_free(_vals); \
974 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
975 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
977 } else if (_cnt > 1) { \
978 talloc_free(_vals); \
979 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
980 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
982 attr = talloc_move(mem_ctx, &_vals[0]); \
984 talloc_free(_vals); \
987 #define GET_UINT32_EX(attr, needed) do { \
990 int32_t*_vals = NULL; \
992 _status = find_drsuapi_attr_int32(mem_ctx, cur, \
993 DRSUAPI_ATTID_ ## attr, \
995 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
997 _status = NT_STATUS_OK; \
1001 if (!NT_STATUS_IS_OK(_status)) { \
1002 DEBUG(0,(__location__ "attr[%s] %s\n", \
1003 #attr, nt_errstr(_status))); \
1008 talloc_free(_vals); \
1009 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1010 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1012 } else if (_cnt > 1) { \
1013 talloc_free(_vals); \
1014 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1015 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1017 attr = (uint32_t)_vals[0]; \
1019 talloc_free(_vals); \
1022 #define GET_UINT64_EX(attr, needed) do { \
1025 int64_t *_vals = NULL; \
1027 _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1028 DRSUAPI_ATTID_ ## attr, \
1030 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1032 _status = NT_STATUS_OK; \
1036 if (!NT_STATUS_IS_OK(_status)) { \
1037 DEBUG(0,(__location__ "attr[%s] %s\n", \
1038 #attr, nt_errstr(_status))); \
1043 talloc_free(_vals); \
1044 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1045 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1047 } else if (_cnt > 1) { \
1048 talloc_free(_vals); \
1049 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1050 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1052 attr = (uint64_t)_vals[0]; \
1054 talloc_free(_vals); \
1057 #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
1058 #define GET_STRING(attr) GET_STRING_EX(attr, false)
1059 #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
1060 #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
1062 /* Convert a struct samu_DELTA to a struct samu. */
1063 #define STRING_CHANGED (old_string && !new_string) ||\
1064 (!old_string && new_string) ||\
1065 (old_string && new_string && (strcmp(old_string, new_string) != 0))
1067 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1069 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1071 /****************************************************************
1072 ****************************************************************/
1074 static NTSTATUS
sam_account_from_object(struct samu
*account
,
1075 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1077 TALLOC_CTX
*mem_ctx
= account
;
1078 const char *old_string
, *new_string
;
1079 time_t unix_time
, stored_time
;
1086 NTTIME accountExpires
;
1087 const char *sAMAccountName
;
1088 const char *displayName
;
1089 const char *homeDirectory
;
1090 const char *homeDrive
;
1091 const char *scriptPath
;
1092 const char *profilePath
;
1093 const char *description
;
1094 const char *userWorkstations
;
1095 const char *comment
;
1096 DATA_BLOB userParameters
;
1097 struct dom_sid objectSid
;
1098 uint32_t primaryGroupID
;
1099 uint32_t userAccountControl
;
1100 DATA_BLOB logonHours
;
1101 uint32_t badPwdCount
;
1102 uint32_t logonCount
;
1103 DATA_BLOB unicodePwd
;
1107 uint32_t acct_flags
;
1108 uint32_t units_per_week
;
1110 memset(zero_buf
, '\0', sizeof(zero_buf
));
1112 objectSid
= cur
->object
.identifier
->sid
;
1113 GET_STRING_EX(sAMAccountName
, true);
1114 DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1115 sAMAccountName
, sid_string_dbg(&objectSid
)));
1116 GET_UINT64(lastLogon
);
1117 GET_UINT64(lastLogoff
);
1118 GET_UINT64(pwdLastSet
);
1119 GET_UINT64(accountExpires
);
1120 GET_STRING(displayName
);
1121 GET_STRING(homeDirectory
);
1122 GET_STRING(homeDrive
);
1123 GET_STRING(scriptPath
);
1124 GET_STRING(profilePath
);
1125 GET_STRING(description
);
1126 GET_STRING(userWorkstations
);
1127 GET_STRING(comment
);
1128 GET_BLOB(userParameters
);
1129 GET_UINT32(primaryGroupID
);
1130 GET_UINT32(userAccountControl
);
1131 GET_BLOB(logonHours
);
1132 GET_UINT32(badPwdCount
);
1133 GET_UINT32(logonCount
);
1134 GET_BLOB(unicodePwd
);
1137 status
= dom_sid_split_rid(mem_ctx
, &objectSid
, NULL
, &rid
);
1138 if (!NT_STATUS_IS_OK(status
)) {
1141 acct_flags
= ds_uf2acb(userAccountControl
);
1143 /* Username, fullname, home dir, dir drive, logon script, acct
1144 desc, workstations, profile. */
1146 if (sAMAccountName
) {
1147 old_string
= pdb_get_nt_username(account
);
1148 new_string
= sAMAccountName
;
1150 if (STRING_CHANGED
) {
1151 pdb_set_nt_username(account
, new_string
, PDB_CHANGED
);
1154 /* Unix username is the same - for sanity */
1155 old_string
= pdb_get_username( account
);
1156 if (STRING_CHANGED
) {
1157 pdb_set_username(account
, new_string
, PDB_CHANGED
);
1162 old_string
= pdb_get_fullname(account
);
1163 new_string
= displayName
;
1166 pdb_set_fullname(account
, new_string
, PDB_CHANGED
);
1169 if (homeDirectory
) {
1170 old_string
= pdb_get_homedir(account
);
1171 new_string
= homeDirectory
;
1174 pdb_set_homedir(account
, new_string
, PDB_CHANGED
);
1178 old_string
= pdb_get_dir_drive(account
);
1179 new_string
= homeDrive
;
1182 pdb_set_dir_drive(account
, new_string
, PDB_CHANGED
);
1186 old_string
= pdb_get_logon_script(account
);
1187 new_string
= scriptPath
;
1190 pdb_set_logon_script(account
, new_string
, PDB_CHANGED
);
1194 old_string
= pdb_get_acct_desc(account
);
1195 new_string
= description
;
1198 pdb_set_acct_desc(account
, new_string
, PDB_CHANGED
);
1201 if (userWorkstations
) {
1202 old_string
= pdb_get_workstations(account
);
1203 new_string
= userWorkstations
;
1206 pdb_set_workstations(account
, new_string
, PDB_CHANGED
);
1210 old_string
= pdb_get_profile_path(account
);
1211 new_string
= profilePath
;
1214 pdb_set_profile_path(account
, new_string
, PDB_CHANGED
);
1217 if (userParameters
.data
) {
1219 old_string
= pdb_get_munged_dial(account
);
1220 newstr
= (userParameters
.length
== 0) ? NULL
:
1221 base64_encode_data_blob(talloc_tos(), userParameters
);
1223 if (STRING_CHANGED_NC(old_string
, newstr
))
1224 pdb_set_munged_dial(account
, newstr
, PDB_CHANGED
);
1225 TALLOC_FREE(newstr
);
1228 /* User and group sid */
1229 if (rid
!= 0 && pdb_get_user_rid(account
) != rid
) {
1230 pdb_set_user_sid_from_rid(account
, rid
, PDB_CHANGED
);
1232 if (primaryGroupID
!= 0 && pdb_get_group_rid(account
) != primaryGroupID
) {
1233 pdb_set_group_sid_from_rid(account
, primaryGroupID
, PDB_CHANGED
);
1236 /* Logon and password information */
1237 if (!nt_time_is_zero(&lastLogon
)) {
1238 unix_time
= nt_time_to_unix(lastLogon
);
1239 stored_time
= pdb_get_logon_time(account
);
1240 if (stored_time
!= unix_time
)
1241 pdb_set_logon_time(account
, unix_time
, PDB_CHANGED
);
1244 if (!nt_time_is_zero(&lastLogoff
)) {
1245 unix_time
= nt_time_to_unix(lastLogoff
);
1246 stored_time
= pdb_get_logoff_time(account
);
1247 if (stored_time
!= unix_time
)
1248 pdb_set_logoff_time(account
, unix_time
,PDB_CHANGED
);
1252 units_per_week
= logonHours
.length
* 8;
1254 if (pdb_get_logon_divs(account
) != units_per_week
) {
1255 pdb_set_logon_divs(account
, units_per_week
, PDB_CHANGED
);
1258 /* Logon Hours Len */
1259 if (units_per_week
/8 != pdb_get_hours_len(account
)) {
1260 pdb_set_hours_len(account
, units_per_week
/8, PDB_CHANGED
);
1264 if (logonHours
.data
) {
1265 char oldstr
[44], newstr
[44];
1266 pdb_sethexhours(oldstr
, pdb_get_hours(account
));
1267 pdb_sethexhours(newstr
, logonHours
.data
);
1268 if (!strequal(oldstr
, newstr
)) {
1269 pdb_set_hours(account
, logonHours
.data
,
1270 logonHours
.length
, PDB_CHANGED
);
1274 if (pdb_get_bad_password_count(account
) != badPwdCount
)
1275 pdb_set_bad_password_count(account
, badPwdCount
, PDB_CHANGED
);
1277 if (pdb_get_logon_count(account
) != logonCount
)
1278 pdb_set_logon_count(account
, logonCount
, PDB_CHANGED
);
1280 if (!nt_time_is_zero(&pwdLastSet
)) {
1281 unix_time
= nt_time_to_unix(pwdLastSet
);
1282 stored_time
= pdb_get_pass_last_set_time(account
);
1283 if (stored_time
!= unix_time
)
1284 pdb_set_pass_last_set_time(account
, unix_time
, PDB_CHANGED
);
1286 /* no last set time, make it now */
1287 pdb_set_pass_last_set_time(account
, time(NULL
), PDB_CHANGED
);
1290 if (!nt_time_is_zero(&accountExpires
)) {
1291 unix_time
= nt_time_to_unix(accountExpires
);
1292 stored_time
= pdb_get_kickoff_time(account
);
1293 if (stored_time
!= unix_time
)
1294 pdb_set_kickoff_time(account
, unix_time
, PDB_CHANGED
);
1297 /* Decode hashes from password hash
1298 Note that win2000 may send us all zeros for the hashes if it doesn't
1299 think this channel is secure enough - don't set the passwords at all
1302 if (dBCSPwd
.length
== 16 && memcmp(dBCSPwd
.data
, zero_buf
, 16) != 0) {
1303 pdb_set_lanman_passwd(account
, dBCSPwd
.data
, PDB_CHANGED
);
1306 if (unicodePwd
.length
== 16 && memcmp(unicodePwd
.data
, zero_buf
, 16) != 0) {
1307 pdb_set_nt_passwd(account
, unicodePwd
.data
, PDB_CHANGED
);
1312 /* TODO: account expiry time */
1314 pdb_set_acct_ctrl(account
, acct_flags
, PDB_CHANGED
);
1316 pdb_set_domain(account
, lp_workgroup(), PDB_CHANGED
);
1318 DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1319 sAMAccountName
, sid_string_dbg(&objectSid
)));
1320 return NT_STATUS_OK
;
1323 /****************************************************************
1324 ****************************************************************/
1326 static NTSTATUS
handle_account_object(struct dssync_passdb
*pctx
,
1327 TALLOC_CTX
*mem_ctx
,
1328 struct dssync_passdb_obj
*obj
)
1330 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1333 struct samu
*sam_account
=NULL
;
1336 struct dom_sid user_sid
;
1337 struct dom_sid group_sid
;
1338 struct passwd
*passwd
= NULL
;
1339 uint32_t acct_flags
;
1342 const char *sAMAccountName
;
1343 uint32_t sAMAccountType
;
1344 uint32_t userAccountControl
;
1346 user_sid
= cur
->object
.identifier
->sid
;
1347 GET_STRING_EX(sAMAccountName
, true);
1348 GET_UINT32_EX(sAMAccountType
, true);
1349 GET_UINT32_EX(userAccountControl
, true);
1351 status
= dom_sid_split_rid(mem_ctx
, &user_sid
, NULL
, &rid
);
1352 if (!NT_STATUS_IS_OK(status
)) {
1356 fstrcpy(account
, sAMAccountName
);
1357 if (rid
== DOMAIN_RID_GUEST
) {
1359 * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1360 * that's why we need to ignore it here.
1362 * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1365 DEBUG(0,("Ignore %s - %s\n", account
, sid_string_dbg(&user_sid
)));
1366 return NT_STATUS_OK
;
1368 DEBUG(0,("Creating account: %s\n", account
));
1370 if ( !(sam_account
= samu_new(mem_ctx
)) ) {
1371 return NT_STATUS_NO_MEMORY
;
1374 acct_flags
= ds_uf2acb(userAccountControl
);
1375 status
= smb_create_user(sam_account
, acct_flags
, account
, &passwd
);
1376 if (!NT_STATUS_IS_OK(status
)) {
1377 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1378 account
, nt_errstr(status
)));
1379 TALLOC_FREE(sam_account
);
1383 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1384 sid_string_dbg(&user_sid
), account
));
1385 if (!pdb_getsampwsid(sam_account
, &user_sid
)) {
1386 sam_account_from_object(sam_account
, cur
);
1387 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
1388 sid_string_dbg(&user_sid
),
1389 pdb_get_username(sam_account
)));
1390 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account
))) {
1391 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1393 TALLOC_FREE(sam_account
);
1394 return NT_STATUS_ACCESS_DENIED
;
1397 sam_account_from_object(sam_account
, cur
);
1398 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
1399 sid_string_dbg(&user_sid
),
1400 pdb_get_username(sam_account
)));
1401 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account
))) {
1402 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1404 TALLOC_FREE(sam_account
);
1405 return NT_STATUS_ACCESS_DENIED
;
1409 if (pdb_get_group_sid(sam_account
) == NULL
) {
1410 TALLOC_FREE(sam_account
);
1411 return NT_STATUS_UNSUCCESSFUL
;
1414 group_sid
= *pdb_get_group_sid(sam_account
);
1416 if (!pdb_getgrsid(&map
, group_sid
)) {
1417 DEBUG(0, ("Primary group of %s has no mapping!\n",
1418 pdb_get_username(sam_account
)));
1420 if (map
.gid
!= passwd
->pw_gid
) {
1421 if (!(grp
= getgrgid(map
.gid
))) {
1422 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
1423 (unsigned long)map
.gid
, pdb_get_username(sam_account
),
1424 sid_string_dbg(&group_sid
)));
1426 smb_set_primary_group(grp
->gr_name
, pdb_get_username(sam_account
));
1432 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1433 pdb_get_username(sam_account
)));
1436 TALLOC_FREE(sam_account
);
1437 return NT_STATUS_OK
;
1440 /****************************************************************
1441 ****************************************************************/
1443 static NTSTATUS
handle_alias_object(struct dssync_passdb
*pctx
,
1444 TALLOC_CTX
*mem_ctx
,
1445 struct dssync_passdb_obj
*obj
)
1447 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1451 struct group
*grp
= NULL
;
1452 struct dom_sid group_sid
;
1454 struct dom_sid
*dom_sid
= NULL
;
1459 const char *sAMAccountName
;
1460 uint32_t sAMAccountType
;
1462 const char *description
;
1464 uint32_t num_members
= 0;
1465 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1467 group_sid
= cur
->object
.identifier
->sid
;
1468 GET_STRING_EX(sAMAccountName
, true);
1469 GET_UINT32_EX(sAMAccountType
, true);
1470 GET_UINT32_EX(groupType
, true);
1471 GET_STRING(description
);
1473 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1474 &num_members
, &members
);
1475 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1476 status
= NT_STATUS_OK
;
1478 if (!NT_STATUS_IS_OK(status
)) {
1482 fstrcpy(name
, sAMAccountName
);
1483 fstrcpy(comment
, description
);
1485 dom_sid_split_rid(mem_ctx
, &group_sid
, &dom_sid
, &rid
);
1487 sid_to_fstring(sid_string
, &group_sid
);
1488 DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1489 name
, sid_string
, num_members
));
1491 status
= dssync_insert_obj(pctx
, pctx
->aliases
, obj
);
1492 if (!NT_STATUS_IS_OK(status
)) {
1496 if (pdb_getgrsid(&map
, group_sid
)) {
1497 if ( map
.gid
!= -1 )
1498 grp
= getgrgid(map
.gid
);
1505 /* No group found from mapping, find it from its name. */
1506 if ((grp
= getgrnam(name
)) == NULL
) {
1508 /* No appropriate group found, create one */
1510 DEBUG(0,("Creating unix group: '%s'\n", name
));
1512 if (smb_create_group(name
, &gid
) != 0)
1513 return NT_STATUS_ACCESS_DENIED
;
1515 if ((grp
= getgrgid(gid
)) == NULL
)
1516 return NT_STATUS_ACCESS_DENIED
;
1520 map
.gid
= grp
->gr_gid
;
1521 map
.sid
= group_sid
;
1523 if (dom_sid_equal(dom_sid
, &global_sid_Builtin
)) {
1525 * pdb_ldap does not like SID_NAME_WKN_GRP...
1527 * map.sid_name_use = SID_NAME_WKN_GRP;
1529 map
.sid_name_use
= SID_NAME_ALIAS
;
1531 map
.sid_name_use
= SID_NAME_ALIAS
;
1534 strlcpy(map
.nt_name
, name
, sizeof(map
.nt_name
));
1536 strlcpy(map
.comment
, comment
, sizeof(map
.comment
));
1538 strlcpy(map
.comment
, "", sizeof(map
.comment
));
1542 pdb_add_group_mapping_entry(&map
);
1544 pdb_update_group_mapping_entry(&map
);
1546 for (i
=0; i
< num_members
; i
++) {
1547 struct dssync_passdb_mem
*mem
;
1549 status
= dssync_create_mem(pctx
, obj
,
1552 if (!NT_STATUS_IS_OK(status
)) {
1557 return NT_STATUS_OK
;
1560 /****************************************************************
1561 ****************************************************************/
1563 static NTSTATUS
handle_group_object(struct dssync_passdb
*pctx
,
1564 TALLOC_CTX
*mem_ctx
,
1565 struct dssync_passdb_obj
*obj
)
1567 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1571 struct group
*grp
= NULL
;
1572 struct dom_sid group_sid
;
1577 const char *sAMAccountName
;
1578 uint32_t sAMAccountType
;
1580 const char *description
;
1582 uint32_t num_members
= 0;
1583 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1585 group_sid
= cur
->object
.identifier
->sid
;
1586 GET_STRING_EX(sAMAccountName
, true);
1587 GET_UINT32_EX(sAMAccountType
, true);
1588 GET_UINT32_EX(groupType
, true);
1589 GET_STRING(description
);
1591 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1592 &num_members
, &members
);
1593 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1594 status
= NT_STATUS_OK
;
1596 if (!NT_STATUS_IS_OK(status
)) {
1600 fstrcpy(name
, sAMAccountName
);
1601 fstrcpy(comment
, description
);
1603 sid_to_fstring(sid_string
, &group_sid
);
1604 DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1605 name
, sid_string
, num_members
));
1607 status
= dssync_insert_obj(pctx
, pctx
->groups
, obj
);
1608 if (!NT_STATUS_IS_OK(status
)) {
1612 if (pdb_getgrsid(&map
, group_sid
)) {
1613 if ( map
.gid
!= -1 )
1614 grp
= getgrgid(map
.gid
);
1621 /* No group found from mapping, find it from its name. */
1622 if ((grp
= getgrnam(name
)) == NULL
) {
1624 /* No appropriate group found, create one */
1626 DEBUG(0,("Creating unix group: '%s'\n", name
));
1628 if (smb_create_group(name
, &gid
) != 0)
1629 return NT_STATUS_ACCESS_DENIED
;
1631 if ((grp
= getgrnam(name
)) == NULL
)
1632 return NT_STATUS_ACCESS_DENIED
;
1636 map
.gid
= grp
->gr_gid
;
1637 map
.sid
= group_sid
;
1638 map
.sid_name_use
= SID_NAME_DOM_GRP
;
1639 strlcpy(map
.nt_name
, name
, sizeof(map
.nt_name
));
1641 strlcpy(map
.comment
, comment
, sizeof(map
.comment
));
1643 strlcpy(map
.comment
, "", sizeof(map
.comment
));
1647 pdb_add_group_mapping_entry(&map
);
1649 pdb_update_group_mapping_entry(&map
);
1651 for (i
=0; i
< num_members
; i
++) {
1652 struct dssync_passdb_mem
*mem
;
1654 status
= dssync_create_mem(pctx
, obj
,
1657 if (!NT_STATUS_IS_OK(status
)) {
1662 return NT_STATUS_OK
;
1665 /****************************************************************
1666 ****************************************************************/
1668 static NTSTATUS
handle_interdomain_trust_object(struct dssync_passdb
*pctx
,
1669 TALLOC_CTX
*mem_ctx
,
1670 struct dssync_passdb_obj
*obj
)
1672 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1673 DEBUG(0,("trust: %s\n", cur
->object
.identifier
->dn
));
1674 return NT_STATUS_NOT_IMPLEMENTED
;
1677 /****************************************************************
1678 ****************************************************************/
1680 struct dssync_object_table_t
{
1682 NTSTATUS (*fn
) (struct dssync_passdb
*pctx
,
1683 TALLOC_CTX
*mem_ctx
,
1684 struct dssync_passdb_obj
*obj
);
1687 static const struct dssync_object_table_t dssync_object_table
[] = {
1688 { ATYPE_NORMAL_ACCOUNT
, handle_account_object
},
1689 { ATYPE_WORKSTATION_TRUST
, handle_account_object
},
1690 { ATYPE_SECURITY_LOCAL_GROUP
, handle_alias_object
},
1691 { ATYPE_SECURITY_GLOBAL_GROUP
, handle_group_object
},
1692 { ATYPE_INTERDOMAIN_TRUST
, handle_interdomain_trust_object
},
1695 /****************************************************************
1696 ****************************************************************/
1698 static NTSTATUS
parse_object(struct dssync_passdb
*pctx
,
1699 TALLOC_CTX
*mem_ctx
,
1700 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1702 NTSTATUS status
= NT_STATUS_OK
;
1706 struct drsuapi_DsReplicaAttribute
*attr
;
1710 uint32_t sam_type
= 0;
1712 DEBUG(3, ("parsing object '%s'\n", cur
->object
.identifier
->dn
));
1714 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
1716 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
1718 if (attr
->value_ctr
.num_values
!= 1) {
1722 if (!attr
->value_ctr
.values
[0].blob
) {
1726 blob
= attr
->value_ctr
.values
[0].blob
;
1728 switch (attr
->attid
) {
1729 case DRSUAPI_ATTID_sAMAccountName
:
1730 pull_string_talloc(mem_ctx
, NULL
, 0, &name
,
1731 blob
->data
, blob
->length
,
1734 case DRSUAPI_ATTID_sAMAccountType
:
1735 sam_type
= IVAL(blob
->data
, 0);
1737 case DRSUAPI_ATTID_userAccountControl
:
1738 uacc
= IVAL(blob
->data
, 0);
1745 for (a
=0; a
< ARRAY_SIZE(dssync_object_table
); a
++) {
1746 if (sam_type
== dssync_object_table
[a
].type
) {
1747 if (dssync_object_table
[a
].fn
) {
1748 struct dssync_passdb_obj
*obj
;
1749 status
= dssync_create_obj(pctx
, pctx
->all
,
1750 sam_type
, cur
, &obj
);
1751 if (!NT_STATUS_IS_OK(status
)) {
1754 status
= dssync_object_table
[a
].fn(pctx
,
1765 static NTSTATUS
parse_link(struct dssync_passdb
*pctx
,
1766 TALLOC_CTX
*mem_ctx
,
1767 struct drsuapi_DsReplicaLinkedAttribute
*cur
)
1769 struct drsuapi_DsReplicaObjectIdentifier3
*id3
;
1770 const DATA_BLOB
*blob
;
1771 enum ndr_err_code ndr_err
;
1773 bool active
= false;
1774 struct dssync_passdb_mem
*mem
;
1775 struct dssync_passdb_obj
*obj
;
1777 if (cur
->attid
!= DRSUAPI_ATTID_member
) {
1778 return NT_STATUS_OK
;
1781 if (cur
->flags
& DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
) {
1785 DEBUG(3, ("parsing link '%s' - %s\n",
1786 cur
->identifier
->dn
, active
?"adding":"deleting"));
1788 blob
= cur
->value
.blob
;
1791 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1794 obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &cur
->identifier
->guid
);
1796 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1799 id3
= talloc_zero(obj
, struct drsuapi_DsReplicaObjectIdentifier3
);
1801 return NT_STATUS_NO_MEMORY
;
1804 /* windows sometimes sends an extra two pad bytes here */
1805 ndr_err
= ndr_pull_struct_blob(blob
, id3
, id3
,
1806 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
1807 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1808 status
= ndr_map_error2ntstatus(ndr_err
);
1812 status
= dssync_create_mem(pctx
, obj
,
1815 if (!NT_STATUS_IS_OK(status
)) {
1819 return NT_STATUS_OK
;
1822 /****************************************************************
1823 ****************************************************************/
1825 static NTSTATUS
passdb_process_objects(struct dssync_context
*ctx
,
1826 TALLOC_CTX
*mem_ctx
,
1827 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
1828 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1830 NTSTATUS status
= NT_STATUS_OK
;
1831 struct dssync_passdb
*pctx
=
1832 talloc_get_type_abort(ctx
->private_data
,
1833 struct dssync_passdb
);
1835 for (; cur
; cur
= cur
->next_object
) {
1836 status
= parse_object(pctx
, mem_ctx
, cur
);
1837 if (!NT_STATUS_IS_OK(status
)) {
1846 /****************************************************************
1847 ****************************************************************/
1849 static NTSTATUS
passdb_process_links(struct dssync_context
*ctx
,
1850 TALLOC_CTX
*mem_ctx
,
1852 struct drsuapi_DsReplicaLinkedAttribute
*links
,
1853 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1855 NTSTATUS status
= NT_STATUS_OK
;
1856 struct dssync_passdb
*pctx
=
1857 talloc_get_type_abort(ctx
->private_data
,
1858 struct dssync_passdb
);
1861 for (i
= 0; i
< count
; i
++) {
1862 status
= parse_link(pctx
, mem_ctx
, &links
[i
]);
1863 if (!NT_STATUS_IS_OK(status
)) {
1872 /****************************************************************
1873 ****************************************************************/
1875 const struct dssync_ops libnet_dssync_passdb_ops
= {
1876 .startup
= passdb_startup
,
1877 .process_objects
= passdb_process_objects
,
1878 .process_links
= passdb_process_links
,
1879 .finish
= passdb_finish
,