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 "dbwrap/dbwrap_rbt.h"
29 #include "../libds/common/flag_mapping.h"
32 /****************************************************************
33 ****************************************************************/
35 struct dssync_passdb
{
36 struct pdb_methods
*methods
;
37 struct db_context
*all
;
38 struct db_context
*aliases
;
39 struct db_context
*groups
;
42 struct dssync_passdb_obj
{
43 struct dssync_passdb_obj
*self
;
45 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
48 struct db_context
*members
;
51 struct dssync_passdb_mem
{
52 struct dssync_passdb_mem
*self
;
54 struct drsuapi_DsReplicaObjectIdentifier3
*cur
;
55 struct dssync_passdb_obj
*obj
;
60 static NTSTATUS
dssync_insert_obj(struct dssync_passdb
*pctx
,
61 struct db_context
*db
,
62 struct dssync_passdb_obj
*obj
)
65 struct db_record
*rec
;
68 rec
= dbwrap_fetch_locked(db
, talloc_tos(), obj
->key
);
70 return NT_STATUS_NO_MEMORY
;
73 value
= dbwrap_record_get_value(rec
);
74 if (value
.dsize
!= 0) {
78 status
= dbwrap_record_store(rec
, obj
->data
, TDB_INSERT
);
79 if (!NT_STATUS_IS_OK(status
)) {
87 static struct dssync_passdb_obj
*dssync_parse_obj(const TDB_DATA data
)
89 struct dssync_passdb_obj
*obj
;
91 if (data
.dsize
!= sizeof(obj
)) {
96 * we need to copy the pointer to avoid alignment problems
99 memcpy(&obj
, data
.dptr
, sizeof(obj
));
101 return talloc_get_type_abort(obj
, struct dssync_passdb_obj
);
104 static struct dssync_passdb_obj
*dssync_search_obj_by_guid(struct dssync_passdb
*pctx
,
105 struct db_context
*db
,
106 const struct GUID
*guid
)
108 struct dssync_passdb_obj
*obj
;
113 key
= make_tdb_data((const uint8_t *)(const void *)guid
,
116 status
= dbwrap_fetch(db
, talloc_tos(), key
, &data
);
117 if (!NT_STATUS_IS_OK(status
)) {
121 obj
= dssync_parse_obj(data
);
125 static NTSTATUS
dssync_create_obj(struct dssync_passdb
*pctx
,
126 struct db_context
*db
,
128 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
129 struct dssync_passdb_obj
**_obj
)
132 struct dssync_passdb_obj
*obj
;
134 obj
= talloc_zero(pctx
, struct dssync_passdb_obj
);
136 return NT_STATUS_NO_MEMORY
;
141 obj
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->object
.identifier
->guid
,
142 sizeof(cur
->object
.identifier
->guid
));
143 obj
->data
= make_tdb_data((const uint8_t *)(void *)&obj
->self
,
146 obj
->members
= db_open_rbt(obj
);
147 if (obj
->members
== NULL
) {
148 return NT_STATUS_NO_MEMORY
;
151 status
= dssync_insert_obj(pctx
, db
, obj
);
152 if (!NT_STATUS_IS_OK(status
)) {
160 static NTSTATUS
dssync_insert_mem(struct dssync_passdb
*pctx
,
161 struct dssync_passdb_obj
*obj
,
162 struct dssync_passdb_mem
*mem
)
165 struct db_record
*rec
;
168 rec
= dbwrap_fetch_locked(obj
->members
, talloc_tos(), mem
->key
);
170 return NT_STATUS_NO_MEMORY
;
173 value
= dbwrap_record_get_value(rec
);
174 if (value
.dsize
!= 0) {
178 status
= dbwrap_record_store(rec
, mem
->data
, TDB_INSERT
);
179 if (!NT_STATUS_IS_OK(status
)) {
187 static NTSTATUS
dssync_create_mem(struct dssync_passdb
*pctx
,
188 struct dssync_passdb_obj
*obj
,
190 struct drsuapi_DsReplicaObjectIdentifier3
*cur
,
191 struct dssync_passdb_mem
**_mem
)
194 struct dssync_passdb_mem
*mem
;
196 mem
= talloc_zero(pctx
, struct dssync_passdb_mem
);
198 return NT_STATUS_NO_MEMORY
;
202 mem
->active
= active
;
204 mem
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->guid
,
206 mem
->data
= make_tdb_data((const uint8_t *)(void *)&mem
->self
,
209 status
= dssync_insert_mem(pctx
, obj
, mem
);
210 if (!NT_STATUS_IS_OK(status
)) {
218 static struct dssync_passdb_mem
*dssync_parse_mem(const TDB_DATA data
)
220 struct dssync_passdb_mem
*mem
;
222 if (data
.dsize
!= sizeof(mem
)) {
227 * we need to copy the pointer to avoid alignment problems
230 memcpy(&mem
, data
.dptr
, sizeof(mem
));
232 return talloc_get_type_abort(mem
, struct dssync_passdb_mem
);
235 static NTSTATUS
passdb_startup(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
236 struct replUpToDateVectorBlob
**pold_utdv
)
239 struct dssync_passdb
*pctx
;
241 pctx
= talloc_zero(mem_ctx
, struct dssync_passdb
);
243 return NT_STATUS_NO_MEMORY
;
246 if (ctx
->output_filename
) {
247 status
= make_pdb_method_name(&pctx
->methods
, ctx
->output_filename
);
249 status
= make_pdb_method_name(&pctx
->methods
, lp_passdb_backend());
252 if (!NT_STATUS_IS_OK(status
)) {
256 pctx
->all
= db_open_rbt(pctx
);
257 if (pctx
->all
== NULL
) {
258 return NT_STATUS_NO_MEMORY
;
260 pctx
->aliases
= db_open_rbt(pctx
);
261 if (pctx
->aliases
== NULL
) {
262 return NT_STATUS_NO_MEMORY
;
264 pctx
->groups
= db_open_rbt(pctx
);
265 if (pctx
->groups
== NULL
) {
266 return NT_STATUS_NO_MEMORY
;
269 ctx
->private_data
= pctx
;
274 /****************************************************************
275 ****************************************************************/
277 struct dssync_passdb_traverse_amembers
{
278 struct dssync_context
*ctx
;
279 struct dssync_passdb_obj
*obj
;
284 struct dssync_passdb_traverse_aliases
{
285 struct dssync_context
*ctx
;
290 static int dssync_passdb_traverse_amembers(struct db_record
*rec
,
293 struct dssync_passdb_traverse_amembers
*state
=
294 (struct dssync_passdb_traverse_amembers
*)private_data
;
295 struct dssync_passdb
*pctx
=
296 talloc_get_type_abort(state
->ctx
->private_data
,
297 struct dssync_passdb
);
298 struct dssync_passdb_mem
*mem
;
300 struct dom_sid alias_sid
;
301 struct dom_sid member_sid
;
302 const char *member_dn
;
305 struct dom_sid
*members
;
306 bool is_member
= false;
312 alias_sid
= state
->obj
->cur
->object
.identifier
->sid
;
314 value
= dbwrap_record_get_value(rec
);
315 mem
= dssync_parse_mem(value
);
320 member_sid
= mem
->cur
->sid
;
321 member_dn
= mem
->cur
->dn
;
323 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
324 if (mem
->obj
== NULL
) {
325 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
326 sid_string_dbg(&alias_sid
),
327 is_null_sid(&member_sid
)?
328 sid_string_dbg(&member_sid
):
333 switch (mem
->obj
->type
) {
334 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
335 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
336 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
337 sid_string_dbg(&alias_sid
),
344 DEBUG(0,("alias[%s] member[%s]\n",
345 sid_string_dbg(&alias_sid
),
346 sid_string_dbg(&member_sid
)));
348 status
= pdb_enum_aliasmem(&alias_sid
, talloc_tos(),
349 &members
, &num_members
);
350 if (!NT_STATUS_IS_OK(status
)) {
351 DEBUG(0, ("Could not find current alias members %s - %s\n",
352 sid_string_dbg(&alias_sid
),
357 for (i
=0; i
< num_members
; i
++) {
360 match
= dom_sid_equal(&members
[i
], &member_sid
);
367 status
= NT_STATUS_OK
;
369 if (!is_member
&& mem
->active
) {
371 pdb_add_aliasmem(&alias_sid
, &member_sid
);
372 } else if (is_member
&& !mem
->active
) {
374 pdb_del_aliasmem(&alias_sid
, &member_sid
);
376 if (!NT_STATUS_IS_OK(status
)) {
377 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
379 sid_string_dbg(&member_sid
),
380 sid_string_dbg(&alias_sid
),
388 static int dssync_passdb_traverse_aliases(struct db_record
*rec
,
391 struct dssync_passdb_traverse_aliases
*state
=
392 (struct dssync_passdb_traverse_aliases
*)private_data
;
393 struct dssync_passdb
*pctx
=
394 talloc_get_type_abort(state
->ctx
->private_data
,
395 struct dssync_passdb
);
396 struct dssync_passdb_traverse_amembers mstate
;
397 struct dssync_passdb_obj
*obj
;
402 if (pctx
->methods
== NULL
) {
406 value
= dbwrap_record_get_value(rec
);
407 obj
= dssync_parse_obj(value
);
413 mstate
.ctx
= state
->ctx
;
414 mstate
.name
= "members";
416 status
= dbwrap_traverse_read(obj
->members
,
417 dssync_passdb_traverse_amembers
,
419 if (!NT_STATUS_IS_OK(status
)) {
426 struct dssync_passdb_traverse_gmembers
{
427 struct dssync_context
*ctx
;
428 struct dssync_passdb_obj
*obj
;
433 struct dssync_passdb_traverse_groups
{
434 struct dssync_context
*ctx
;
439 static int dssync_passdb_traverse_gmembers(struct db_record
*rec
,
442 struct dssync_passdb_traverse_gmembers
*state
=
443 (struct dssync_passdb_traverse_gmembers
*)private_data
;
444 struct dssync_passdb
*pctx
=
445 talloc_get_type_abort(state
->ctx
->private_data
,
446 struct dssync_passdb
);
447 struct dssync_passdb_mem
*mem
;
449 char *nt_member
= NULL
;
451 struct dom_sid group_sid
;
452 struct dom_sid member_sid
;
453 struct samu
*member
= NULL
;
454 const char *member_dn
= NULL
;
458 bool is_unix_member
= false;
463 group_sid
= state
->obj
->cur
->object
.identifier
->sid
;
465 status
= dom_sid_split_rid(talloc_tos(), &group_sid
, NULL
, &rid
);
466 if (!NT_STATUS_IS_OK(status
)) {
470 value
= dbwrap_record_get_value(rec
);
472 mem
= dssync_parse_mem(value
);
477 member_sid
= mem
->cur
->sid
;
478 member_dn
= mem
->cur
->dn
;
480 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
481 if (mem
->obj
== NULL
) {
482 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
483 sid_string_dbg(&group_sid
),
484 is_null_sid(&member_sid
)?
485 sid_string_dbg(&member_sid
):
490 member_sid
= mem
->obj
->cur
->object
.identifier
->sid
;
491 member_dn
= mem
->obj
->cur
->object
.identifier
->dn
;
493 switch (mem
->obj
->type
) {
494 case ATYPE_SECURITY_LOCAL_GROUP
:
495 case ATYPE_SECURITY_GLOBAL_GROUP
:
496 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
497 sid_string_dbg(&group_sid
),
498 sid_string_dbg(&member_sid
)));
501 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
502 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
503 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
504 sid_string_dbg(&group_sid
),
511 map
= talloc_zero(NULL
, GROUP_MAP
);
516 if (!get_domain_group_from_sid(group_sid
, map
)) {
517 DEBUG(0, ("Could not find global group %s\n",
518 sid_string_dbg(&group_sid
)));
519 //return NT_STATUS_NO_SUCH_GROUP;
524 if (!(grp
= getgrgid(map
->gid
))) {
525 DEBUG(0, ("Could not find unix group %lu\n",
526 (unsigned long)map
->gid
));
527 //return NT_STATUS_NO_SUCH_GROUP;
534 DEBUG(0,("Group members of %s: ", grp
->gr_name
));
536 if ( !(member
= samu_new(talloc_tos())) ) {
537 //return NT_STATUS_NO_MEMORY;
541 if (!pdb_getsampwsid(member
, &member_sid
)) {
542 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
543 sid_string_tos(&member_sid
), grp
->gr_name
));
548 if (pdb_get_group_rid(member
) == rid
) {
549 DEBUGADD(0,("%s(primary),", pdb_get_username(member
)));
554 DEBUGADD(0,("%s,", pdb_get_username(member
)));
555 nt_member
= talloc_strdup(talloc_tos(), pdb_get_username(member
));
560 unix_members
= grp
->gr_mem
;
562 while (*unix_members
) {
563 if (strcmp(*unix_members
, nt_member
) == 0) {
564 is_unix_member
= true;
570 if (!is_unix_member
&& mem
->active
) {
571 smb_add_user_group(grp
->gr_name
, nt_member
);
572 } else if (is_unix_member
&& !mem
->active
) {
573 smb_delete_user_group(grp
->gr_name
, nt_member
);
579 static int dssync_passdb_traverse_groups(struct db_record
*rec
,
582 struct dssync_passdb_traverse_groups
*state
=
583 (struct dssync_passdb_traverse_groups
*)private_data
;
584 struct dssync_passdb
*pctx
=
585 talloc_get_type_abort(state
->ctx
->private_data
,
586 struct dssync_passdb
);
587 struct dssync_passdb_traverse_gmembers mstate
;
588 struct dssync_passdb_obj
*obj
;
593 if (pctx
->methods
== NULL
) {
597 value
= dbwrap_record_get_value(rec
);
599 obj
= dssync_parse_obj(value
);
605 mstate
.ctx
= state
->ctx
;
606 mstate
.name
= "members";
608 status
= dbwrap_traverse_read(obj
->members
,
609 dssync_passdb_traverse_gmembers
,
611 if (!NT_STATUS_IS_OK(status
)) {
618 static NTSTATUS
passdb_finish(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
619 struct replUpToDateVectorBlob
*new_utdv
)
621 struct dssync_passdb
*pctx
=
622 talloc_get_type_abort(ctx
->private_data
,
623 struct dssync_passdb
);
624 struct dssync_passdb_traverse_aliases astate
;
625 struct dssync_passdb_traverse_groups gstate
;
630 astate
.name
= "aliases";
631 status
= dbwrap_traverse_read(pctx
->aliases
,
632 dssync_passdb_traverse_aliases
,
634 if (!NT_STATUS_IS_OK(status
)) {
635 return NT_STATUS_INTERNAL_ERROR
;
640 gstate
.name
= "groups";
641 status
= dbwrap_traverse_read(pctx
->groups
,
642 dssync_passdb_traverse_groups
,
644 if (!NT_STATUS_IS_OK(status
)) {
645 return NT_STATUS_INTERNAL_ERROR
;
648 TALLOC_FREE(pctx
->methods
);
654 /****************************************************************
655 ****************************************************************/
657 static NTSTATUS
smb_create_user(TALLOC_CTX
*mem_ctx
,
660 struct passwd
**passwd_p
)
662 struct passwd
*passwd
;
663 char *add_script
= NULL
;
665 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
671 /* Create appropriate user */
672 if (acct_flags
& ACB_NORMAL
) {
673 add_script
= lp_add_user_script(mem_ctx
);
674 } else if ( (acct_flags
& ACB_WSTRUST
) ||
675 (acct_flags
& ACB_SVRTRUST
) ||
676 (acct_flags
& ACB_DOMTRUST
) ) {
677 add_script
= lp_add_machine_script(mem_ctx
);
679 DEBUG(1, ("Unknown user type: %s\n",
680 pdb_encode_acct_ctrl(acct_flags
, NEW_PW_FORMAT_SPACE_PADDED_LEN
)));
681 return NT_STATUS_UNSUCCESSFUL
;
685 return NT_STATUS_NO_MEMORY
;
690 add_script
= talloc_all_string_sub(mem_ctx
, add_script
,
693 return NT_STATUS_NO_MEMORY
;
695 add_ret
= smbrun(add_script
, NULL
);
696 DEBUG(add_ret
? 0 : 1,("fetch_account: Running the command `%s' "
697 "gave %d\n", add_script
, add_ret
));
699 smb_nscd_flush_user_cache();
703 /* try and find the possible unix account again */
704 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
706 return NT_STATUS_NO_SUCH_USER
;
714 static struct drsuapi_DsReplicaAttribute
*find_drsuapi_attr(
715 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
720 for (i
= 0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
721 struct drsuapi_DsReplicaAttribute
*attr
;
723 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
725 if (attr
->attid
== attid
) {
733 static NTSTATUS
find_drsuapi_attr_string(TALLOC_CTX
*mem_ctx
,
734 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
739 struct drsuapi_DsReplicaAttribute
*attr
;
743 attr
= find_drsuapi_attr(cur
, attid
);
745 return NT_STATUS_PROPSET_NOT_FOUND
;
748 array
= talloc_array(mem_ctx
, char *, attr
->value_ctr
.num_values
);
750 return NT_STATUS_NO_MEMORY
;
753 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
754 const DATA_BLOB
*blob
;
757 blob
= attr
->value_ctr
.values
[a
].blob
;
760 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
763 ret
= pull_string_talloc(array
, NULL
, 0, &array
[a
],
764 blob
->data
, blob
->length
,
768 return NT_STATUS_INTERNAL_ERROR
;
772 *_count
= attr
->value_ctr
.num_values
;
777 static NTSTATUS
find_drsuapi_attr_int32(TALLOC_CTX
*mem_ctx
,
778 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
783 struct drsuapi_DsReplicaAttribute
*attr
;
787 attr
= find_drsuapi_attr(cur
, attid
);
789 return NT_STATUS_PROPSET_NOT_FOUND
;
792 array
= talloc_array(mem_ctx
, int32_t, attr
->value_ctr
.num_values
);
794 return NT_STATUS_NO_MEMORY
;
797 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
798 const DATA_BLOB
*blob
;
800 blob
= attr
->value_ctr
.values
[a
].blob
;
803 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
806 if (blob
->length
!= 4) {
807 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
810 array
[a
] = IVAL(blob
->data
, 0);
813 *_count
= attr
->value_ctr
.num_values
;
818 static NTSTATUS
find_drsuapi_attr_blob(TALLOC_CTX
*mem_ctx
,
819 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
824 struct drsuapi_DsReplicaAttribute
*attr
;
828 attr
= find_drsuapi_attr(cur
, attid
);
830 return NT_STATUS_PROPSET_NOT_FOUND
;
833 array
= talloc_array(mem_ctx
, DATA_BLOB
, attr
->value_ctr
.num_values
);
835 return NT_STATUS_NO_MEMORY
;
838 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
839 const DATA_BLOB
*blob
;
841 blob
= attr
->value_ctr
.values
[a
].blob
;
844 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
847 array
[a
] = data_blob_talloc(array
, blob
->data
, blob
->length
);
848 if (array
[a
].length
!= blob
->length
) {
849 return NT_STATUS_NO_MEMORY
;
852 *_count
= attr
->value_ctr
.num_values
;
857 static NTSTATUS
find_drsuapi_attr_int64(TALLOC_CTX
*mem_ctx
,
858 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
863 struct drsuapi_DsReplicaAttribute
*attr
;
867 attr
= find_drsuapi_attr(cur
, attid
);
869 return NT_STATUS_PROPSET_NOT_FOUND
;
872 array
= talloc_array(mem_ctx
, int64_t, attr
->value_ctr
.num_values
);
874 return NT_STATUS_NO_MEMORY
;
877 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
878 const DATA_BLOB
*blob
;
880 blob
= attr
->value_ctr
.values
[a
].blob
;
883 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
886 if (blob
->length
!= 8) {
887 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
890 array
[a
] = BVAL(blob
->data
, 0);
892 *_count
= attr
->value_ctr
.num_values
;
897 static NTSTATUS
find_drsuapi_attr_dn(TALLOC_CTX
*mem_ctx
,
898 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
901 struct drsuapi_DsReplicaObjectIdentifier3
**_array
)
903 struct drsuapi_DsReplicaAttribute
*attr
;
904 struct drsuapi_DsReplicaObjectIdentifier3
*array
;
907 attr
= find_drsuapi_attr(cur
, attid
);
909 return NT_STATUS_PROPSET_NOT_FOUND
;
912 array
= talloc_array(mem_ctx
,
913 struct drsuapi_DsReplicaObjectIdentifier3
,
914 attr
->value_ctr
.num_values
);
916 return NT_STATUS_NO_MEMORY
;
919 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
920 const DATA_BLOB
*blob
;
921 enum ndr_err_code ndr_err
;
924 blob
= attr
->value_ctr
.values
[a
].blob
;
927 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
930 /* windows sometimes sends an extra two pad bytes here */
931 ndr_err
= ndr_pull_struct_blob(blob
, array
, &array
[a
],
932 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
933 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
934 status
= ndr_map_error2ntstatus(ndr_err
);
938 *_count
= attr
->value_ctr
.num_values
;
943 #define GET_BLOB_EX(attr, needed) do { \
946 DATA_BLOB *_vals = NULL; \
947 attr = data_blob_null; \
948 _status = find_drsuapi_attr_blob(mem_ctx, cur, \
949 DRSUAPI_ATTID_ ## attr, \
951 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
953 _status = NT_STATUS_OK; \
957 if (!NT_STATUS_IS_OK(_status)) { \
958 DEBUG(0,(__location__ "attr[%s] %s\n", \
959 #attr, nt_errstr(_status))); \
964 talloc_free(_vals); \
965 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
966 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
968 } else if (_cnt > 1) { \
969 talloc_free(_vals); \
970 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
971 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
974 (void)talloc_steal(mem_ctx, _vals[0].data); \
976 talloc_free(_vals); \
979 #define GET_STRING_EX(attr, needed) do { \
982 char **_vals = NULL; \
984 _status = find_drsuapi_attr_string(mem_ctx, cur, \
985 DRSUAPI_ATTID_ ## attr, \
987 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
989 _status = NT_STATUS_OK; \
993 if (!NT_STATUS_IS_OK(_status)) { \
994 DEBUG(0,(__location__ "attr[%s] %s\n", \
995 #attr, nt_errstr(_status))); \
1000 talloc_free(_vals); \
1001 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1002 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1004 } else if (_cnt > 1) { \
1005 talloc_free(_vals); \
1006 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1007 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1009 attr = talloc_move(mem_ctx, &_vals[0]); \
1011 talloc_free(_vals); \
1014 #define GET_UINT32_EX(attr, needed) do { \
1017 int32_t*_vals = NULL; \
1019 _status = find_drsuapi_attr_int32(mem_ctx, cur, \
1020 DRSUAPI_ATTID_ ## attr, \
1022 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1024 _status = NT_STATUS_OK; \
1028 if (!NT_STATUS_IS_OK(_status)) { \
1029 DEBUG(0,(__location__ "attr[%s] %s\n", \
1030 #attr, nt_errstr(_status))); \
1035 talloc_free(_vals); \
1036 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1037 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1039 } else if (_cnt > 1) { \
1040 talloc_free(_vals); \
1041 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1042 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1044 attr = (uint32_t)_vals[0]; \
1046 talloc_free(_vals); \
1049 #define GET_UINT64_EX(attr, needed) do { \
1052 int64_t *_vals = NULL; \
1054 _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1055 DRSUAPI_ATTID_ ## attr, \
1057 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1059 _status = NT_STATUS_OK; \
1063 if (!NT_STATUS_IS_OK(_status)) { \
1064 DEBUG(0,(__location__ "attr[%s] %s\n", \
1065 #attr, nt_errstr(_status))); \
1070 talloc_free(_vals); \
1071 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1072 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1074 } else if (_cnt > 1) { \
1075 talloc_free(_vals); \
1076 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1077 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1079 attr = (uint64_t)_vals[0]; \
1081 talloc_free(_vals); \
1084 #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
1085 #define GET_STRING(attr) GET_STRING_EX(attr, false)
1086 #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
1087 #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
1089 /* Convert a struct samu_DELTA to a struct samu. */
1090 #define STRING_CHANGED (old_string && !new_string) ||\
1091 (!old_string && new_string) ||\
1092 (old_string && new_string && (strcmp(old_string, new_string) != 0))
1094 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1096 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1098 /****************************************************************
1099 ****************************************************************/
1101 static NTSTATUS
sam_account_from_object(struct samu
*account
,
1102 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1104 TALLOC_CTX
*mem_ctx
= account
;
1105 const char *old_string
, *new_string
;
1106 time_t unix_time
, stored_time
;
1113 NTTIME accountExpires
;
1114 const char *sAMAccountName
;
1115 const char *displayName
;
1116 const char *homeDirectory
;
1117 const char *homeDrive
;
1118 const char *scriptPath
;
1119 const char *profilePath
;
1120 const char *description
;
1121 const char *userWorkstations
;
1122 DATA_BLOB userParameters
;
1123 struct dom_sid objectSid
;
1124 uint32_t primaryGroupID
;
1125 uint32_t userAccountControl
;
1126 DATA_BLOB logonHours
;
1127 uint32_t badPwdCount
;
1128 uint32_t logonCount
;
1129 DATA_BLOB unicodePwd
;
1133 uint32_t acct_flags
;
1134 uint32_t units_per_week
;
1136 memset(zero_buf
, '\0', sizeof(zero_buf
));
1138 objectSid
= cur
->object
.identifier
->sid
;
1139 GET_STRING_EX(sAMAccountName
, true);
1140 DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1141 sAMAccountName
, sid_string_dbg(&objectSid
)));
1142 GET_UINT64(lastLogon
);
1143 GET_UINT64(lastLogoff
);
1144 GET_UINT64(pwdLastSet
);
1145 GET_UINT64(accountExpires
);
1146 GET_STRING(displayName
);
1147 GET_STRING(homeDirectory
);
1148 GET_STRING(homeDrive
);
1149 GET_STRING(scriptPath
);
1150 GET_STRING(profilePath
);
1151 GET_STRING(description
);
1152 GET_STRING(userWorkstations
);
1153 GET_BLOB(userParameters
);
1154 GET_UINT32(primaryGroupID
);
1155 GET_UINT32(userAccountControl
);
1156 GET_BLOB(logonHours
);
1157 GET_UINT32(badPwdCount
);
1158 GET_UINT32(logonCount
);
1159 GET_BLOB(unicodePwd
);
1162 status
= dom_sid_split_rid(mem_ctx
, &objectSid
, NULL
, &rid
);
1163 if (!NT_STATUS_IS_OK(status
)) {
1166 acct_flags
= ds_uf2acb(userAccountControl
);
1168 /* Username, fullname, home dir, dir drive, logon script, acct
1169 desc, workstations, profile. */
1171 if (sAMAccountName
) {
1172 old_string
= pdb_get_nt_username(account
);
1173 new_string
= sAMAccountName
;
1175 if (STRING_CHANGED
) {
1176 pdb_set_nt_username(account
, new_string
, PDB_CHANGED
);
1179 /* Unix username is the same - for sanity */
1180 old_string
= pdb_get_username( account
);
1181 if (STRING_CHANGED
) {
1182 pdb_set_username(account
, new_string
, PDB_CHANGED
);
1187 old_string
= pdb_get_fullname(account
);
1188 new_string
= displayName
;
1191 pdb_set_fullname(account
, new_string
, PDB_CHANGED
);
1194 if (homeDirectory
) {
1195 old_string
= pdb_get_homedir(account
);
1196 new_string
= homeDirectory
;
1199 pdb_set_homedir(account
, new_string
, PDB_CHANGED
);
1203 old_string
= pdb_get_dir_drive(account
);
1204 new_string
= homeDrive
;
1207 pdb_set_dir_drive(account
, new_string
, PDB_CHANGED
);
1211 old_string
= pdb_get_logon_script(account
);
1212 new_string
= scriptPath
;
1215 pdb_set_logon_script(account
, new_string
, PDB_CHANGED
);
1219 old_string
= pdb_get_acct_desc(account
);
1220 new_string
= description
;
1223 pdb_set_acct_desc(account
, new_string
, PDB_CHANGED
);
1226 if (userWorkstations
) {
1227 old_string
= pdb_get_workstations(account
);
1228 new_string
= userWorkstations
;
1231 pdb_set_workstations(account
, new_string
, PDB_CHANGED
);
1235 old_string
= pdb_get_profile_path(account
);
1236 new_string
= profilePath
;
1239 pdb_set_profile_path(account
, new_string
, PDB_CHANGED
);
1242 if (userParameters
.data
) {
1244 old_string
= pdb_get_munged_dial(account
);
1245 newstr
= (userParameters
.length
== 0) ? NULL
:
1246 base64_encode_data_blob(talloc_tos(), userParameters
);
1248 if (STRING_CHANGED_NC(old_string
, newstr
))
1249 pdb_set_munged_dial(account
, newstr
, PDB_CHANGED
);
1250 TALLOC_FREE(newstr
);
1253 /* User and group sid */
1254 if (rid
!= 0 && pdb_get_user_rid(account
) != rid
) {
1255 pdb_set_user_sid_from_rid(account
, rid
, PDB_CHANGED
);
1257 if (primaryGroupID
!= 0 && pdb_get_group_rid(account
) != primaryGroupID
) {
1258 pdb_set_group_sid_from_rid(account
, primaryGroupID
, PDB_CHANGED
);
1261 /* Logon and password information */
1262 if (!nt_time_is_zero(&lastLogon
)) {
1263 unix_time
= nt_time_to_unix(lastLogon
);
1264 stored_time
= pdb_get_logon_time(account
);
1265 if (stored_time
!= unix_time
)
1266 pdb_set_logon_time(account
, unix_time
, PDB_CHANGED
);
1269 if (!nt_time_is_zero(&lastLogoff
)) {
1270 unix_time
= nt_time_to_unix(lastLogoff
);
1271 stored_time
= pdb_get_logoff_time(account
);
1272 if (stored_time
!= unix_time
)
1273 pdb_set_logoff_time(account
, unix_time
,PDB_CHANGED
);
1277 units_per_week
= logonHours
.length
* 8;
1279 if (pdb_get_logon_divs(account
) != units_per_week
) {
1280 pdb_set_logon_divs(account
, units_per_week
, PDB_CHANGED
);
1283 /* Logon Hours Len */
1284 if (units_per_week
/8 != pdb_get_hours_len(account
)) {
1285 pdb_set_hours_len(account
, units_per_week
/8, PDB_CHANGED
);
1289 if (logonHours
.data
) {
1290 char oldstr
[44], newstr
[44];
1291 pdb_sethexhours(oldstr
, pdb_get_hours(account
));
1292 pdb_sethexhours(newstr
, logonHours
.data
);
1293 if (!strequal(oldstr
, newstr
)) {
1294 pdb_set_hours(account
, logonHours
.data
,
1295 logonHours
.length
, PDB_CHANGED
);
1299 if (pdb_get_bad_password_count(account
) != badPwdCount
)
1300 pdb_set_bad_password_count(account
, badPwdCount
, PDB_CHANGED
);
1302 if (pdb_get_logon_count(account
) != logonCount
)
1303 pdb_set_logon_count(account
, logonCount
, PDB_CHANGED
);
1305 if (!nt_time_is_zero(&pwdLastSet
)) {
1306 unix_time
= nt_time_to_unix(pwdLastSet
);
1307 stored_time
= pdb_get_pass_last_set_time(account
);
1308 if (stored_time
!= unix_time
)
1309 pdb_set_pass_last_set_time(account
, unix_time
, PDB_CHANGED
);
1311 /* no last set time, make it now */
1312 pdb_set_pass_last_set_time(account
, time(NULL
), PDB_CHANGED
);
1315 if (!nt_time_is_zero(&accountExpires
)) {
1316 unix_time
= nt_time_to_unix(accountExpires
);
1317 stored_time
= pdb_get_kickoff_time(account
);
1318 if (stored_time
!= unix_time
)
1319 pdb_set_kickoff_time(account
, unix_time
, PDB_CHANGED
);
1322 /* Decode hashes from password hash
1323 Note that win2000 may send us all zeros for the hashes if it doesn't
1324 think this channel is secure enough - don't set the passwords at all
1327 if (dBCSPwd
.length
== 16 && memcmp(dBCSPwd
.data
, zero_buf
, 16) != 0) {
1328 pdb_set_lanman_passwd(account
, dBCSPwd
.data
, PDB_CHANGED
);
1331 if (unicodePwd
.length
== 16 && memcmp(unicodePwd
.data
, zero_buf
, 16) != 0) {
1332 pdb_set_nt_passwd(account
, unicodePwd
.data
, PDB_CHANGED
);
1337 /* TODO: account expiry time */
1339 pdb_set_acct_ctrl(account
, acct_flags
, PDB_CHANGED
);
1341 pdb_set_domain(account
, lp_workgroup(), PDB_CHANGED
);
1343 DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1344 sAMAccountName
, sid_string_dbg(&objectSid
)));
1345 return NT_STATUS_OK
;
1348 /****************************************************************
1349 ****************************************************************/
1351 static NTSTATUS
handle_account_object(struct dssync_passdb
*pctx
,
1352 TALLOC_CTX
*mem_ctx
,
1353 struct dssync_passdb_obj
*obj
)
1355 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1358 struct samu
*sam_account
=NULL
;
1361 struct dom_sid user_sid
;
1362 struct dom_sid group_sid
;
1363 struct passwd
*passwd
= NULL
;
1364 uint32_t acct_flags
;
1367 const char *sAMAccountName
;
1368 uint32_t userAccountControl
;
1370 user_sid
= cur
->object
.identifier
->sid
;
1371 GET_STRING_EX(sAMAccountName
, true);
1372 GET_UINT32_EX(userAccountControl
, true);
1374 status
= dom_sid_split_rid(mem_ctx
, &user_sid
, NULL
, &rid
);
1375 if (!NT_STATUS_IS_OK(status
)) {
1379 fstrcpy(account
, sAMAccountName
);
1380 if (rid
== DOMAIN_RID_GUEST
) {
1382 * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1383 * that's why we need to ignore it here.
1385 * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1388 DEBUG(0,("Ignore %s - %s\n", account
, sid_string_dbg(&user_sid
)));
1389 return NT_STATUS_OK
;
1391 DEBUG(0,("Creating account: %s\n", account
));
1393 if ( !(sam_account
= samu_new(mem_ctx
)) ) {
1394 return NT_STATUS_NO_MEMORY
;
1397 acct_flags
= ds_uf2acb(userAccountControl
);
1398 status
= smb_create_user(sam_account
, acct_flags
, account
, &passwd
);
1399 if (!NT_STATUS_IS_OK(status
)) {
1400 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1401 account
, nt_errstr(status
)));
1402 TALLOC_FREE(sam_account
);
1406 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1407 sid_string_dbg(&user_sid
), account
));
1408 if (!pdb_getsampwsid(sam_account
, &user_sid
)) {
1409 sam_account_from_object(sam_account
, cur
);
1410 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
1411 sid_string_dbg(&user_sid
),
1412 pdb_get_username(sam_account
)));
1413 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account
))) {
1414 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1416 TALLOC_FREE(sam_account
);
1417 return NT_STATUS_ACCESS_DENIED
;
1420 sam_account_from_object(sam_account
, cur
);
1421 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
1422 sid_string_dbg(&user_sid
),
1423 pdb_get_username(sam_account
)));
1424 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account
))) {
1425 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1427 TALLOC_FREE(sam_account
);
1428 return NT_STATUS_ACCESS_DENIED
;
1432 if (pdb_get_group_sid(sam_account
) == NULL
) {
1433 TALLOC_FREE(sam_account
);
1434 return NT_STATUS_UNSUCCESSFUL
;
1437 group_sid
= *pdb_get_group_sid(sam_account
);
1439 map
= talloc_zero(NULL
, GROUP_MAP
);
1441 return NT_STATUS_NO_MEMORY
;
1444 if (!pdb_getgrsid(map
, group_sid
)) {
1445 DEBUG(0, ("Primary group of %s has no mapping!\n",
1446 pdb_get_username(sam_account
)));
1448 if (map
->gid
!= passwd
->pw_gid
) {
1449 if (!(grp
= getgrgid(map
->gid
))) {
1450 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
1451 (unsigned long)map
->gid
, pdb_get_username(sam_account
),
1452 sid_string_dbg(&group_sid
)));
1454 smb_set_primary_group(grp
->gr_name
, pdb_get_username(sam_account
));
1462 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1463 pdb_get_username(sam_account
)));
1466 TALLOC_FREE(sam_account
);
1467 return NT_STATUS_OK
;
1470 /****************************************************************
1471 ****************************************************************/
1473 static NTSTATUS
handle_alias_object(struct dssync_passdb
*pctx
,
1474 TALLOC_CTX
*mem_ctx
,
1475 struct dssync_passdb_obj
*obj
)
1477 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1479 struct group
*grp
= NULL
;
1480 struct dom_sid group_sid
;
1482 struct dom_sid
*dom_sid
= NULL
;
1487 const char *sAMAccountName
;
1488 const char *description
;
1490 uint32_t num_members
= 0;
1491 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1493 group_sid
= cur
->object
.identifier
->sid
;
1494 GET_STRING_EX(sAMAccountName
, true);
1495 GET_STRING(description
);
1497 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1498 &num_members
, &members
);
1499 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1500 status
= NT_STATUS_OK
;
1502 if (!NT_STATUS_IS_OK(status
)) {
1506 dom_sid_split_rid(mem_ctx
, &group_sid
, &dom_sid
, &rid
);
1508 map
= talloc_zero(mem_ctx
, GROUP_MAP
);
1510 status
= NT_STATUS_NO_MEMORY
;
1514 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1515 if (map
->nt_name
== NULL
) {
1516 status
= NT_STATUS_NO_MEMORY
;
1521 map
->comment
= talloc_strdup(map
, description
);
1523 map
->comment
= talloc_strdup(map
, "");
1525 if (map
->comment
== NULL
) {
1526 status
= NT_STATUS_NO_MEMORY
;
1530 sid_to_fstring(sid_string
, &group_sid
);
1531 DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1532 map
->nt_name
, sid_string
, num_members
));
1534 status
= dssync_insert_obj(pctx
, pctx
->aliases
, obj
);
1535 if (!NT_STATUS_IS_OK(status
)) {
1539 if (pdb_getgrsid(map
, group_sid
)) {
1540 if (map
->gid
!= -1) {
1541 grp
= getgrgid(map
->gid
);
1549 /* No group found from mapping, find it from its name. */
1550 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1552 /* No appropriate group found, create one */
1554 DEBUG(0, ("Creating unix group: '%s'\n",
1557 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1558 status
= NT_STATUS_ACCESS_DENIED
;
1562 if ((grp
= getgrgid(gid
)) == NULL
) {
1563 status
= NT_STATUS_ACCESS_DENIED
;
1569 map
->gid
= grp
->gr_gid
;
1570 map
->sid
= group_sid
;
1572 if (dom_sid_equal(dom_sid
, &global_sid_Builtin
)) {
1574 * pdb_ldap does not like SID_NAME_WKN_GRP...
1576 * map.sid_name_use = SID_NAME_WKN_GRP;
1578 map
->sid_name_use
= SID_NAME_ALIAS
;
1580 map
->sid_name_use
= SID_NAME_ALIAS
;
1584 pdb_add_group_mapping_entry(map
);
1586 pdb_update_group_mapping_entry(map
);
1589 for (i
=0; i
< num_members
; i
++) {
1590 struct dssync_passdb_mem
*mem
;
1592 status
= dssync_create_mem(pctx
, obj
,
1595 if (!NT_STATUS_IS_OK(status
)) {
1600 status
= NT_STATUS_OK
;
1607 /****************************************************************
1608 ****************************************************************/
1610 static NTSTATUS
handle_group_object(struct dssync_passdb
*pctx
,
1611 TALLOC_CTX
*mem_ctx
,
1612 struct dssync_passdb_obj
*obj
)
1614 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1616 struct group
*grp
= NULL
;
1617 struct dom_sid group_sid
;
1622 const char *sAMAccountName
;
1623 const char *description
;
1625 uint32_t num_members
= 0;
1626 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1628 group_sid
= cur
->object
.identifier
->sid
;
1629 GET_STRING_EX(sAMAccountName
, true);
1630 GET_STRING(description
);
1632 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1633 &num_members
, &members
);
1634 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1635 status
= NT_STATUS_OK
;
1637 if (!NT_STATUS_IS_OK(status
)) {
1641 map
= talloc_zero(NULL
, GROUP_MAP
);
1643 return NT_STATUS_NO_MEMORY
;
1646 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1647 if (!map
->nt_name
) {
1648 status
= NT_STATUS_NO_MEMORY
;
1652 map
->comment
= talloc_strdup(map
, description
);
1654 map
->comment
= talloc_strdup(map
, "");
1656 if (!map
->comment
) {
1657 status
= NT_STATUS_NO_MEMORY
;
1661 sid_to_fstring(sid_string
, &group_sid
);
1662 DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1663 map
->nt_name
, sid_string
, num_members
));
1665 status
= dssync_insert_obj(pctx
, pctx
->groups
, obj
);
1666 if (!NT_STATUS_IS_OK(status
)) {
1670 if (pdb_getgrsid(map
, group_sid
)) {
1671 if (map
->gid
!= -1) {
1672 grp
= getgrgid(map
->gid
);
1680 /* No group found from mapping, find it from its name. */
1681 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1683 /* No appropriate group found, create one */
1685 DEBUG(0, ("Creating unix group: '%s'\n",
1688 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1689 status
= NT_STATUS_ACCESS_DENIED
;
1693 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1694 status
= NT_STATUS_ACCESS_DENIED
;
1700 map
->gid
= grp
->gr_gid
;
1701 map
->sid
= group_sid
;
1702 map
->sid_name_use
= SID_NAME_DOM_GRP
;
1705 pdb_add_group_mapping_entry(map
);
1707 pdb_update_group_mapping_entry(map
);
1710 for (i
=0; i
< num_members
; i
++) {
1711 struct dssync_passdb_mem
*mem
;
1713 status
= dssync_create_mem(pctx
, obj
,
1716 if (!NT_STATUS_IS_OK(status
)) {
1721 status
= NT_STATUS_OK
;
1728 /****************************************************************
1729 ****************************************************************/
1731 static NTSTATUS
handle_interdomain_trust_object(struct dssync_passdb
*pctx
,
1732 TALLOC_CTX
*mem_ctx
,
1733 struct dssync_passdb_obj
*obj
)
1735 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1736 DEBUG(0,("trust: %s\n", cur
->object
.identifier
->dn
));
1737 return NT_STATUS_NOT_IMPLEMENTED
;
1740 /****************************************************************
1741 ****************************************************************/
1743 struct dssync_object_table_t
{
1745 NTSTATUS (*fn
) (struct dssync_passdb
*pctx
,
1746 TALLOC_CTX
*mem_ctx
,
1747 struct dssync_passdb_obj
*obj
);
1750 static const struct dssync_object_table_t dssync_object_table
[] = {
1751 { ATYPE_NORMAL_ACCOUNT
, handle_account_object
},
1752 { ATYPE_WORKSTATION_TRUST
, handle_account_object
},
1753 { ATYPE_SECURITY_LOCAL_GROUP
, handle_alias_object
},
1754 { ATYPE_SECURITY_GLOBAL_GROUP
, handle_group_object
},
1755 { ATYPE_INTERDOMAIN_TRUST
, handle_interdomain_trust_object
},
1758 /****************************************************************
1759 ****************************************************************/
1761 static NTSTATUS
parse_object(struct dssync_passdb
*pctx
,
1762 TALLOC_CTX
*mem_ctx
,
1763 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1765 NTSTATUS status
= NT_STATUS_OK
;
1769 struct drsuapi_DsReplicaAttribute
*attr
;
1772 uint32_t sam_type
= 0;
1774 DEBUG(3, ("parsing object '%s'\n", cur
->object
.identifier
->dn
));
1776 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
1778 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
1780 if (attr
->value_ctr
.num_values
!= 1) {
1784 if (!attr
->value_ctr
.values
[0].blob
) {
1788 blob
= attr
->value_ctr
.values
[0].blob
;
1790 switch (attr
->attid
) {
1791 case DRSUAPI_ATTID_sAMAccountName
:
1792 pull_string_talloc(mem_ctx
, NULL
, 0, &name
,
1793 blob
->data
, blob
->length
,
1796 case DRSUAPI_ATTID_sAMAccountType
:
1797 sam_type
= IVAL(blob
->data
, 0);
1804 for (a
=0; a
< ARRAY_SIZE(dssync_object_table
); a
++) {
1805 if (sam_type
== dssync_object_table
[a
].type
) {
1806 if (dssync_object_table
[a
].fn
) {
1807 struct dssync_passdb_obj
*obj
;
1808 status
= dssync_create_obj(pctx
, pctx
->all
,
1809 sam_type
, cur
, &obj
);
1810 if (!NT_STATUS_IS_OK(status
)) {
1813 status
= dssync_object_table
[a
].fn(pctx
,
1824 static NTSTATUS
parse_link(struct dssync_passdb
*pctx
,
1825 TALLOC_CTX
*mem_ctx
,
1826 struct drsuapi_DsReplicaLinkedAttribute
*cur
)
1828 struct drsuapi_DsReplicaObjectIdentifier3
*id3
;
1829 const DATA_BLOB
*blob
;
1830 enum ndr_err_code ndr_err
;
1832 bool active
= false;
1833 struct dssync_passdb_mem
*mem
;
1834 struct dssync_passdb_obj
*obj
;
1836 if (cur
->attid
!= DRSUAPI_ATTID_member
) {
1837 return NT_STATUS_OK
;
1840 if (cur
->flags
& DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
) {
1844 DEBUG(3, ("parsing link '%s' - %s\n",
1845 cur
->identifier
->dn
, active
?"adding":"deleting"));
1847 blob
= cur
->value
.blob
;
1850 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1853 obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &cur
->identifier
->guid
);
1855 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1858 id3
= talloc_zero(obj
, struct drsuapi_DsReplicaObjectIdentifier3
);
1860 return NT_STATUS_NO_MEMORY
;
1863 /* windows sometimes sends an extra two pad bytes here */
1864 ndr_err
= ndr_pull_struct_blob(blob
, id3
, id3
,
1865 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
1866 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1867 status
= ndr_map_error2ntstatus(ndr_err
);
1871 status
= dssync_create_mem(pctx
, obj
,
1874 if (!NT_STATUS_IS_OK(status
)) {
1878 return NT_STATUS_OK
;
1881 /****************************************************************
1882 ****************************************************************/
1884 static NTSTATUS
passdb_process_objects(struct dssync_context
*ctx
,
1885 TALLOC_CTX
*mem_ctx
,
1886 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
1887 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1889 NTSTATUS status
= NT_STATUS_OK
;
1890 struct dssync_passdb
*pctx
=
1891 talloc_get_type_abort(ctx
->private_data
,
1892 struct dssync_passdb
);
1894 for (; cur
; cur
= cur
->next_object
) {
1895 status
= parse_object(pctx
, mem_ctx
, cur
);
1896 if (!NT_STATUS_IS_OK(status
)) {
1905 /****************************************************************
1906 ****************************************************************/
1908 static NTSTATUS
passdb_process_links(struct dssync_context
*ctx
,
1909 TALLOC_CTX
*mem_ctx
,
1911 struct drsuapi_DsReplicaLinkedAttribute
*links
,
1912 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1914 NTSTATUS status
= NT_STATUS_OK
;
1915 struct dssync_passdb
*pctx
=
1916 talloc_get_type_abort(ctx
->private_data
,
1917 struct dssync_passdb
);
1920 for (i
= 0; i
< count
; i
++) {
1921 status
= parse_link(pctx
, mem_ctx
, &links
[i
]);
1922 if (!NT_STATUS_IS_OK(status
)) {
1931 /****************************************************************
1932 ****************************************************************/
1934 const struct dssync_ops libnet_dssync_passdb_ops
= {
1935 .startup
= passdb_startup
,
1936 .process_objects
= passdb_process_objects
,
1937 .process_links
= passdb_process_links
,
1938 .finish
= passdb_finish
,