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"
31 #include "lib/util/base64.h"
32 #include "lib/util/string_wrappers.h"
34 /****************************************************************
35 ****************************************************************/
37 struct dssync_passdb
{
38 struct pdb_methods
*methods
;
39 struct db_context
*all
;
40 struct db_context
*aliases
;
41 struct db_context
*groups
;
44 struct dssync_passdb_obj
{
45 struct dssync_passdb_obj
*self
;
47 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
50 struct db_context
*members
;
53 struct dssync_passdb_mem
{
54 struct dssync_passdb_mem
*self
;
56 struct drsuapi_DsReplicaObjectIdentifier3
*cur
;
57 struct dssync_passdb_obj
*obj
;
62 static NTSTATUS
dssync_insert_obj(struct dssync_passdb
*pctx
,
63 struct db_context
*db
,
64 struct dssync_passdb_obj
*obj
)
67 struct db_record
*rec
;
70 rec
= dbwrap_fetch_locked(db
, talloc_tos(), obj
->key
);
72 return NT_STATUS_NO_MEMORY
;
75 value
= dbwrap_record_get_value(rec
);
76 if (value
.dsize
!= 0) {
80 status
= dbwrap_record_store(rec
, obj
->data
, TDB_INSERT
);
81 if (!NT_STATUS_IS_OK(status
)) {
89 static struct dssync_passdb_obj
*dssync_parse_obj(const TDB_DATA data
)
91 struct dssync_passdb_obj
*obj
;
93 if (data
.dsize
!= sizeof(obj
)) {
98 * we need to copy the pointer to avoid alignment problems
101 memcpy(&obj
, data
.dptr
, sizeof(obj
));
103 return talloc_get_type_abort(obj
, struct dssync_passdb_obj
);
106 static struct dssync_passdb_obj
*dssync_search_obj_by_guid(struct dssync_passdb
*pctx
,
107 struct db_context
*db
,
108 const struct GUID
*guid
)
110 struct dssync_passdb_obj
*obj
;
115 key
= make_tdb_data((const uint8_t *)(const void *)guid
,
118 status
= dbwrap_fetch(db
, talloc_tos(), key
, &data
);
119 if (!NT_STATUS_IS_OK(status
)) {
123 obj
= dssync_parse_obj(data
);
127 static NTSTATUS
dssync_create_obj(struct dssync_passdb
*pctx
,
128 struct db_context
*db
,
130 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
131 struct dssync_passdb_obj
**_obj
)
134 struct dssync_passdb_obj
*obj
;
136 obj
= talloc_zero(pctx
, struct dssync_passdb_obj
);
138 return NT_STATUS_NO_MEMORY
;
143 obj
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->object
.identifier
->guid
,
144 sizeof(cur
->object
.identifier
->guid
));
145 obj
->data
= make_tdb_data((const uint8_t *)(void *)&obj
->self
,
148 obj
->members
= db_open_rbt(obj
);
149 if (obj
->members
== NULL
) {
150 return NT_STATUS_NO_MEMORY
;
153 status
= dssync_insert_obj(pctx
, db
, obj
);
154 if (!NT_STATUS_IS_OK(status
)) {
162 static NTSTATUS
dssync_insert_mem(struct dssync_passdb
*pctx
,
163 struct dssync_passdb_obj
*obj
,
164 struct dssync_passdb_mem
*mem
)
167 struct db_record
*rec
;
170 rec
= dbwrap_fetch_locked(obj
->members
, talloc_tos(), mem
->key
);
172 return NT_STATUS_NO_MEMORY
;
175 value
= dbwrap_record_get_value(rec
);
176 if (value
.dsize
!= 0) {
180 status
= dbwrap_record_store(rec
, mem
->data
, TDB_INSERT
);
181 if (!NT_STATUS_IS_OK(status
)) {
189 static NTSTATUS
dssync_create_mem(struct dssync_passdb
*pctx
,
190 struct dssync_passdb_obj
*obj
,
192 struct drsuapi_DsReplicaObjectIdentifier3
*cur
,
193 struct dssync_passdb_mem
**_mem
)
196 struct dssync_passdb_mem
*mem
;
198 mem
= talloc_zero(pctx
, struct dssync_passdb_mem
);
200 return NT_STATUS_NO_MEMORY
;
204 mem
->active
= active
;
206 mem
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->guid
,
208 mem
->data
= make_tdb_data((const uint8_t *)(void *)&mem
->self
,
211 status
= dssync_insert_mem(pctx
, obj
, mem
);
212 if (!NT_STATUS_IS_OK(status
)) {
220 static struct dssync_passdb_mem
*dssync_parse_mem(const TDB_DATA data
)
222 struct dssync_passdb_mem
*mem
;
224 if (data
.dsize
!= sizeof(mem
)) {
229 * we need to copy the pointer to avoid alignment problems
232 memcpy(&mem
, data
.dptr
, sizeof(mem
));
234 return talloc_get_type_abort(mem
, struct dssync_passdb_mem
);
237 static NTSTATUS
passdb_startup(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
238 struct replUpToDateVectorBlob
**pold_utdv
)
241 struct dssync_passdb
*pctx
;
243 pctx
= talloc_zero(mem_ctx
, struct dssync_passdb
);
245 return NT_STATUS_NO_MEMORY
;
248 if (ctx
->output_filename
) {
249 status
= make_pdb_method_name(&pctx
->methods
, ctx
->output_filename
);
251 status
= make_pdb_method_name(&pctx
->methods
, lp_passdb_backend());
254 if (!NT_STATUS_IS_OK(status
)) {
258 pctx
->all
= db_open_rbt(pctx
);
259 if (pctx
->all
== NULL
) {
260 return NT_STATUS_NO_MEMORY
;
262 pctx
->aliases
= db_open_rbt(pctx
);
263 if (pctx
->aliases
== NULL
) {
264 return NT_STATUS_NO_MEMORY
;
266 pctx
->groups
= db_open_rbt(pctx
);
267 if (pctx
->groups
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
271 ctx
->private_data
= pctx
;
276 /****************************************************************
277 ****************************************************************/
279 struct dssync_passdb_traverse_amembers
{
280 struct dssync_context
*ctx
;
281 struct dssync_passdb_obj
*obj
;
286 struct dssync_passdb_traverse_aliases
{
287 struct dssync_context
*ctx
;
292 static int dssync_passdb_traverse_amembers(struct db_record
*rec
,
295 struct dssync_passdb_traverse_amembers
*state
=
296 (struct dssync_passdb_traverse_amembers
*)private_data
;
297 struct dssync_passdb
*pctx
=
298 talloc_get_type_abort(state
->ctx
->private_data
,
299 struct dssync_passdb
);
300 struct dssync_passdb_mem
*mem
;
302 struct dom_sid alias_sid
;
303 struct dom_sid member_sid
;
304 struct dom_sid_buf buf1
, buf2
;
305 const char *member_dn
;
308 struct dom_sid
*members
;
309 bool is_member
= false;
315 alias_sid
= state
->obj
->cur
->object
.identifier
->sid
;
317 value
= dbwrap_record_get_value(rec
);
318 mem
= dssync_parse_mem(value
);
323 member_sid
= mem
->cur
->sid
;
324 member_dn
= mem
->cur
->dn
;
326 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
327 if (mem
->obj
== NULL
) {
328 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
329 dom_sid_str_buf(&alias_sid
, &buf1
),
330 is_null_sid(&member_sid
)?
331 dom_sid_str_buf(&member_sid
, &buf2
):
336 switch (mem
->obj
->type
) {
337 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
338 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
339 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
340 dom_sid_str_buf(&alias_sid
, &buf1
),
347 DEBUG(0,("alias[%s] member[%s]\n",
348 dom_sid_str_buf(&alias_sid
, &buf1
),
349 dom_sid_str_buf(&member_sid
, &buf2
)));
351 status
= pdb_enum_aliasmem(&alias_sid
, talloc_tos(),
352 &members
, &num_members
);
353 if (!NT_STATUS_IS_OK(status
)) {
354 DEBUG(0, ("Could not find current alias members %s - %s\n",
355 dom_sid_str_buf(&alias_sid
, &buf1
),
360 for (i
=0; i
< num_members
; i
++) {
363 match
= dom_sid_equal(&members
[i
], &member_sid
);
370 status
= NT_STATUS_OK
;
372 if (!is_member
&& mem
->active
) {
374 pdb_add_aliasmem(&alias_sid
, &member_sid
);
375 } else if (is_member
&& !mem
->active
) {
377 pdb_del_aliasmem(&alias_sid
, &member_sid
);
379 if (!NT_STATUS_IS_OK(status
)) {
380 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
382 dom_sid_str_buf(&member_sid
, &buf1
),
383 dom_sid_str_buf(&alias_sid
, &buf2
),
391 static int dssync_passdb_traverse_aliases(struct db_record
*rec
,
394 struct dssync_passdb_traverse_aliases
*state
=
395 (struct dssync_passdb_traverse_aliases
*)private_data
;
396 struct dssync_passdb
*pctx
=
397 talloc_get_type_abort(state
->ctx
->private_data
,
398 struct dssync_passdb
);
399 struct dssync_passdb_traverse_amembers mstate
;
400 struct dssync_passdb_obj
*obj
;
405 if (pctx
->methods
== NULL
) {
409 value
= dbwrap_record_get_value(rec
);
410 obj
= dssync_parse_obj(value
);
416 mstate
.ctx
= state
->ctx
;
417 mstate
.name
= "members";
419 status
= dbwrap_traverse_read(obj
->members
,
420 dssync_passdb_traverse_amembers
,
422 if (!NT_STATUS_IS_OK(status
)) {
429 struct dssync_passdb_traverse_gmembers
{
430 struct dssync_context
*ctx
;
431 struct dssync_passdb_obj
*obj
;
436 struct dssync_passdb_traverse_groups
{
437 struct dssync_context
*ctx
;
442 static int dssync_passdb_traverse_gmembers(struct db_record
*rec
,
445 struct dssync_passdb_traverse_gmembers
*state
=
446 (struct dssync_passdb_traverse_gmembers
*)private_data
;
447 struct dssync_passdb
*pctx
=
448 talloc_get_type_abort(state
->ctx
->private_data
,
449 struct dssync_passdb
);
450 struct dssync_passdb_mem
*mem
;
452 char *nt_member
= NULL
;
454 struct dom_sid group_sid
;
455 struct dom_sid member_sid
;
456 struct dom_sid_buf buf1
, buf2
;
457 struct samu
*member
= NULL
;
458 const char *member_dn
= NULL
;
462 bool is_unix_member
= false;
467 group_sid
= state
->obj
->cur
->object
.identifier
->sid
;
469 status
= dom_sid_split_rid(talloc_tos(), &group_sid
, NULL
, &rid
);
470 if (!NT_STATUS_IS_OK(status
)) {
474 value
= dbwrap_record_get_value(rec
);
476 mem
= dssync_parse_mem(value
);
481 member_sid
= mem
->cur
->sid
;
482 member_dn
= mem
->cur
->dn
;
484 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
485 if (mem
->obj
== NULL
) {
486 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
487 dom_sid_str_buf(&group_sid
, &buf1
),
488 is_null_sid(&member_sid
)?
489 dom_sid_str_buf(&member_sid
, &buf2
):
494 member_sid
= mem
->obj
->cur
->object
.identifier
->sid
;
495 member_dn
= mem
->obj
->cur
->object
.identifier
->dn
;
497 switch (mem
->obj
->type
) {
498 case ATYPE_SECURITY_LOCAL_GROUP
:
499 case ATYPE_SECURITY_GLOBAL_GROUP
:
500 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
501 dom_sid_str_buf(&group_sid
, &buf1
),
502 dom_sid_str_buf(&member_sid
, &buf2
)));
505 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
506 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
507 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
508 dom_sid_str_buf(&group_sid
, &buf1
),
515 map
= talloc_zero(NULL
, GROUP_MAP
);
520 if (!get_domain_group_from_sid(group_sid
, map
)) {
521 DEBUG(0, ("Could not find global group %s\n",
522 dom_sid_str_buf(&group_sid
, &buf1
)));
523 //return NT_STATUS_NO_SUCH_GROUP;
528 if (!(grp
= getgrgid(map
->gid
))) {
529 DEBUG(0, ("Could not find unix group %lu\n",
530 (unsigned long)map
->gid
));
531 //return NT_STATUS_NO_SUCH_GROUP;
538 DEBUG(0,("Group members of %s: ", grp
->gr_name
));
540 if ( !(member
= samu_new(talloc_tos())) ) {
541 //return NT_STATUS_NO_MEMORY;
545 if (!pdb_getsampwsid(member
, &member_sid
)) {
546 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
547 dom_sid_str_buf(&member_sid
, &buf1
),
553 if (pdb_get_group_rid(member
) == rid
) {
554 DEBUGADD(0,("%s(primary),", pdb_get_username(member
)));
559 DEBUGADD(0,("%s,", pdb_get_username(member
)));
560 nt_member
= talloc_strdup(talloc_tos(), pdb_get_username(member
));
565 unix_members
= grp
->gr_mem
;
567 while (*unix_members
) {
568 if (strcmp(*unix_members
, nt_member
) == 0) {
569 is_unix_member
= true;
575 if (!is_unix_member
&& mem
->active
) {
576 smb_add_user_group(grp
->gr_name
, nt_member
);
577 } else if (is_unix_member
&& !mem
->active
) {
578 smb_delete_user_group(grp
->gr_name
, nt_member
);
584 static int dssync_passdb_traverse_groups(struct db_record
*rec
,
587 struct dssync_passdb_traverse_groups
*state
=
588 (struct dssync_passdb_traverse_groups
*)private_data
;
589 struct dssync_passdb
*pctx
=
590 talloc_get_type_abort(state
->ctx
->private_data
,
591 struct dssync_passdb
);
592 struct dssync_passdb_traverse_gmembers mstate
;
593 struct dssync_passdb_obj
*obj
;
598 if (pctx
->methods
== NULL
) {
602 value
= dbwrap_record_get_value(rec
);
604 obj
= dssync_parse_obj(value
);
610 mstate
.ctx
= state
->ctx
;
611 mstate
.name
= "members";
613 status
= dbwrap_traverse_read(obj
->members
,
614 dssync_passdb_traverse_gmembers
,
616 if (!NT_STATUS_IS_OK(status
)) {
623 static NTSTATUS
passdb_finish(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
624 struct replUpToDateVectorBlob
*new_utdv
)
626 struct dssync_passdb
*pctx
=
627 talloc_get_type_abort(ctx
->private_data
,
628 struct dssync_passdb
);
629 struct dssync_passdb_traverse_aliases astate
;
630 struct dssync_passdb_traverse_groups gstate
;
635 astate
.name
= "aliases";
636 status
= dbwrap_traverse_read(pctx
->aliases
,
637 dssync_passdb_traverse_aliases
,
639 if (!NT_STATUS_IS_OK(status
)) {
640 return NT_STATUS_INTERNAL_ERROR
;
645 gstate
.name
= "groups";
646 status
= dbwrap_traverse_read(pctx
->groups
,
647 dssync_passdb_traverse_groups
,
649 if (!NT_STATUS_IS_OK(status
)) {
650 return NT_STATUS_INTERNAL_ERROR
;
653 TALLOC_FREE(pctx
->methods
);
659 /****************************************************************
660 ****************************************************************/
662 static NTSTATUS
smb_create_user(TALLOC_CTX
*mem_ctx
,
665 struct passwd
**passwd_p
)
667 const struct loadparm_substitution
*lp_sub
=
668 loadparm_s3_global_substitution();
669 struct passwd
*passwd
;
670 char *add_script
= NULL
;
672 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
678 /* Create appropriate user */
679 if (acct_flags
& ACB_NORMAL
) {
680 add_script
= lp_add_user_script(mem_ctx
, lp_sub
);
681 } else if ( (acct_flags
& ACB_WSTRUST
) ||
682 (acct_flags
& ACB_SVRTRUST
) ||
683 (acct_flags
& ACB_DOMTRUST
) ) {
684 add_script
= lp_add_machine_script(mem_ctx
, lp_sub
);
686 DEBUG(1, ("Unknown user type: %s\n",
687 pdb_encode_acct_ctrl(acct_flags
, NEW_PW_FORMAT_SPACE_PADDED_LEN
)));
688 return NT_STATUS_UNSUCCESSFUL
;
692 return NT_STATUS_NO_MEMORY
;
697 add_script
= talloc_all_string_sub(mem_ctx
, add_script
,
700 return NT_STATUS_NO_MEMORY
;
702 add_ret
= smbrun(add_script
, NULL
, NULL
);
703 DEBUG(add_ret
? 0 : 1,("fetch_account: Running the command `%s' "
704 "gave %d\n", add_script
, add_ret
));
706 smb_nscd_flush_user_cache();
710 /* try and find the possible unix account again */
711 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
713 return NT_STATUS_NO_SUCH_USER
;
721 static struct drsuapi_DsReplicaAttribute
*find_drsuapi_attr(
722 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
727 for (i
= 0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
728 struct drsuapi_DsReplicaAttribute
*attr
;
730 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
732 if (attr
->attid
== attid
) {
740 static NTSTATUS
find_drsuapi_attr_string(TALLOC_CTX
*mem_ctx
,
741 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
746 struct drsuapi_DsReplicaAttribute
*attr
;
750 attr
= find_drsuapi_attr(cur
, attid
);
752 return NT_STATUS_PROPSET_NOT_FOUND
;
755 array
= talloc_array(mem_ctx
, char *, attr
->value_ctr
.num_values
);
757 return NT_STATUS_NO_MEMORY
;
760 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
761 const DATA_BLOB
*blob
;
764 blob
= attr
->value_ctr
.values
[a
].blob
;
767 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
770 ret
= pull_string_talloc(array
, NULL
, 0, &array
[a
],
771 blob
->data
, blob
->length
,
775 return NT_STATUS_INTERNAL_ERROR
;
779 *_count
= attr
->value_ctr
.num_values
;
784 static NTSTATUS
find_drsuapi_attr_int32(TALLOC_CTX
*mem_ctx
,
785 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
790 struct drsuapi_DsReplicaAttribute
*attr
;
794 attr
= find_drsuapi_attr(cur
, attid
);
796 return NT_STATUS_PROPSET_NOT_FOUND
;
799 array
= talloc_array(mem_ctx
, int32_t, attr
->value_ctr
.num_values
);
801 return NT_STATUS_NO_MEMORY
;
804 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
805 const DATA_BLOB
*blob
;
807 blob
= attr
->value_ctr
.values
[a
].blob
;
810 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
813 if (blob
->length
!= 4) {
814 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
817 array
[a
] = IVAL(blob
->data
, 0);
820 *_count
= attr
->value_ctr
.num_values
;
825 static NTSTATUS
find_drsuapi_attr_blob(TALLOC_CTX
*mem_ctx
,
826 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
831 struct drsuapi_DsReplicaAttribute
*attr
;
835 attr
= find_drsuapi_attr(cur
, attid
);
837 return NT_STATUS_PROPSET_NOT_FOUND
;
840 array
= talloc_array(mem_ctx
, DATA_BLOB
, attr
->value_ctr
.num_values
);
842 return NT_STATUS_NO_MEMORY
;
845 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
846 const DATA_BLOB
*blob
;
848 blob
= attr
->value_ctr
.values
[a
].blob
;
851 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
854 array
[a
] = data_blob_talloc(array
, blob
->data
, blob
->length
);
855 if (array
[a
].length
!= blob
->length
) {
856 return NT_STATUS_NO_MEMORY
;
859 *_count
= attr
->value_ctr
.num_values
;
864 static NTSTATUS
find_drsuapi_attr_int64(TALLOC_CTX
*mem_ctx
,
865 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
870 struct drsuapi_DsReplicaAttribute
*attr
;
874 attr
= find_drsuapi_attr(cur
, attid
);
876 return NT_STATUS_PROPSET_NOT_FOUND
;
879 array
= talloc_array(mem_ctx
, int64_t, attr
->value_ctr
.num_values
);
881 return NT_STATUS_NO_MEMORY
;
884 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
885 const DATA_BLOB
*blob
;
887 blob
= attr
->value_ctr
.values
[a
].blob
;
890 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
893 if (blob
->length
!= 8) {
894 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
897 array
[a
] = BVAL(blob
->data
, 0);
899 *_count
= attr
->value_ctr
.num_values
;
904 static NTSTATUS
find_drsuapi_attr_dn(TALLOC_CTX
*mem_ctx
,
905 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
908 struct drsuapi_DsReplicaObjectIdentifier3
**_array
)
910 struct drsuapi_DsReplicaAttribute
*attr
;
911 struct drsuapi_DsReplicaObjectIdentifier3
*array
;
914 attr
= find_drsuapi_attr(cur
, attid
);
916 return NT_STATUS_PROPSET_NOT_FOUND
;
919 array
= talloc_array(mem_ctx
,
920 struct drsuapi_DsReplicaObjectIdentifier3
,
921 attr
->value_ctr
.num_values
);
923 return NT_STATUS_NO_MEMORY
;
926 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
927 const DATA_BLOB
*blob
;
928 enum ndr_err_code ndr_err
;
931 blob
= attr
->value_ctr
.values
[a
].blob
;
934 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
937 /* windows sometimes sends an extra two pad bytes here */
938 ndr_err
= ndr_pull_struct_blob(blob
, array
, &array
[a
],
939 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
940 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
941 status
= ndr_map_error2ntstatus(ndr_err
);
945 *_count
= attr
->value_ctr
.num_values
;
950 #define GET_BLOB_EX(attr, needed) do { \
953 DATA_BLOB *_vals = NULL; \
954 attr = data_blob_null; \
955 _status = find_drsuapi_attr_blob(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; \
981 (void)talloc_steal(mem_ctx, _vals[0].data); \
983 talloc_free(_vals); \
986 #define GET_STRING_EX(attr, needed) do { \
989 char **_vals = NULL; \
991 _status = find_drsuapi_attr_string(mem_ctx, cur, \
992 DRSUAPI_ATTID_ ## attr, \
994 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
996 _status = NT_STATUS_OK; \
1000 if (!NT_STATUS_IS_OK(_status)) { \
1001 DEBUG(0,(__location__ "attr[%s] %s\n", \
1002 #attr, nt_errstr(_status))); \
1007 talloc_free(_vals); \
1008 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1009 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1011 } else if (_cnt > 1) { \
1012 talloc_free(_vals); \
1013 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1014 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1016 attr = talloc_move(mem_ctx, &_vals[0]); \
1018 talloc_free(_vals); \
1021 #define GET_UINT32_EX(attr, needed) do { \
1024 int32_t*_vals = NULL; \
1026 _status = find_drsuapi_attr_int32(mem_ctx, cur, \
1027 DRSUAPI_ATTID_ ## attr, \
1029 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1031 _status = NT_STATUS_OK; \
1035 if (!NT_STATUS_IS_OK(_status)) { \
1036 DEBUG(0,(__location__ "attr[%s] %s\n", \
1037 #attr, nt_errstr(_status))); \
1042 talloc_free(_vals); \
1043 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1044 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1046 } else if (_cnt > 1) { \
1047 talloc_free(_vals); \
1048 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1049 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1051 attr = (uint32_t)_vals[0]; \
1053 talloc_free(_vals); \
1056 #define GET_UINT64_EX(attr, needed) do { \
1059 int64_t *_vals = NULL; \
1061 _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1062 DRSUAPI_ATTID_ ## attr, \
1064 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1066 _status = NT_STATUS_OK; \
1070 if (!NT_STATUS_IS_OK(_status)) { \
1071 DEBUG(0,(__location__ "attr[%s] %s\n", \
1072 #attr, nt_errstr(_status))); \
1077 talloc_free(_vals); \
1078 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1079 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1081 } else if (_cnt > 1) { \
1082 talloc_free(_vals); \
1083 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1084 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1086 attr = (uint64_t)_vals[0]; \
1088 talloc_free(_vals); \
1091 #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
1092 #define GET_STRING(attr) GET_STRING_EX(attr, false)
1093 #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
1094 #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
1096 /* Convert a struct samu_DELTA to a struct samu. */
1097 #define STRING_CHANGED (old_string && !new_string) ||\
1098 (!old_string && new_string) ||\
1099 (old_string && new_string && (strcmp(old_string, new_string) != 0))
1101 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1103 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1105 /****************************************************************
1106 ****************************************************************/
1108 static NTSTATUS
sam_account_from_object(struct samu
*account
,
1109 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1111 TALLOC_CTX
*mem_ctx
= account
;
1112 const char *old_string
, *new_string
;
1113 struct dom_sid_buf buf
;
1114 time_t unix_time
, stored_time
;
1120 NTTIME accountExpires
;
1121 const char *sAMAccountName
;
1122 const char *displayName
;
1123 const char *homeDirectory
;
1124 const char *homeDrive
;
1125 const char *scriptPath
;
1126 const char *profilePath
;
1127 const char *description
;
1128 const char *userWorkstations
;
1129 DATA_BLOB userParameters
;
1130 struct dom_sid objectSid
;
1131 uint32_t primaryGroupID
;
1132 uint32_t userAccountControl
;
1133 DATA_BLOB logonHours
;
1134 uint32_t badPwdCount
;
1135 uint32_t logonCount
;
1136 DATA_BLOB unicodePwd
;
1140 uint32_t acct_flags
;
1141 uint32_t units_per_week
;
1143 objectSid
= cur
->object
.identifier
->sid
;
1144 GET_STRING_EX(sAMAccountName
, true);
1145 DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1147 dom_sid_str_buf(&objectSid
, &buf
)));
1148 GET_UINT64(lastLogon
);
1149 GET_UINT64(lastLogoff
);
1150 GET_UINT64(pwdLastSet
);
1151 GET_UINT64(accountExpires
);
1152 GET_STRING(displayName
);
1153 GET_STRING(homeDirectory
);
1154 GET_STRING(homeDrive
);
1155 GET_STRING(scriptPath
);
1156 GET_STRING(profilePath
);
1157 GET_STRING(description
);
1158 GET_STRING(userWorkstations
);
1159 GET_BLOB(userParameters
);
1160 GET_UINT32(primaryGroupID
);
1161 GET_UINT32(userAccountControl
);
1162 GET_BLOB(logonHours
);
1163 GET_UINT32(badPwdCount
);
1164 GET_UINT32(logonCount
);
1165 GET_BLOB(unicodePwd
);
1168 status
= dom_sid_split_rid(mem_ctx
, &objectSid
, NULL
, &rid
);
1169 if (!NT_STATUS_IS_OK(status
)) {
1172 acct_flags
= ds_uf2acb(userAccountControl
);
1174 /* Username, fullname, home dir, dir drive, logon script, acct
1175 desc, workstations, profile. */
1177 if (sAMAccountName
) {
1178 old_string
= pdb_get_nt_username(account
);
1179 new_string
= sAMAccountName
;
1181 if (STRING_CHANGED
) {
1182 pdb_set_nt_username(account
, new_string
, PDB_CHANGED
);
1185 /* Unix username is the same - for sanity */
1186 old_string
= pdb_get_username( account
);
1187 if (STRING_CHANGED
) {
1188 pdb_set_username(account
, new_string
, PDB_CHANGED
);
1193 old_string
= pdb_get_fullname(account
);
1194 new_string
= displayName
;
1197 pdb_set_fullname(account
, new_string
, PDB_CHANGED
);
1200 if (homeDirectory
) {
1201 old_string
= pdb_get_homedir(account
);
1202 new_string
= homeDirectory
;
1205 pdb_set_homedir(account
, new_string
, PDB_CHANGED
);
1209 old_string
= pdb_get_dir_drive(account
);
1210 new_string
= homeDrive
;
1213 pdb_set_dir_drive(account
, new_string
, PDB_CHANGED
);
1217 old_string
= pdb_get_logon_script(account
);
1218 new_string
= scriptPath
;
1221 pdb_set_logon_script(account
, new_string
, PDB_CHANGED
);
1225 old_string
= pdb_get_acct_desc(account
);
1226 new_string
= description
;
1229 pdb_set_acct_desc(account
, new_string
, PDB_CHANGED
);
1232 if (userWorkstations
) {
1233 old_string
= pdb_get_workstations(account
);
1234 new_string
= userWorkstations
;
1237 pdb_set_workstations(account
, new_string
, PDB_CHANGED
);
1241 old_string
= pdb_get_profile_path(account
);
1242 new_string
= profilePath
;
1245 pdb_set_profile_path(account
, new_string
, PDB_CHANGED
);
1248 if (userParameters
.data
) {
1249 char *newstr
= NULL
;
1250 old_string
= pdb_get_munged_dial(account
);
1252 if (userParameters
.length
!= 0) {
1253 newstr
= base64_encode_data_blob(talloc_tos(),
1255 SMB_ASSERT(newstr
!= NULL
);
1258 if (STRING_CHANGED_NC(old_string
, newstr
))
1259 pdb_set_munged_dial(account
, newstr
, PDB_CHANGED
);
1260 TALLOC_FREE(newstr
);
1263 /* User and group sid */
1264 if (rid
!= 0 && pdb_get_user_rid(account
) != rid
) {
1265 pdb_set_user_sid_from_rid(account
, rid
, PDB_CHANGED
);
1267 if (primaryGroupID
!= 0 && pdb_get_group_rid(account
) != primaryGroupID
) {
1268 pdb_set_group_sid_from_rid(account
, primaryGroupID
, PDB_CHANGED
);
1271 /* Logon and password information */
1272 if (!nt_time_is_zero(&lastLogon
)) {
1273 unix_time
= nt_time_to_unix(lastLogon
);
1274 stored_time
= pdb_get_logon_time(account
);
1275 if (stored_time
!= unix_time
)
1276 pdb_set_logon_time(account
, unix_time
, PDB_CHANGED
);
1279 if (!nt_time_is_zero(&lastLogoff
)) {
1280 unix_time
= nt_time_to_unix(lastLogoff
);
1281 stored_time
= pdb_get_logoff_time(account
);
1282 if (stored_time
!= unix_time
)
1283 pdb_set_logoff_time(account
, unix_time
,PDB_CHANGED
);
1287 units_per_week
= logonHours
.length
* 8;
1289 if (pdb_get_logon_divs(account
) != units_per_week
) {
1290 pdb_set_logon_divs(account
, units_per_week
, PDB_CHANGED
);
1293 /* Logon Hours Len */
1294 if (units_per_week
/8 != pdb_get_hours_len(account
)) {
1295 pdb_set_hours_len(account
, units_per_week
/8, PDB_CHANGED
);
1299 if (logonHours
.data
) {
1300 char oldstr
[44], newstr
[44];
1301 pdb_sethexhours(oldstr
, pdb_get_hours(account
));
1302 pdb_sethexhours(newstr
, logonHours
.data
);
1303 if (!strequal(oldstr
, newstr
)) {
1304 pdb_set_hours(account
, logonHours
.data
,
1305 logonHours
.length
, PDB_CHANGED
);
1309 if (pdb_get_bad_password_count(account
) != badPwdCount
)
1310 pdb_set_bad_password_count(account
, badPwdCount
, PDB_CHANGED
);
1312 if (pdb_get_logon_count(account
) != logonCount
)
1313 pdb_set_logon_count(account
, logonCount
, PDB_CHANGED
);
1315 if (!nt_time_is_zero(&pwdLastSet
)) {
1316 unix_time
= nt_time_to_unix(pwdLastSet
);
1317 stored_time
= pdb_get_pass_last_set_time(account
);
1318 if (stored_time
!= unix_time
)
1319 pdb_set_pass_last_set_time(account
, unix_time
, PDB_CHANGED
);
1321 /* no last set time, make it now */
1322 pdb_set_pass_last_set_time(account
, time(NULL
), PDB_CHANGED
);
1325 if (!nt_time_is_zero(&accountExpires
)) {
1326 unix_time
= nt_time_to_unix(accountExpires
);
1327 stored_time
= pdb_get_kickoff_time(account
);
1328 if (stored_time
!= unix_time
)
1329 pdb_set_kickoff_time(account
, unix_time
, PDB_CHANGED
);
1332 /* Decode hashes from password hash
1333 Note that win2000 may send us all zeros for the hashes if it doesn't
1334 think this channel is secure enough - don't set the passwords at all
1337 if (dBCSPwd
.length
== 16 && !all_zero(dBCSPwd
.data
, 16)) {
1338 pdb_set_lanman_passwd(account
, dBCSPwd
.data
, PDB_CHANGED
);
1341 if (unicodePwd
.length
== 16 && !all_zero(unicodePwd
.data
, 16)) {
1342 pdb_set_nt_passwd(account
, unicodePwd
.data
, PDB_CHANGED
);
1347 /* TODO: account expiry time */
1349 pdb_set_acct_ctrl(account
, acct_flags
, PDB_CHANGED
);
1351 pdb_set_domain(account
, lp_workgroup(), PDB_CHANGED
);
1353 DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1355 dom_sid_str_buf(&objectSid
, &buf
)));
1356 return NT_STATUS_OK
;
1359 /****************************************************************
1360 ****************************************************************/
1362 static NTSTATUS
handle_account_object(struct dssync_passdb
*pctx
,
1363 TALLOC_CTX
*mem_ctx
,
1364 struct dssync_passdb_obj
*obj
)
1366 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1369 struct samu
*sam_account
=NULL
;
1372 struct dom_sid user_sid
;
1373 struct dom_sid group_sid
;
1374 struct dom_sid_buf buf
;
1375 struct passwd
*passwd
= NULL
;
1376 uint32_t acct_flags
;
1379 const char *sAMAccountName
;
1380 uint32_t userAccountControl
;
1382 user_sid
= cur
->object
.identifier
->sid
;
1383 GET_STRING_EX(sAMAccountName
, true);
1384 GET_UINT32_EX(userAccountControl
, true);
1386 status
= dom_sid_split_rid(mem_ctx
, &user_sid
, NULL
, &rid
);
1387 if (!NT_STATUS_IS_OK(status
)) {
1391 fstrcpy(account
, sAMAccountName
);
1392 if (rid
== DOMAIN_RID_GUEST
) {
1394 * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1395 * that's why we need to ignore it here.
1397 * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1400 DEBUG(0,("Ignore %s - %s\n",
1402 dom_sid_str_buf(&user_sid
, &buf
)));
1403 return NT_STATUS_OK
;
1405 DEBUG(0,("Creating account: %s\n", account
));
1407 if ( !(sam_account
= samu_new(mem_ctx
)) ) {
1408 return NT_STATUS_NO_MEMORY
;
1411 acct_flags
= ds_uf2acb(userAccountControl
);
1412 status
= smb_create_user(sam_account
, acct_flags
, account
, &passwd
);
1413 if (!NT_STATUS_IS_OK(status
)) {
1414 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1415 account
, nt_errstr(status
)));
1416 TALLOC_FREE(sam_account
);
1420 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1421 dom_sid_str_buf(&user_sid
, &buf
),
1423 if (!pdb_getsampwsid(sam_account
, &user_sid
)) {
1424 sam_account_from_object(sam_account
, cur
);
1425 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
1426 dom_sid_str_buf(&user_sid
, &buf
),
1427 pdb_get_username(sam_account
)));
1428 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account
))) {
1429 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1431 TALLOC_FREE(sam_account
);
1432 return NT_STATUS_ACCESS_DENIED
;
1435 sam_account_from_object(sam_account
, cur
);
1436 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
1437 dom_sid_str_buf(&user_sid
, &buf
),
1438 pdb_get_username(sam_account
)));
1439 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account
))) {
1440 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1442 TALLOC_FREE(sam_account
);
1443 return NT_STATUS_ACCESS_DENIED
;
1447 if (pdb_get_group_sid(sam_account
) == NULL
) {
1448 TALLOC_FREE(sam_account
);
1449 return NT_STATUS_UNSUCCESSFUL
;
1452 group_sid
= *pdb_get_group_sid(sam_account
);
1454 map
= talloc_zero(NULL
, GROUP_MAP
);
1456 return NT_STATUS_NO_MEMORY
;
1459 if (!pdb_getgrsid(map
, group_sid
)) {
1460 DEBUG(0, ("Primary group of %s has no mapping!\n",
1461 pdb_get_username(sam_account
)));
1463 if (map
->gid
!= passwd
->pw_gid
) {
1464 if (!(grp
= getgrgid(map
->gid
))) {
1465 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
1466 (unsigned long)map
->gid
, pdb_get_username(sam_account
),
1467 dom_sid_str_buf(&group_sid
, &buf
)));
1469 smb_set_primary_group(grp
->gr_name
, pdb_get_username(sam_account
));
1477 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1478 pdb_get_username(sam_account
)));
1481 TALLOC_FREE(sam_account
);
1482 return NT_STATUS_OK
;
1485 /****************************************************************
1486 ****************************************************************/
1488 static NTSTATUS
handle_alias_object(struct dssync_passdb
*pctx
,
1489 TALLOC_CTX
*mem_ctx
,
1490 struct dssync_passdb_obj
*obj
)
1492 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1494 struct group
*grp
= NULL
;
1495 struct dom_sid group_sid
;
1497 struct dom_sid
*dom_sid
= NULL
;
1498 struct dom_sid_buf sid_str
;
1502 const char *sAMAccountName
;
1503 const char *description
;
1505 uint32_t num_members
= 0;
1506 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1508 group_sid
= cur
->object
.identifier
->sid
;
1509 GET_STRING_EX(sAMAccountName
, true);
1510 GET_STRING(description
);
1512 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1513 &num_members
, &members
);
1514 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1515 status
= NT_STATUS_OK
;
1517 if (!NT_STATUS_IS_OK(status
)) {
1521 dom_sid_split_rid(mem_ctx
, &group_sid
, &dom_sid
, &rid
);
1523 map
= talloc_zero(mem_ctx
, GROUP_MAP
);
1525 status
= NT_STATUS_NO_MEMORY
;
1529 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1530 if (map
->nt_name
== NULL
) {
1531 status
= NT_STATUS_NO_MEMORY
;
1536 map
->comment
= talloc_strdup(map
, description
);
1538 map
->comment
= talloc_strdup(map
, "");
1540 if (map
->comment
== NULL
) {
1541 status
= NT_STATUS_NO_MEMORY
;
1545 DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1547 dom_sid_str_buf(&group_sid
, &sid_str
),
1550 status
= dssync_insert_obj(pctx
, pctx
->aliases
, obj
);
1551 if (!NT_STATUS_IS_OK(status
)) {
1555 if (pdb_getgrsid(map
, group_sid
)) {
1556 if (map
->gid
!= -1) {
1557 grp
= getgrgid(map
->gid
);
1565 /* No group found from mapping, find it from its name. */
1566 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1568 /* No appropriate group found, create one */
1570 DEBUG(0, ("Creating unix group: '%s'\n",
1573 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1574 status
= NT_STATUS_ACCESS_DENIED
;
1578 if ((grp
= getgrgid(gid
)) == NULL
) {
1579 status
= NT_STATUS_ACCESS_DENIED
;
1585 map
->gid
= grp
->gr_gid
;
1586 map
->sid
= group_sid
;
1588 if (dom_sid_equal(dom_sid
, &global_sid_Builtin
)) {
1590 * pdb_ldap does not like SID_NAME_WKN_GRP...
1592 * map.sid_name_use = SID_NAME_WKN_GRP;
1594 map
->sid_name_use
= SID_NAME_ALIAS
;
1596 map
->sid_name_use
= SID_NAME_ALIAS
;
1600 pdb_add_group_mapping_entry(map
);
1602 pdb_update_group_mapping_entry(map
);
1605 for (i
=0; i
< num_members
; i
++) {
1606 struct dssync_passdb_mem
*mem
;
1608 status
= dssync_create_mem(pctx
, obj
,
1611 if (!NT_STATUS_IS_OK(status
)) {
1616 status
= NT_STATUS_OK
;
1623 /****************************************************************
1624 ****************************************************************/
1626 static NTSTATUS
handle_group_object(struct dssync_passdb
*pctx
,
1627 TALLOC_CTX
*mem_ctx
,
1628 struct dssync_passdb_obj
*obj
)
1630 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1632 struct group
*grp
= NULL
;
1633 struct dom_sid group_sid
;
1634 struct dom_sid_buf sid_str
;
1638 const char *sAMAccountName
;
1639 const char *description
;
1641 uint32_t num_members
= 0;
1642 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1644 group_sid
= cur
->object
.identifier
->sid
;
1645 GET_STRING_EX(sAMAccountName
, true);
1646 GET_STRING(description
);
1648 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1649 &num_members
, &members
);
1650 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1651 status
= NT_STATUS_OK
;
1653 if (!NT_STATUS_IS_OK(status
)) {
1657 map
= talloc_zero(NULL
, GROUP_MAP
);
1659 return NT_STATUS_NO_MEMORY
;
1662 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1663 if (!map
->nt_name
) {
1664 status
= NT_STATUS_NO_MEMORY
;
1668 map
->comment
= talloc_strdup(map
, description
);
1670 map
->comment
= talloc_strdup(map
, "");
1672 if (!map
->comment
) {
1673 status
= NT_STATUS_NO_MEMORY
;
1677 DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1679 dom_sid_str_buf(&group_sid
, &sid_str
),
1682 status
= dssync_insert_obj(pctx
, pctx
->groups
, obj
);
1683 if (!NT_STATUS_IS_OK(status
)) {
1687 if (pdb_getgrsid(map
, group_sid
)) {
1688 if (map
->gid
!= -1) {
1689 grp
= getgrgid(map
->gid
);
1697 /* No group found from mapping, find it from its name. */
1698 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1700 /* No appropriate group found, create one */
1702 DEBUG(0, ("Creating unix group: '%s'\n",
1705 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1706 status
= NT_STATUS_ACCESS_DENIED
;
1710 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1711 status
= NT_STATUS_ACCESS_DENIED
;
1717 map
->gid
= grp
->gr_gid
;
1718 map
->sid
= group_sid
;
1719 map
->sid_name_use
= SID_NAME_DOM_GRP
;
1722 pdb_add_group_mapping_entry(map
);
1724 pdb_update_group_mapping_entry(map
);
1727 for (i
=0; i
< num_members
; i
++) {
1728 struct dssync_passdb_mem
*mem
;
1730 status
= dssync_create_mem(pctx
, obj
,
1733 if (!NT_STATUS_IS_OK(status
)) {
1738 status
= NT_STATUS_OK
;
1745 /****************************************************************
1746 ****************************************************************/
1748 static NTSTATUS
handle_interdomain_trust_object(struct dssync_passdb
*pctx
,
1749 TALLOC_CTX
*mem_ctx
,
1750 struct dssync_passdb_obj
*obj
)
1752 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1753 DEBUG(0,("trust: %s\n", cur
->object
.identifier
->dn
));
1754 return NT_STATUS_NOT_IMPLEMENTED
;
1757 /****************************************************************
1758 ****************************************************************/
1760 struct dssync_object_table_t
{
1762 NTSTATUS (*fn
) (struct dssync_passdb
*pctx
,
1763 TALLOC_CTX
*mem_ctx
,
1764 struct dssync_passdb_obj
*obj
);
1767 static const struct dssync_object_table_t dssync_object_table
[] = {
1768 { ATYPE_NORMAL_ACCOUNT
, handle_account_object
},
1769 { ATYPE_WORKSTATION_TRUST
, handle_account_object
},
1770 { ATYPE_SECURITY_LOCAL_GROUP
, handle_alias_object
},
1771 { ATYPE_SECURITY_GLOBAL_GROUP
, handle_group_object
},
1772 { ATYPE_INTERDOMAIN_TRUST
, handle_interdomain_trust_object
},
1775 /****************************************************************
1776 ****************************************************************/
1778 static NTSTATUS
parse_object(struct dssync_passdb
*pctx
,
1779 TALLOC_CTX
*mem_ctx
,
1780 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1782 NTSTATUS status
= NT_STATUS_OK
;
1783 DATA_BLOB
*blob
= NULL
;
1788 uint32_t sam_type
= 0;
1790 DEBUG(3, ("parsing object '%s'\n", cur
->object
.identifier
->dn
));
1792 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
1793 struct drsuapi_DsReplicaAttribute
*attr
=
1794 &cur
->object
.attribute_ctr
.attributes
[i
];
1796 if (attr
->value_ctr
.num_values
!= 1) {
1800 if (!attr
->value_ctr
.values
[0].blob
) {
1804 blob
= attr
->value_ctr
.values
[0].blob
;
1806 switch (attr
->attid
) {
1807 case DRSUAPI_ATTID_sAMAccountName
:
1808 pull_string_talloc(mem_ctx
, NULL
, 0, &name
,
1809 blob
->data
, blob
->length
,
1812 case DRSUAPI_ATTID_sAMAccountType
:
1813 sam_type
= IVAL(blob
->data
, 0);
1820 for (a
=0; a
< ARRAY_SIZE(dssync_object_table
); a
++) {
1821 if (sam_type
== dssync_object_table
[a
].type
) {
1822 if (dssync_object_table
[a
].fn
) {
1823 struct dssync_passdb_obj
*obj
= NULL
;
1824 status
= dssync_create_obj(pctx
, pctx
->all
,
1825 sam_type
, cur
, &obj
);
1826 if (!NT_STATUS_IS_OK(status
)) {
1829 status
= dssync_object_table
[a
].fn(pctx
,
1840 static NTSTATUS
parse_link(struct dssync_passdb
*pctx
,
1841 TALLOC_CTX
*mem_ctx
,
1842 struct drsuapi_DsReplicaLinkedAttribute
*cur
)
1844 struct drsuapi_DsReplicaObjectIdentifier3
*id3
;
1845 const DATA_BLOB
*blob
;
1846 enum ndr_err_code ndr_err
;
1848 bool active
= false;
1849 struct dssync_passdb_mem
*mem
;
1850 struct dssync_passdb_obj
*obj
;
1852 if (cur
->attid
!= DRSUAPI_ATTID_member
) {
1853 return NT_STATUS_OK
;
1856 if (cur
->flags
& DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
) {
1860 DEBUG(3, ("parsing link '%s' - %s\n",
1861 cur
->identifier
->dn
, active
?"adding":"deleting"));
1863 blob
= cur
->value
.blob
;
1866 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1869 obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &cur
->identifier
->guid
);
1871 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1874 id3
= talloc_zero(obj
, struct drsuapi_DsReplicaObjectIdentifier3
);
1876 return NT_STATUS_NO_MEMORY
;
1879 /* windows sometimes sends an extra two pad bytes here */
1880 ndr_err
= ndr_pull_struct_blob(blob
, id3
, id3
,
1881 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
1882 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1883 status
= ndr_map_error2ntstatus(ndr_err
);
1887 status
= dssync_create_mem(pctx
, obj
,
1890 if (!NT_STATUS_IS_OK(status
)) {
1894 return NT_STATUS_OK
;
1897 /****************************************************************
1898 ****************************************************************/
1900 static NTSTATUS
passdb_process_objects(struct dssync_context
*ctx
,
1901 TALLOC_CTX
*mem_ctx
,
1902 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
1903 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1905 NTSTATUS status
= NT_STATUS_OK
;
1906 struct dssync_passdb
*pctx
=
1907 talloc_get_type_abort(ctx
->private_data
,
1908 struct dssync_passdb
);
1910 for (; cur
; cur
= cur
->next_object
) {
1911 status
= parse_object(pctx
, mem_ctx
, cur
);
1912 if (!NT_STATUS_IS_OK(status
)) {
1921 /****************************************************************
1922 ****************************************************************/
1924 static NTSTATUS
passdb_process_links(struct dssync_context
*ctx
,
1925 TALLOC_CTX
*mem_ctx
,
1927 struct drsuapi_DsReplicaLinkedAttribute
*links
,
1928 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1930 NTSTATUS status
= NT_STATUS_OK
;
1931 struct dssync_passdb
*pctx
=
1932 talloc_get_type_abort(ctx
->private_data
,
1933 struct dssync_passdb
);
1936 for (i
= 0; i
< count
; i
++) {
1937 status
= parse_link(pctx
, mem_ctx
, &links
[i
]);
1938 if (!NT_STATUS_IS_OK(status
)) {
1947 /****************************************************************
1948 ****************************************************************/
1950 const struct dssync_ops libnet_dssync_passdb_ops
= {
1951 .startup
= passdb_startup
,
1952 .process_objects
= passdb_process_objects
,
1953 .process_links
= passdb_process_links
,
1954 .finish
= passdb_finish
,