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 "libnet/libnet_dssync.h"
22 #include "libnet/libnet_samsync.h"
23 #include "../libcli/security/security.h"
24 #include "../libds/common/flags.h"
25 #include "../librpc/gen_ndr/ndr_drsuapi.h"
27 #include "../libds/common/flag_mapping.h"
29 /****************************************************************
30 ****************************************************************/
32 struct dssync_passdb
{
33 struct pdb_methods
*methods
;
34 struct db_context
*all
;
35 struct db_context
*aliases
;
36 struct db_context
*groups
;
39 struct dssync_passdb_obj
{
40 struct dssync_passdb_obj
*self
;
42 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
45 struct db_context
*members
;
48 struct dssync_passdb_mem
{
49 struct dssync_passdb_mem
*self
;
51 struct drsuapi_DsReplicaObjectIdentifier3
*cur
;
52 struct dssync_passdb_obj
*obj
;
57 static NTSTATUS
dssync_insert_obj(struct dssync_passdb
*pctx
,
58 struct db_context
*db
,
59 struct dssync_passdb_obj
*obj
)
62 struct db_record
*rec
;
64 rec
= db
->fetch_locked(db
, talloc_tos(), obj
->key
);
66 return NT_STATUS_NO_MEMORY
;
68 if (rec
->value
.dsize
!= 0) {
72 status
= rec
->store(rec
, obj
->data
, TDB_INSERT
);
73 if (!NT_STATUS_IS_OK(status
)) {
81 static struct dssync_passdb_obj
*dssync_parse_obj(const TDB_DATA data
)
83 struct dssync_passdb_obj
*obj
;
85 if (data
.dsize
!= sizeof(obj
)) {
90 * we need to copy the pointer to avoid alignment problems
93 memcpy(&obj
, data
.dptr
, sizeof(obj
));
95 return talloc_get_type_abort(obj
, struct dssync_passdb_obj
);
98 static struct dssync_passdb_obj
*dssync_search_obj_by_guid(struct dssync_passdb
*pctx
,
99 struct db_context
*db
,
100 const struct GUID
*guid
)
102 struct dssync_passdb_obj
*obj
;
107 key
= make_tdb_data((const uint8_t *)(void *)guid
,
110 ret
= db
->fetch(db
, talloc_tos(), key
, &data
);
115 obj
= dssync_parse_obj(data
);
119 static NTSTATUS
dssync_create_obj(struct dssync_passdb
*pctx
,
120 struct db_context
*db
,
122 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
123 struct dssync_passdb_obj
**_obj
)
126 struct dssync_passdb_obj
*obj
;
128 obj
= talloc_zero(pctx
, struct dssync_passdb_obj
);
130 return NT_STATUS_NO_MEMORY
;
135 obj
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->object
.identifier
->guid
,
136 sizeof(cur
->object
.identifier
->guid
));
137 obj
->data
= make_tdb_data((const uint8_t *)(void *)&obj
->self
,
140 obj
->members
= db_open_rbt(obj
);
141 if (obj
->members
== NULL
) {
142 return NT_STATUS_NO_MEMORY
;
145 status
= dssync_insert_obj(pctx
, db
, obj
);
146 if (!NT_STATUS_IS_OK(status
)) {
154 static NTSTATUS
dssync_insert_mem(struct dssync_passdb
*pctx
,
155 struct dssync_passdb_obj
*obj
,
156 struct dssync_passdb_mem
*mem
)
159 struct db_record
*rec
;
161 rec
= obj
->members
->fetch_locked(obj
->members
, talloc_tos(), mem
->key
);
163 return NT_STATUS_NO_MEMORY
;
165 if (rec
->value
.dsize
!= 0) {
169 status
= rec
->store(rec
, mem
->data
, TDB_INSERT
);
170 if (!NT_STATUS_IS_OK(status
)) {
178 static NTSTATUS
dssync_create_mem(struct dssync_passdb
*pctx
,
179 struct dssync_passdb_obj
*obj
,
181 struct drsuapi_DsReplicaObjectIdentifier3
*cur
,
182 struct dssync_passdb_mem
**_mem
)
185 struct dssync_passdb_mem
*mem
;
187 mem
= talloc_zero(pctx
, struct dssync_passdb_mem
);
189 return NT_STATUS_NO_MEMORY
;
193 mem
->active
= active
;
195 mem
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->guid
,
197 mem
->data
= make_tdb_data((const uint8_t *)(void *)&mem
->self
,
200 status
= dssync_insert_mem(pctx
, obj
, mem
);
201 if (!NT_STATUS_IS_OK(status
)) {
209 static struct dssync_passdb_mem
*dssync_parse_mem(const TDB_DATA data
)
211 struct dssync_passdb_mem
*mem
;
213 if (data
.dsize
!= sizeof(mem
)) {
218 * we need to copy the pointer to avoid alignment problems
221 memcpy(&mem
, data
.dptr
, sizeof(mem
));
223 return talloc_get_type_abort(mem
, struct dssync_passdb_mem
);
226 static NTSTATUS
passdb_startup(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
227 struct replUpToDateVectorBlob
**pold_utdv
)
230 struct dssync_passdb
*pctx
;
232 pctx
= talloc_zero(mem_ctx
, struct dssync_passdb
);
234 return NT_STATUS_NO_MEMORY
;
237 if (ctx
->output_filename
) {
238 status
= make_pdb_method_name(&pctx
->methods
, ctx
->output_filename
);
240 status
= make_pdb_method_name(&pctx
->methods
, lp_passdb_backend());
243 if (!NT_STATUS_IS_OK(status
)) {
247 pctx
->all
= db_open_rbt(pctx
);
248 if (pctx
->all
== NULL
) {
249 return NT_STATUS_NO_MEMORY
;
251 pctx
->aliases
= db_open_rbt(pctx
);
252 if (pctx
->aliases
== NULL
) {
253 return NT_STATUS_NO_MEMORY
;
255 pctx
->groups
= db_open_rbt(pctx
);
256 if (pctx
->groups
== NULL
) {
257 return NT_STATUS_NO_MEMORY
;
260 ctx
->private_data
= pctx
;
265 /****************************************************************
266 ****************************************************************/
268 struct dssync_passdb_traverse_amembers
{
269 struct dssync_context
*ctx
;
270 struct dssync_passdb_obj
*obj
;
275 struct dssync_passdb_traverse_aliases
{
276 struct dssync_context
*ctx
;
281 static int dssync_passdb_traverse_amembers(struct db_record
*rec
,
284 struct dssync_passdb_traverse_amembers
*state
=
285 (struct dssync_passdb_traverse_amembers
*)private_data
;
286 struct dssync_passdb
*pctx
=
287 talloc_get_type_abort(state
->ctx
->private_data
,
288 struct dssync_passdb
);
289 struct dssync_passdb_mem
*mem
;
291 struct dom_sid alias_sid
;
292 struct dom_sid member_sid
;
293 const char *member_dn
;
296 struct dom_sid
*members
;
297 bool is_member
= false;
302 alias_sid
= state
->obj
->cur
->object
.identifier
->sid
;
304 mem
= dssync_parse_mem(rec
->value
);
309 member_sid
= mem
->cur
->sid
;
310 member_dn
= mem
->cur
->dn
;
312 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
313 if (mem
->obj
== NULL
) {
314 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
315 sid_string_dbg(&alias_sid
),
316 is_null_sid(&member_sid
)?
317 sid_string_dbg(&member_sid
):
322 switch (mem
->obj
->type
) {
323 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
324 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
325 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
326 sid_string_dbg(&alias_sid
),
333 DEBUG(0,("alias[%s] member[%s]\n",
334 sid_string_dbg(&alias_sid
),
335 sid_string_dbg(&member_sid
)));
337 status
= pdb_enum_aliasmem(&alias_sid
, talloc_tos(),
338 &members
, &num_members
);
339 if (!NT_STATUS_IS_OK(status
)) {
340 DEBUG(0, ("Could not find current alias members %s - %s\n",
341 sid_string_dbg(&alias_sid
),
346 for (i
=0; i
< num_members
; i
++) {
349 match
= dom_sid_equal(&members
[i
], &member_sid
);
356 status
= NT_STATUS_OK
;
358 if (!is_member
&& mem
->active
) {
360 pdb_add_aliasmem(&alias_sid
, &member_sid
);
361 } else if (is_member
&& !mem
->active
) {
363 pdb_del_aliasmem(&alias_sid
, &member_sid
);
365 if (!NT_STATUS_IS_OK(status
)) {
366 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
368 sid_string_dbg(&member_sid
),
369 sid_string_dbg(&alias_sid
),
377 static int dssync_passdb_traverse_aliases(struct db_record
*rec
,
380 struct dssync_passdb_traverse_aliases
*state
=
381 (struct dssync_passdb_traverse_aliases
*)private_data
;
382 struct dssync_passdb
*pctx
=
383 talloc_get_type_abort(state
->ctx
->private_data
,
384 struct dssync_passdb
);
385 struct dssync_passdb_traverse_amembers mstate
;
386 struct dssync_passdb_obj
*obj
;
390 if (pctx
->methods
== NULL
) {
394 obj
= dssync_parse_obj(rec
->value
);
400 mstate
.ctx
= state
->ctx
;
401 mstate
.name
= "members";
403 ret
= obj
->members
->traverse_read(obj
->members
,
404 dssync_passdb_traverse_amembers
,
413 struct dssync_passdb_traverse_gmembers
{
414 struct dssync_context
*ctx
;
415 struct dssync_passdb_obj
*obj
;
420 struct dssync_passdb_traverse_groups
{
421 struct dssync_context
*ctx
;
426 static int dssync_passdb_traverse_gmembers(struct db_record
*rec
,
429 struct dssync_passdb_traverse_gmembers
*state
=
430 (struct dssync_passdb_traverse_gmembers
*)private_data
;
431 struct dssync_passdb
*pctx
=
432 talloc_get_type_abort(state
->ctx
->private_data
,
433 struct dssync_passdb
);
434 struct dssync_passdb_mem
*mem
;
436 char *nt_member
= NULL
;
438 struct dom_sid group_sid
;
439 struct dom_sid member_sid
;
440 struct samu
*member
= NULL
;
441 const char *member_dn
= NULL
;
445 bool is_unix_member
= false;
449 group_sid
= state
->obj
->cur
->object
.identifier
->sid
;
451 status
= dom_sid_split_rid(talloc_tos(), &group_sid
, NULL
, &rid
);
452 if (!NT_STATUS_IS_OK(status
)) {
456 mem
= dssync_parse_mem(rec
->value
);
461 member_sid
= mem
->cur
->sid
;
462 member_dn
= mem
->cur
->dn
;
464 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
465 if (mem
->obj
== NULL
) {
466 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
467 sid_string_dbg(&group_sid
),
468 is_null_sid(&member_sid
)?
469 sid_string_dbg(&member_sid
):
474 member_sid
= mem
->obj
->cur
->object
.identifier
->sid
;
475 member_dn
= mem
->obj
->cur
->object
.identifier
->dn
;
477 switch (mem
->obj
->type
) {
478 case ATYPE_SECURITY_LOCAL_GROUP
:
479 case ATYPE_SECURITY_GLOBAL_GROUP
:
480 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
481 sid_string_dbg(&group_sid
),
482 sid_string_dbg(&member_sid
)));
485 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
486 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
487 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
488 sid_string_dbg(&group_sid
),
495 if (!get_domain_group_from_sid(group_sid
, &map
)) {
496 DEBUG(0, ("Could not find global group %s\n",
497 sid_string_dbg(&group_sid
)));
498 //return NT_STATUS_NO_SUCH_GROUP;
502 if (!(grp
= getgrgid(map
.gid
))) {
503 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map
.gid
));
504 //return NT_STATUS_NO_SUCH_GROUP;
508 DEBUG(0,("Group members of %s: ", grp
->gr_name
));
510 if ( !(member
= samu_new(talloc_tos())) ) {
511 //return NT_STATUS_NO_MEMORY;
515 if (!pdb_getsampwsid(member
, &member_sid
)) {
516 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
517 sid_string_tos(&member_sid
), grp
->gr_name
));
522 if (pdb_get_group_rid(member
) == rid
) {
523 DEBUGADD(0,("%s(primary),", pdb_get_username(member
)));
528 DEBUGADD(0,("%s,", pdb_get_username(member
)));
529 nt_member
= talloc_strdup(talloc_tos(), pdb_get_username(member
));
534 unix_members
= grp
->gr_mem
;
536 while (*unix_members
) {
537 if (strcmp(*unix_members
, nt_member
) == 0) {
538 is_unix_member
= true;
544 if (!is_unix_member
&& mem
->active
) {
545 smb_add_user_group(grp
->gr_name
, nt_member
);
546 } else if (is_unix_member
&& !mem
->active
) {
547 smb_delete_user_group(grp
->gr_name
, nt_member
);
553 static int dssync_passdb_traverse_groups(struct db_record
*rec
,
556 struct dssync_passdb_traverse_groups
*state
=
557 (struct dssync_passdb_traverse_groups
*)private_data
;
558 struct dssync_passdb
*pctx
=
559 talloc_get_type_abort(state
->ctx
->private_data
,
560 struct dssync_passdb
);
561 struct dssync_passdb_traverse_gmembers mstate
;
562 struct dssync_passdb_obj
*obj
;
566 if (pctx
->methods
== NULL
) {
570 obj
= dssync_parse_obj(rec
->value
);
576 mstate
.ctx
= state
->ctx
;
577 mstate
.name
= "members";
579 ret
= obj
->members
->traverse_read(obj
->members
,
580 dssync_passdb_traverse_gmembers
,
589 static NTSTATUS
passdb_finish(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
590 struct replUpToDateVectorBlob
*new_utdv
)
592 struct dssync_passdb
*pctx
=
593 talloc_get_type_abort(ctx
->private_data
,
594 struct dssync_passdb
);
595 struct dssync_passdb_traverse_aliases astate
;
596 struct dssync_passdb_traverse_groups gstate
;
601 astate
.name
= "aliases";
602 ret
= pctx
->aliases
->traverse_read(pctx
->aliases
,
603 dssync_passdb_traverse_aliases
,
606 return NT_STATUS_INTERNAL_ERROR
;
611 gstate
.name
= "groups";
612 ret
= pctx
->groups
->traverse_read(pctx
->groups
,
613 dssync_passdb_traverse_groups
,
616 return NT_STATUS_INTERNAL_ERROR
;
619 TALLOC_FREE(pctx
->methods
);
625 /****************************************************************
626 ****************************************************************/
628 static NTSTATUS
smb_create_user(TALLOC_CTX
*mem_ctx
,
631 struct passwd
**passwd_p
)
633 struct passwd
*passwd
;
634 char *add_script
= NULL
;
636 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
642 /* Create appropriate user */
643 if (acct_flags
& ACB_NORMAL
) {
644 add_script
= talloc_strdup(mem_ctx
, lp_adduser_script());
645 } else if ( (acct_flags
& ACB_WSTRUST
) ||
646 (acct_flags
& ACB_SVRTRUST
) ||
647 (acct_flags
& ACB_DOMTRUST
) ) {
648 add_script
= talloc_strdup(mem_ctx
, lp_addmachine_script());
650 DEBUG(1, ("Unknown user type: %s\n",
651 pdb_encode_acct_ctrl(acct_flags
, NEW_PW_FORMAT_SPACE_PADDED_LEN
)));
652 return NT_STATUS_UNSUCCESSFUL
;
656 return NT_STATUS_NO_MEMORY
;
661 add_script
= talloc_all_string_sub(mem_ctx
, add_script
,
664 return NT_STATUS_NO_MEMORY
;
666 add_ret
= smbrun(add_script
, NULL
);
667 DEBUG(add_ret
? 0 : 1,("fetch_account: Running the command `%s' "
668 "gave %d\n", add_script
, add_ret
));
670 smb_nscd_flush_user_cache();
674 /* try and find the possible unix account again */
675 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
677 return NT_STATUS_NO_SUCH_USER
;
685 static struct drsuapi_DsReplicaAttribute
*find_drsuapi_attr(
686 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
691 for (i
= 0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
692 struct drsuapi_DsReplicaAttribute
*attr
;
694 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
696 if (attr
->attid
== attid
) {
704 static NTSTATUS
find_drsuapi_attr_string(TALLOC_CTX
*mem_ctx
,
705 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
710 struct drsuapi_DsReplicaAttribute
*attr
;
714 attr
= find_drsuapi_attr(cur
, attid
);
716 return NT_STATUS_PROPSET_NOT_FOUND
;
719 array
= talloc_array(mem_ctx
, char *, attr
->value_ctr
.num_values
);
721 return NT_STATUS_NO_MEMORY
;
724 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
725 const DATA_BLOB
*blob
;
728 blob
= attr
->value_ctr
.values
[a
].blob
;
731 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
734 ret
= pull_string_talloc(array
, NULL
, 0, &array
[a
],
735 blob
->data
, blob
->length
,
739 return NT_STATUS_INTERNAL_ERROR
;
743 *_count
= attr
->value_ctr
.num_values
;
748 static NTSTATUS
find_drsuapi_attr_int32(TALLOC_CTX
*mem_ctx
,
749 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
754 struct drsuapi_DsReplicaAttribute
*attr
;
758 attr
= find_drsuapi_attr(cur
, attid
);
760 return NT_STATUS_PROPSET_NOT_FOUND
;
763 array
= talloc_array(mem_ctx
, int32_t, attr
->value_ctr
.num_values
);
765 return NT_STATUS_NO_MEMORY
;
768 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
769 const DATA_BLOB
*blob
;
771 blob
= attr
->value_ctr
.values
[a
].blob
;
774 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
777 if (blob
->length
!= 4) {
778 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
781 array
[a
] = IVAL(blob
->data
, 0);
784 *_count
= attr
->value_ctr
.num_values
;
789 static NTSTATUS
find_drsuapi_attr_blob(TALLOC_CTX
*mem_ctx
,
790 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
795 struct drsuapi_DsReplicaAttribute
*attr
;
799 attr
= find_drsuapi_attr(cur
, attid
);
801 return NT_STATUS_PROPSET_NOT_FOUND
;
804 array
= talloc_array(mem_ctx
, DATA_BLOB
, attr
->value_ctr
.num_values
);
806 return NT_STATUS_NO_MEMORY
;
809 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
810 const DATA_BLOB
*blob
;
812 blob
= attr
->value_ctr
.values
[a
].blob
;
815 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
818 array
[a
] = data_blob_talloc(array
, blob
->data
, blob
->length
);
819 if (array
[a
].length
!= blob
->length
) {
820 return NT_STATUS_NO_MEMORY
;
823 *_count
= attr
->value_ctr
.num_values
;
828 static NTSTATUS
find_drsuapi_attr_int64(TALLOC_CTX
*mem_ctx
,
829 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
834 struct drsuapi_DsReplicaAttribute
*attr
;
838 attr
= find_drsuapi_attr(cur
, attid
);
840 return NT_STATUS_PROPSET_NOT_FOUND
;
843 array
= talloc_array(mem_ctx
, int64_t, attr
->value_ctr
.num_values
);
845 return NT_STATUS_NO_MEMORY
;
848 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
849 const DATA_BLOB
*blob
;
851 blob
= attr
->value_ctr
.values
[a
].blob
;
854 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
857 if (blob
->length
!= 8) {
858 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
861 array
[a
] = BVAL(blob
->data
, 0);
863 *_count
= attr
->value_ctr
.num_values
;
868 static NTSTATUS
find_drsuapi_attr_dn(TALLOC_CTX
*mem_ctx
,
869 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
872 struct drsuapi_DsReplicaObjectIdentifier3
**_array
)
874 struct drsuapi_DsReplicaAttribute
*attr
;
875 struct drsuapi_DsReplicaObjectIdentifier3
*array
;
878 attr
= find_drsuapi_attr(cur
, attid
);
880 return NT_STATUS_PROPSET_NOT_FOUND
;
883 array
= talloc_array(mem_ctx
,
884 struct drsuapi_DsReplicaObjectIdentifier3
,
885 attr
->value_ctr
.num_values
);
887 return NT_STATUS_NO_MEMORY
;
890 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
891 const DATA_BLOB
*blob
;
892 enum ndr_err_code ndr_err
;
895 blob
= attr
->value_ctr
.values
[a
].blob
;
898 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
901 /* windows sometimes sends an extra two pad bytes here */
902 ndr_err
= ndr_pull_struct_blob(blob
, array
, &array
[a
],
903 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
904 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
905 status
= ndr_map_error2ntstatus(ndr_err
);
909 *_count
= attr
->value_ctr
.num_values
;
914 #define GET_BLOB_EX(attr, needed) do { \
917 DATA_BLOB *_vals = NULL; \
918 attr = data_blob_null; \
919 _status = find_drsuapi_attr_blob(mem_ctx, cur, \
920 DRSUAPI_ATTID_ ## attr, \
922 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
924 _status = NT_STATUS_OK; \
928 if (!NT_STATUS_IS_OK(_status)) { \
929 DEBUG(0,(__location__ "attr[%s] %s\n", \
930 #attr, nt_errstr(_status))); \
935 talloc_free(_vals); \
936 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
937 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
939 } else if (_cnt > 1) { \
940 talloc_free(_vals); \
941 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
942 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
945 (void)talloc_steal(mem_ctx, _vals[0].data); \
947 talloc_free(_vals); \
950 #define GET_STRING_EX(attr, needed) do { \
953 char **_vals = NULL; \
955 _status = find_drsuapi_attr_string(mem_ctx, cur, \
956 DRSUAPI_ATTID_ ## attr, \
958 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
960 _status = NT_STATUS_OK; \
964 if (!NT_STATUS_IS_OK(_status)) { \
965 DEBUG(0,(__location__ "attr[%s] %s\n", \
966 #attr, nt_errstr(_status))); \
971 talloc_free(_vals); \
972 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
973 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
975 } else if (_cnt > 1) { \
976 talloc_free(_vals); \
977 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
978 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
980 attr = talloc_move(mem_ctx, &_vals[0]); \
982 talloc_free(_vals); \
985 #define GET_UINT32_EX(attr, needed) do { \
988 int32_t*_vals = NULL; \
990 _status = find_drsuapi_attr_int32(mem_ctx, cur, \
991 DRSUAPI_ATTID_ ## attr, \
993 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
995 _status = NT_STATUS_OK; \
999 if (!NT_STATUS_IS_OK(_status)) { \
1000 DEBUG(0,(__location__ "attr[%s] %s\n", \
1001 #attr, nt_errstr(_status))); \
1006 talloc_free(_vals); \
1007 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1008 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1010 } else if (_cnt > 1) { \
1011 talloc_free(_vals); \
1012 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1013 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1015 attr = (uint32_t)_vals[0]; \
1017 talloc_free(_vals); \
1020 #define GET_UINT64_EX(attr, needed) do { \
1023 int64_t *_vals = NULL; \
1025 _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1026 DRSUAPI_ATTID_ ## attr, \
1028 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1030 _status = NT_STATUS_OK; \
1034 if (!NT_STATUS_IS_OK(_status)) { \
1035 DEBUG(0,(__location__ "attr[%s] %s\n", \
1036 #attr, nt_errstr(_status))); \
1041 talloc_free(_vals); \
1042 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1043 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1045 } else if (_cnt > 1) { \
1046 talloc_free(_vals); \
1047 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1048 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1050 attr = (uint64_t)_vals[0]; \
1052 talloc_free(_vals); \
1055 #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
1056 #define GET_STRING(attr) GET_STRING_EX(attr, false)
1057 #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
1058 #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
1060 /* Convert a struct samu_DELTA to a struct samu. */
1061 #define STRING_CHANGED (old_string && !new_string) ||\
1062 (!old_string && new_string) ||\
1063 (old_string && new_string && (strcmp(old_string, new_string) != 0))
1065 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1067 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1069 /****************************************************************
1070 ****************************************************************/
1072 static NTSTATUS
sam_account_from_object(struct samu
*account
,
1073 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1075 TALLOC_CTX
*mem_ctx
= account
;
1076 const char *old_string
, *new_string
;
1077 time_t unix_time
, stored_time
;
1084 NTTIME accountExpires
;
1085 const char *sAMAccountName
;
1086 const char *displayName
;
1087 const char *homeDirectory
;
1088 const char *homeDrive
;
1089 const char *scriptPath
;
1090 const char *profilePath
;
1091 const char *description
;
1092 const char *userWorkstations
;
1093 const char *comment
;
1094 DATA_BLOB userParameters
;
1095 struct dom_sid objectSid
;
1096 uint32_t primaryGroupID
;
1097 uint32_t userAccountControl
;
1098 DATA_BLOB logonHours
;
1099 uint32_t badPwdCount
;
1100 uint32_t logonCount
;
1101 DATA_BLOB unicodePwd
;
1105 uint32_t acct_flags
;
1106 uint32_t units_per_week
;
1108 memset(zero_buf
, '\0', sizeof(zero_buf
));
1110 objectSid
= cur
->object
.identifier
->sid
;
1111 GET_STRING_EX(sAMAccountName
, true);
1112 DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1113 sAMAccountName
, sid_string_dbg(&objectSid
)));
1114 GET_UINT64(lastLogon
);
1115 GET_UINT64(lastLogoff
);
1116 GET_UINT64(pwdLastSet
);
1117 GET_UINT64(accountExpires
);
1118 GET_STRING(displayName
);
1119 GET_STRING(homeDirectory
);
1120 GET_STRING(homeDrive
);
1121 GET_STRING(scriptPath
);
1122 GET_STRING(profilePath
);
1123 GET_STRING(description
);
1124 GET_STRING(userWorkstations
);
1125 GET_STRING(comment
);
1126 GET_BLOB(userParameters
);
1127 GET_UINT32(primaryGroupID
);
1128 GET_UINT32(userAccountControl
);
1129 GET_BLOB(logonHours
);
1130 GET_UINT32(badPwdCount
);
1131 GET_UINT32(logonCount
);
1132 GET_BLOB(unicodePwd
);
1135 status
= dom_sid_split_rid(mem_ctx
, &objectSid
, NULL
, &rid
);
1136 if (!NT_STATUS_IS_OK(status
)) {
1139 acct_flags
= ds_uf2acb(userAccountControl
);
1141 /* Username, fullname, home dir, dir drive, logon script, acct
1142 desc, workstations, profile. */
1144 if (sAMAccountName
) {
1145 old_string
= pdb_get_nt_username(account
);
1146 new_string
= sAMAccountName
;
1148 if (STRING_CHANGED
) {
1149 pdb_set_nt_username(account
, new_string
, PDB_CHANGED
);
1152 /* Unix username is the same - for sanity */
1153 old_string
= pdb_get_username( account
);
1154 if (STRING_CHANGED
) {
1155 pdb_set_username(account
, new_string
, PDB_CHANGED
);
1160 old_string
= pdb_get_fullname(account
);
1161 new_string
= displayName
;
1164 pdb_set_fullname(account
, new_string
, PDB_CHANGED
);
1167 if (homeDirectory
) {
1168 old_string
= pdb_get_homedir(account
);
1169 new_string
= homeDirectory
;
1172 pdb_set_homedir(account
, new_string
, PDB_CHANGED
);
1176 old_string
= pdb_get_dir_drive(account
);
1177 new_string
= homeDrive
;
1180 pdb_set_dir_drive(account
, new_string
, PDB_CHANGED
);
1184 old_string
= pdb_get_logon_script(account
);
1185 new_string
= scriptPath
;
1188 pdb_set_logon_script(account
, new_string
, PDB_CHANGED
);
1192 old_string
= pdb_get_acct_desc(account
);
1193 new_string
= description
;
1196 pdb_set_acct_desc(account
, new_string
, PDB_CHANGED
);
1199 if (userWorkstations
) {
1200 old_string
= pdb_get_workstations(account
);
1201 new_string
= userWorkstations
;
1204 pdb_set_workstations(account
, new_string
, PDB_CHANGED
);
1208 old_string
= pdb_get_profile_path(account
);
1209 new_string
= profilePath
;
1212 pdb_set_profile_path(account
, new_string
, PDB_CHANGED
);
1215 if (userParameters
.data
) {
1217 old_string
= pdb_get_munged_dial(account
);
1218 newstr
= (userParameters
.length
== 0) ? NULL
:
1219 base64_encode_data_blob(talloc_tos(), userParameters
);
1221 if (STRING_CHANGED_NC(old_string
, newstr
))
1222 pdb_set_munged_dial(account
, newstr
, PDB_CHANGED
);
1223 TALLOC_FREE(newstr
);
1226 /* User and group sid */
1227 if (rid
!= 0 && pdb_get_user_rid(account
) != rid
) {
1228 pdb_set_user_sid_from_rid(account
, rid
, PDB_CHANGED
);
1230 if (primaryGroupID
!= 0 && pdb_get_group_rid(account
) != primaryGroupID
) {
1231 pdb_set_group_sid_from_rid(account
, primaryGroupID
, PDB_CHANGED
);
1234 /* Logon and password information */
1235 if (!nt_time_is_zero(&lastLogon
)) {
1236 unix_time
= nt_time_to_unix(lastLogon
);
1237 stored_time
= pdb_get_logon_time(account
);
1238 if (stored_time
!= unix_time
)
1239 pdb_set_logon_time(account
, unix_time
, PDB_CHANGED
);
1242 if (!nt_time_is_zero(&lastLogoff
)) {
1243 unix_time
= nt_time_to_unix(lastLogoff
);
1244 stored_time
= pdb_get_logoff_time(account
);
1245 if (stored_time
!= unix_time
)
1246 pdb_set_logoff_time(account
, unix_time
,PDB_CHANGED
);
1250 units_per_week
= logonHours
.length
* 8;
1252 if (pdb_get_logon_divs(account
) != units_per_week
) {
1253 pdb_set_logon_divs(account
, units_per_week
, PDB_CHANGED
);
1256 /* Logon Hours Len */
1257 if (units_per_week
/8 != pdb_get_hours_len(account
)) {
1258 pdb_set_hours_len(account
, units_per_week
/8, PDB_CHANGED
);
1262 if (logonHours
.data
) {
1263 char oldstr
[44], newstr
[44];
1264 pdb_sethexhours(oldstr
, pdb_get_hours(account
));
1265 pdb_sethexhours(newstr
, logonHours
.data
);
1266 if (!strequal(oldstr
, newstr
)) {
1267 pdb_set_hours(account
, logonHours
.data
,
1268 logonHours
.length
, PDB_CHANGED
);
1272 if (pdb_get_bad_password_count(account
) != badPwdCount
)
1273 pdb_set_bad_password_count(account
, badPwdCount
, PDB_CHANGED
);
1275 if (pdb_get_logon_count(account
) != logonCount
)
1276 pdb_set_logon_count(account
, logonCount
, PDB_CHANGED
);
1278 if (!nt_time_is_zero(&pwdLastSet
)) {
1279 unix_time
= nt_time_to_unix(pwdLastSet
);
1280 stored_time
= pdb_get_pass_last_set_time(account
);
1281 if (stored_time
!= unix_time
)
1282 pdb_set_pass_last_set_time(account
, unix_time
, PDB_CHANGED
);
1284 /* no last set time, make it now */
1285 pdb_set_pass_last_set_time(account
, time(NULL
), PDB_CHANGED
);
1288 if (!nt_time_is_zero(&accountExpires
)) {
1289 unix_time
= nt_time_to_unix(accountExpires
);
1290 stored_time
= pdb_get_kickoff_time(account
);
1291 if (stored_time
!= unix_time
)
1292 pdb_set_kickoff_time(account
, unix_time
, PDB_CHANGED
);
1295 /* Decode hashes from password hash
1296 Note that win2000 may send us all zeros for the hashes if it doesn't
1297 think this channel is secure enough - don't set the passwords at all
1300 if (dBCSPwd
.length
== 16 && memcmp(dBCSPwd
.data
, zero_buf
, 16) != 0) {
1301 pdb_set_lanman_passwd(account
, dBCSPwd
.data
, PDB_CHANGED
);
1304 if (unicodePwd
.length
== 16 && memcmp(unicodePwd
.data
, zero_buf
, 16) != 0) {
1305 pdb_set_nt_passwd(account
, unicodePwd
.data
, PDB_CHANGED
);
1310 /* TODO: account expiry time */
1312 pdb_set_acct_ctrl(account
, acct_flags
, PDB_CHANGED
);
1314 pdb_set_domain(account
, lp_workgroup(), PDB_CHANGED
);
1316 DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1317 sAMAccountName
, sid_string_dbg(&objectSid
)));
1318 return NT_STATUS_OK
;
1321 /****************************************************************
1322 ****************************************************************/
1324 static NTSTATUS
handle_account_object(struct dssync_passdb
*pctx
,
1325 TALLOC_CTX
*mem_ctx
,
1326 struct dssync_passdb_obj
*obj
)
1328 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1331 struct samu
*sam_account
=NULL
;
1334 struct dom_sid user_sid
;
1335 struct dom_sid group_sid
;
1336 struct passwd
*passwd
= NULL
;
1337 uint32_t acct_flags
;
1340 const char *sAMAccountName
;
1341 uint32_t sAMAccountType
;
1342 uint32_t userAccountControl
;
1344 user_sid
= cur
->object
.identifier
->sid
;
1345 GET_STRING_EX(sAMAccountName
, true);
1346 GET_UINT32_EX(sAMAccountType
, true);
1347 GET_UINT32_EX(userAccountControl
, true);
1349 status
= dom_sid_split_rid(mem_ctx
, &user_sid
, NULL
, &rid
);
1350 if (!NT_STATUS_IS_OK(status
)) {
1354 fstrcpy(account
, sAMAccountName
);
1355 if (rid
== DOMAIN_RID_GUEST
) {
1357 * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1358 * that's why we need to ignore it here.
1360 * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1363 DEBUG(0,("Ignore %s - %s\n", account
, sid_string_dbg(&user_sid
)));
1364 return NT_STATUS_OK
;
1366 DEBUG(0,("Creating account: %s\n", account
));
1368 if ( !(sam_account
= samu_new(mem_ctx
)) ) {
1369 return NT_STATUS_NO_MEMORY
;
1372 acct_flags
= ds_uf2acb(userAccountControl
);
1373 status
= smb_create_user(sam_account
, acct_flags
, account
, &passwd
);
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1376 account
, nt_errstr(status
)));
1377 TALLOC_FREE(sam_account
);
1381 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1382 sid_string_dbg(&user_sid
), account
));
1383 if (!pdb_getsampwsid(sam_account
, &user_sid
)) {
1384 sam_account_from_object(sam_account
, cur
);
1385 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
1386 sid_string_dbg(&user_sid
),
1387 pdb_get_username(sam_account
)));
1388 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account
))) {
1389 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1391 TALLOC_FREE(sam_account
);
1392 return NT_STATUS_ACCESS_DENIED
;
1395 sam_account_from_object(sam_account
, cur
);
1396 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
1397 sid_string_dbg(&user_sid
),
1398 pdb_get_username(sam_account
)));
1399 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account
))) {
1400 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1402 TALLOC_FREE(sam_account
);
1403 return NT_STATUS_ACCESS_DENIED
;
1407 if (pdb_get_group_sid(sam_account
) == NULL
) {
1408 TALLOC_FREE(sam_account
);
1409 return NT_STATUS_UNSUCCESSFUL
;
1412 group_sid
= *pdb_get_group_sid(sam_account
);
1414 if (!pdb_getgrsid(&map
, group_sid
)) {
1415 DEBUG(0, ("Primary group of %s has no mapping!\n",
1416 pdb_get_username(sam_account
)));
1418 if (map
.gid
!= passwd
->pw_gid
) {
1419 if (!(grp
= getgrgid(map
.gid
))) {
1420 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
1421 (unsigned long)map
.gid
, pdb_get_username(sam_account
),
1422 sid_string_dbg(&group_sid
)));
1424 smb_set_primary_group(grp
->gr_name
, pdb_get_username(sam_account
));
1430 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1431 pdb_get_username(sam_account
)));
1434 TALLOC_FREE(sam_account
);
1435 return NT_STATUS_OK
;
1438 /****************************************************************
1439 ****************************************************************/
1441 static NTSTATUS
handle_alias_object(struct dssync_passdb
*pctx
,
1442 TALLOC_CTX
*mem_ctx
,
1443 struct dssync_passdb_obj
*obj
)
1445 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1449 struct group
*grp
= NULL
;
1450 struct dom_sid group_sid
;
1452 struct dom_sid
*dom_sid
= NULL
;
1457 const char *sAMAccountName
;
1458 uint32_t sAMAccountType
;
1460 const char *description
;
1462 uint32_t num_members
= 0;
1463 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1465 group_sid
= cur
->object
.identifier
->sid
;
1466 GET_STRING_EX(sAMAccountName
, true);
1467 GET_UINT32_EX(sAMAccountType
, true);
1468 GET_UINT32_EX(groupType
, true);
1469 GET_STRING(description
);
1471 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1472 &num_members
, &members
);
1473 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1474 status
= NT_STATUS_OK
;
1476 if (!NT_STATUS_IS_OK(status
)) {
1480 fstrcpy(name
, sAMAccountName
);
1481 fstrcpy(comment
, description
);
1483 dom_sid_split_rid(mem_ctx
, &group_sid
, &dom_sid
, &rid
);
1485 sid_to_fstring(sid_string
, &group_sid
);
1486 DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1487 name
, sid_string
, num_members
));
1489 status
= dssync_insert_obj(pctx
, pctx
->aliases
, obj
);
1490 if (!NT_STATUS_IS_OK(status
)) {
1494 if (pdb_getgrsid(&map
, group_sid
)) {
1495 if ( map
.gid
!= -1 )
1496 grp
= getgrgid(map
.gid
);
1503 /* No group found from mapping, find it from its name. */
1504 if ((grp
= getgrnam(name
)) == NULL
) {
1506 /* No appropriate group found, create one */
1508 DEBUG(0,("Creating unix group: '%s'\n", name
));
1510 if (smb_create_group(name
, &gid
) != 0)
1511 return NT_STATUS_ACCESS_DENIED
;
1513 if ((grp
= getgrgid(gid
)) == NULL
)
1514 return NT_STATUS_ACCESS_DENIED
;
1518 map
.gid
= grp
->gr_gid
;
1519 map
.sid
= group_sid
;
1521 if (dom_sid_equal(dom_sid
, &global_sid_Builtin
)) {
1523 * pdb_ldap does not like SID_NAME_WKN_GRP...
1525 * map.sid_name_use = SID_NAME_WKN_GRP;
1527 map
.sid_name_use
= SID_NAME_ALIAS
;
1529 map
.sid_name_use
= SID_NAME_ALIAS
;
1532 fstrcpy(map
.nt_name
, name
);
1534 fstrcpy(map
.comment
, comment
);
1536 fstrcpy(map
.comment
, "");
1540 pdb_add_group_mapping_entry(&map
);
1542 pdb_update_group_mapping_entry(&map
);
1544 for (i
=0; i
< num_members
; i
++) {
1545 struct dssync_passdb_mem
*mem
;
1547 status
= dssync_create_mem(pctx
, obj
,
1550 if (!NT_STATUS_IS_OK(status
)) {
1555 return NT_STATUS_OK
;
1558 /****************************************************************
1559 ****************************************************************/
1561 static NTSTATUS
handle_group_object(struct dssync_passdb
*pctx
,
1562 TALLOC_CTX
*mem_ctx
,
1563 struct dssync_passdb_obj
*obj
)
1565 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1569 struct group
*grp
= NULL
;
1570 struct dom_sid group_sid
;
1575 const char *sAMAccountName
;
1576 uint32_t sAMAccountType
;
1578 const char *description
;
1580 uint32_t num_members
= 0;
1581 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1583 group_sid
= cur
->object
.identifier
->sid
;
1584 GET_STRING_EX(sAMAccountName
, true);
1585 GET_UINT32_EX(sAMAccountType
, true);
1586 GET_UINT32_EX(groupType
, true);
1587 GET_STRING(description
);
1589 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1590 &num_members
, &members
);
1591 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1592 status
= NT_STATUS_OK
;
1594 if (!NT_STATUS_IS_OK(status
)) {
1598 fstrcpy(name
, sAMAccountName
);
1599 fstrcpy(comment
, description
);
1601 sid_to_fstring(sid_string
, &group_sid
);
1602 DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1603 name
, sid_string
, num_members
));
1605 status
= dssync_insert_obj(pctx
, pctx
->groups
, obj
);
1606 if (!NT_STATUS_IS_OK(status
)) {
1610 if (pdb_getgrsid(&map
, group_sid
)) {
1611 if ( map
.gid
!= -1 )
1612 grp
= getgrgid(map
.gid
);
1619 /* No group found from mapping, find it from its name. */
1620 if ((grp
= getgrnam(name
)) == NULL
) {
1622 /* No appropriate group found, create one */
1624 DEBUG(0,("Creating unix group: '%s'\n", name
));
1626 if (smb_create_group(name
, &gid
) != 0)
1627 return NT_STATUS_ACCESS_DENIED
;
1629 if ((grp
= getgrnam(name
)) == NULL
)
1630 return NT_STATUS_ACCESS_DENIED
;
1634 map
.gid
= grp
->gr_gid
;
1635 map
.sid
= group_sid
;
1636 map
.sid_name_use
= SID_NAME_DOM_GRP
;
1637 fstrcpy(map
.nt_name
, name
);
1639 fstrcpy(map
.comment
, comment
);
1641 fstrcpy(map
.comment
, "");
1645 pdb_add_group_mapping_entry(&map
);
1647 pdb_update_group_mapping_entry(&map
);
1649 for (i
=0; i
< num_members
; i
++) {
1650 struct dssync_passdb_mem
*mem
;
1652 status
= dssync_create_mem(pctx
, obj
,
1655 if (!NT_STATUS_IS_OK(status
)) {
1660 return NT_STATUS_OK
;
1663 /****************************************************************
1664 ****************************************************************/
1666 static NTSTATUS
handle_interdomain_trust_object(struct dssync_passdb
*pctx
,
1667 TALLOC_CTX
*mem_ctx
,
1668 struct dssync_passdb_obj
*obj
)
1670 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1671 DEBUG(0,("trust: %s\n", cur
->object
.identifier
->dn
));
1672 return NT_STATUS_NOT_IMPLEMENTED
;
1675 /****************************************************************
1676 ****************************************************************/
1678 struct dssync_object_table_t
{
1680 NTSTATUS (*fn
) (struct dssync_passdb
*pctx
,
1681 TALLOC_CTX
*mem_ctx
,
1682 struct dssync_passdb_obj
*obj
);
1685 static const struct dssync_object_table_t dssync_object_table
[] = {
1686 { ATYPE_NORMAL_ACCOUNT
, handle_account_object
},
1687 { ATYPE_WORKSTATION_TRUST
, handle_account_object
},
1688 { ATYPE_SECURITY_LOCAL_GROUP
, handle_alias_object
},
1689 { ATYPE_SECURITY_GLOBAL_GROUP
, handle_group_object
},
1690 { ATYPE_INTERDOMAIN_TRUST
, handle_interdomain_trust_object
},
1693 /****************************************************************
1694 ****************************************************************/
1696 static NTSTATUS
parse_object(struct dssync_passdb
*pctx
,
1697 TALLOC_CTX
*mem_ctx
,
1698 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1700 NTSTATUS status
= NT_STATUS_OK
;
1704 struct drsuapi_DsReplicaAttribute
*attr
;
1708 uint32_t sam_type
= 0;
1710 DEBUG(3, ("parsing object '%s'\n", cur
->object
.identifier
->dn
));
1712 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
1714 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
1716 if (attr
->value_ctr
.num_values
!= 1) {
1720 if (!attr
->value_ctr
.values
[0].blob
) {
1724 blob
= attr
->value_ctr
.values
[0].blob
;
1726 switch (attr
->attid
) {
1727 case DRSUAPI_ATTID_sAMAccountName
:
1728 pull_string_talloc(mem_ctx
, NULL
, 0, &name
,
1729 blob
->data
, blob
->length
,
1732 case DRSUAPI_ATTID_sAMAccountType
:
1733 sam_type
= IVAL(blob
->data
, 0);
1735 case DRSUAPI_ATTID_userAccountControl
:
1736 uacc
= IVAL(blob
->data
, 0);
1743 for (a
=0; a
< ARRAY_SIZE(dssync_object_table
); a
++) {
1744 if (sam_type
== dssync_object_table
[a
].type
) {
1745 if (dssync_object_table
[a
].fn
) {
1746 struct dssync_passdb_obj
*obj
;
1747 status
= dssync_create_obj(pctx
, pctx
->all
,
1748 sam_type
, cur
, &obj
);
1749 if (!NT_STATUS_IS_OK(status
)) {
1752 status
= dssync_object_table
[a
].fn(pctx
,
1763 static NTSTATUS
parse_link(struct dssync_passdb
*pctx
,
1764 TALLOC_CTX
*mem_ctx
,
1765 struct drsuapi_DsReplicaLinkedAttribute
*cur
)
1767 struct drsuapi_DsReplicaObjectIdentifier3
*id3
;
1768 const DATA_BLOB
*blob
;
1769 enum ndr_err_code ndr_err
;
1771 bool active
= false;
1772 struct dssync_passdb_mem
*mem
;
1773 struct dssync_passdb_obj
*obj
;
1775 if (cur
->attid
!= DRSUAPI_ATTID_member
) {
1776 return NT_STATUS_OK
;
1779 if (cur
->flags
& DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
) {
1783 DEBUG(3, ("parsing link '%s' - %s\n",
1784 cur
->identifier
->dn
, active
?"adding":"deleting"));
1786 blob
= cur
->value
.blob
;
1789 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1792 obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &cur
->identifier
->guid
);
1794 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1797 id3
= talloc_zero(obj
, struct drsuapi_DsReplicaObjectIdentifier3
);
1799 return NT_STATUS_NO_MEMORY
;
1802 /* windows sometimes sends an extra two pad bytes here */
1803 ndr_err
= ndr_pull_struct_blob(blob
, id3
, id3
,
1804 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
1805 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1806 status
= ndr_map_error2ntstatus(ndr_err
);
1810 status
= dssync_create_mem(pctx
, obj
,
1813 if (!NT_STATUS_IS_OK(status
)) {
1817 return NT_STATUS_OK
;
1820 /****************************************************************
1821 ****************************************************************/
1823 static NTSTATUS
passdb_process_objects(struct dssync_context
*ctx
,
1824 TALLOC_CTX
*mem_ctx
,
1825 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
1826 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1828 NTSTATUS status
= NT_STATUS_OK
;
1829 struct dssync_passdb
*pctx
=
1830 talloc_get_type_abort(ctx
->private_data
,
1831 struct dssync_passdb
);
1833 for (; cur
; cur
= cur
->next_object
) {
1834 status
= parse_object(pctx
, mem_ctx
, cur
);
1835 if (!NT_STATUS_IS_OK(status
)) {
1844 /****************************************************************
1845 ****************************************************************/
1847 static NTSTATUS
passdb_process_links(struct dssync_context
*ctx
,
1848 TALLOC_CTX
*mem_ctx
,
1850 struct drsuapi_DsReplicaLinkedAttribute
*links
,
1851 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1853 NTSTATUS status
= NT_STATUS_OK
;
1854 struct dssync_passdb
*pctx
=
1855 talloc_get_type_abort(ctx
->private_data
,
1856 struct dssync_passdb
);
1859 for (i
= 0; i
< count
; i
++) {
1860 status
= parse_link(pctx
, mem_ctx
, &links
[i
]);
1861 if (!NT_STATUS_IS_OK(status
)) {
1870 /****************************************************************
1871 ****************************************************************/
1873 const struct dssync_ops libnet_dssync_passdb_ops
= {
1874 .startup
= passdb_startup
,
1875 .process_objects
= passdb_process_objects
,
1876 .process_links
= passdb_process_links
,
1877 .finish
= passdb_finish
,