Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Guenther Deschner <gd@samba.org> 2008
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
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"
26 : #include "util_tdb.h"
27 : #include "dbwrap/dbwrap.h"
28 : #include "dbwrap/dbwrap_rbt.h"
29 : #include "../libds/common/flag_mapping.h"
30 : #include "passdb.h"
31 : #include "lib/util/base64.h"
32 : #include "lib/util/string_wrappers.h"
33 :
34 : /****************************************************************
35 : ****************************************************************/
36 :
37 : struct dssync_passdb {
38 : struct pdb_methods *methods;
39 : struct db_context *all;
40 : struct db_context *aliases;
41 : struct db_context *groups;
42 : };
43 :
44 : struct dssync_passdb_obj {
45 : struct dssync_passdb_obj *self;
46 : uint32_t type;
47 : struct drsuapi_DsReplicaObjectListItemEx *cur;
48 : TDB_DATA key;
49 : TDB_DATA data;
50 : struct db_context *members;
51 : };
52 :
53 : struct dssync_passdb_mem {
54 : struct dssync_passdb_mem *self;
55 : bool active;
56 : struct drsuapi_DsReplicaObjectIdentifier3 *cur;
57 : struct dssync_passdb_obj *obj;
58 : TDB_DATA key;
59 : TDB_DATA data;
60 : };
61 :
62 0 : static NTSTATUS dssync_insert_obj(struct dssync_passdb *pctx,
63 : struct db_context *db,
64 : struct dssync_passdb_obj *obj)
65 : {
66 0 : NTSTATUS status;
67 0 : struct db_record *rec;
68 0 : TDB_DATA value;
69 :
70 0 : rec = dbwrap_fetch_locked(db, talloc_tos(), obj->key);
71 0 : if (rec == NULL) {
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 :
75 0 : value = dbwrap_record_get_value(rec);
76 0 : if (value.dsize != 0) {
77 0 : abort();
78 : }
79 :
80 0 : status = dbwrap_record_store(rec, obj->data, TDB_INSERT);
81 0 : if (!NT_STATUS_IS_OK(status)) {
82 0 : TALLOC_FREE(rec);
83 0 : return status;
84 : }
85 0 : TALLOC_FREE(rec);
86 0 : return NT_STATUS_OK;
87 : }
88 :
89 0 : static struct dssync_passdb_obj *dssync_parse_obj(const TDB_DATA data)
90 : {
91 0 : struct dssync_passdb_obj *obj;
92 :
93 0 : if (data.dsize != sizeof(obj)) {
94 0 : return NULL;
95 : }
96 :
97 : /*
98 : * we need to copy the pointer to avoid alignment problems
99 : * on some systems.
100 : */
101 0 : memcpy(&obj, data.dptr, sizeof(obj));
102 :
103 0 : return talloc_get_type_abort(obj, struct dssync_passdb_obj);
104 : }
105 :
106 0 : static struct dssync_passdb_obj *dssync_search_obj_by_guid(struct dssync_passdb *pctx,
107 : struct db_context *db,
108 : const struct GUID *guid)
109 : {
110 0 : struct dssync_passdb_obj *obj;
111 0 : TDB_DATA key;
112 0 : TDB_DATA data;
113 0 : NTSTATUS status;
114 :
115 0 : key = make_tdb_data((const uint8_t *)(const void *)guid,
116 : sizeof(*guid));
117 :
118 0 : status = dbwrap_fetch(db, talloc_tos(), key, &data);
119 0 : if (!NT_STATUS_IS_OK(status)) {
120 0 : return NULL;
121 : }
122 :
123 0 : obj = dssync_parse_obj(data);
124 0 : return obj;
125 : }
126 :
127 0 : static NTSTATUS dssync_create_obj(struct dssync_passdb *pctx,
128 : struct db_context *db,
129 : uint32_t type,
130 : struct drsuapi_DsReplicaObjectListItemEx *cur,
131 : struct dssync_passdb_obj **_obj)
132 : {
133 0 : NTSTATUS status;
134 0 : struct dssync_passdb_obj *obj;
135 :
136 0 : obj = talloc_zero(pctx, struct dssync_passdb_obj);
137 0 : if (obj == NULL) {
138 0 : return NT_STATUS_NO_MEMORY;
139 : }
140 0 : obj->self = obj;
141 0 : obj->cur = cur;
142 0 : obj->type = type;
143 0 : obj->key = make_tdb_data((const uint8_t *)(void *)&cur->object.identifier->guid,
144 : sizeof(cur->object.identifier->guid));
145 0 : obj->data = make_tdb_data((const uint8_t *)(void *)&obj->self,
146 : sizeof(obj->self));
147 :
148 0 : obj->members = db_open_rbt(obj);
149 0 : if (obj->members == NULL) {
150 0 : return NT_STATUS_NO_MEMORY;
151 : }
152 :
153 0 : status = dssync_insert_obj(pctx, db, obj);
154 0 : if (!NT_STATUS_IS_OK(status)) {
155 0 : TALLOC_FREE(obj);
156 0 : return status;
157 : }
158 0 : *_obj = obj;
159 0 : return NT_STATUS_OK;
160 : }
161 :
162 0 : static NTSTATUS dssync_insert_mem(struct dssync_passdb *pctx,
163 : struct dssync_passdb_obj *obj,
164 : struct dssync_passdb_mem *mem)
165 : {
166 0 : NTSTATUS status;
167 0 : struct db_record *rec;
168 0 : TDB_DATA value;
169 :
170 0 : rec = dbwrap_fetch_locked(obj->members, talloc_tos(), mem->key);
171 0 : if (rec == NULL) {
172 0 : return NT_STATUS_NO_MEMORY;
173 : }
174 :
175 0 : value = dbwrap_record_get_value(rec);
176 0 : if (value.dsize != 0) {
177 0 : abort();
178 : }
179 :
180 0 : status = dbwrap_record_store(rec, mem->data, TDB_INSERT);
181 0 : if (!NT_STATUS_IS_OK(status)) {
182 0 : TALLOC_FREE(rec);
183 0 : return status;
184 : }
185 0 : TALLOC_FREE(rec);
186 0 : return NT_STATUS_OK;
187 : }
188 :
189 0 : static NTSTATUS dssync_create_mem(struct dssync_passdb *pctx,
190 : struct dssync_passdb_obj *obj,
191 : bool active,
192 : struct drsuapi_DsReplicaObjectIdentifier3 *cur,
193 : struct dssync_passdb_mem **_mem)
194 : {
195 0 : NTSTATUS status;
196 0 : struct dssync_passdb_mem *mem;
197 :
198 0 : mem = talloc_zero(pctx, struct dssync_passdb_mem);
199 0 : if (mem == NULL) {
200 0 : return NT_STATUS_NO_MEMORY;
201 : }
202 0 : mem->self = mem;
203 0 : mem->cur = cur;
204 0 : mem->active = active;
205 0 : mem->obj = NULL;
206 0 : mem->key = make_tdb_data((const uint8_t *)(void *)&cur->guid,
207 : sizeof(cur->guid));
208 0 : mem->data = make_tdb_data((const uint8_t *)(void *)&mem->self,
209 : sizeof(mem->self));
210 :
211 0 : status = dssync_insert_mem(pctx, obj, mem);
212 0 : if (!NT_STATUS_IS_OK(status)) {
213 0 : TALLOC_FREE(obj);
214 0 : return status;
215 : }
216 0 : *_mem = mem;
217 0 : return NT_STATUS_OK;
218 : }
219 :
220 0 : static struct dssync_passdb_mem *dssync_parse_mem(const TDB_DATA data)
221 : {
222 0 : struct dssync_passdb_mem *mem;
223 :
224 0 : if (data.dsize != sizeof(mem)) {
225 0 : return NULL;
226 : }
227 :
228 : /*
229 : * we need to copy the pointer to avoid alignment problems
230 : * on some systems.
231 : */
232 0 : memcpy(&mem, data.dptr, sizeof(mem));
233 :
234 0 : return talloc_get_type_abort(mem, struct dssync_passdb_mem);
235 : }
236 :
237 0 : static NTSTATUS passdb_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
238 : struct replUpToDateVectorBlob **pold_utdv)
239 : {
240 0 : NTSTATUS status;
241 0 : struct dssync_passdb *pctx;
242 :
243 0 : pctx = talloc_zero(mem_ctx, struct dssync_passdb);
244 0 : if (pctx == NULL) {
245 0 : return NT_STATUS_NO_MEMORY;
246 : }
247 :
248 0 : if (ctx->output_filename) {
249 0 : status = make_pdb_method_name(&pctx->methods, ctx->output_filename);
250 : } else {
251 0 : status = make_pdb_method_name(&pctx->methods, lp_passdb_backend());
252 : }
253 :
254 0 : if (!NT_STATUS_IS_OK(status)) {
255 0 : return status;
256 : }
257 :
258 0 : pctx->all = db_open_rbt(pctx);
259 0 : if (pctx->all == NULL) {
260 0 : return NT_STATUS_NO_MEMORY;
261 : }
262 0 : pctx->aliases = db_open_rbt(pctx);
263 0 : if (pctx->aliases == NULL) {
264 0 : return NT_STATUS_NO_MEMORY;
265 : }
266 0 : pctx->groups = db_open_rbt(pctx);
267 0 : if (pctx->groups == NULL) {
268 0 : return NT_STATUS_NO_MEMORY;
269 : }
270 :
271 0 : ctx->private_data = pctx;
272 :
273 0 : return status;
274 : }
275 :
276 : /****************************************************************
277 : ****************************************************************/
278 :
279 : struct dssync_passdb_traverse_amembers {
280 : struct dssync_context *ctx;
281 : struct dssync_passdb_obj *obj;
282 : const char *name;
283 : uint32_t idx;
284 : };
285 :
286 : struct dssync_passdb_traverse_aliases {
287 : struct dssync_context *ctx;
288 : const char *name;
289 : uint32_t idx;
290 : };
291 :
292 0 : static int dssync_passdb_traverse_amembers(struct db_record *rec,
293 : void *private_data)
294 : {
295 0 : struct dssync_passdb_traverse_amembers *state =
296 : (struct dssync_passdb_traverse_amembers *)private_data;
297 0 : struct dssync_passdb *pctx =
298 0 : talloc_get_type_abort(state->ctx->private_data,
299 : struct dssync_passdb);
300 0 : struct dssync_passdb_mem *mem;
301 0 : NTSTATUS status;
302 0 : struct dom_sid alias_sid;
303 0 : struct dom_sid member_sid;
304 0 : struct dom_sid_buf buf1, buf2;
305 0 : const char *member_dn;
306 0 : size_t num_members;
307 0 : size_t i;
308 0 : struct dom_sid *members;
309 0 : bool is_member = false;
310 0 : const char *action;
311 0 : TDB_DATA value;
312 :
313 0 : state->idx++;
314 :
315 0 : alias_sid = state->obj->cur->object.identifier->sid;
316 :
317 0 : value = dbwrap_record_get_value(rec);
318 0 : mem = dssync_parse_mem(value);
319 0 : if (mem == NULL) {
320 0 : return -1;
321 : }
322 :
323 0 : member_sid = mem->cur->sid;
324 0 : member_dn = mem->cur->dn;
325 :
326 0 : mem->obj = dssync_search_obj_by_guid(pctx, pctx->all, &mem->cur->guid);
327 0 : if (mem->obj == NULL) {
328 0 : 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):
332 : member_dn));
333 0 : return 0;
334 : }
335 :
336 0 : switch (mem->obj->type) {
337 0 : case ATYPE_DISTRIBUTION_LOCAL_GROUP:
338 : case ATYPE_DISTRIBUTION_GLOBAL_GROUP:
339 0 : DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
340 : dom_sid_str_buf(&alias_sid, &buf1),
341 : member_dn));
342 0 : return 0;
343 0 : default:
344 0 : break;
345 : }
346 :
347 0 : DEBUG(0,("alias[%s] member[%s]\n",
348 : dom_sid_str_buf(&alias_sid, &buf1),
349 : dom_sid_str_buf(&member_sid, &buf2)));
350 :
351 0 : status = pdb_enum_aliasmem(&alias_sid, talloc_tos(),
352 : &members, &num_members);
353 0 : if (!NT_STATUS_IS_OK(status)) {
354 0 : DEBUG(0, ("Could not find current alias members %s - %s\n",
355 : dom_sid_str_buf(&alias_sid, &buf1),
356 : nt_errstr(status)));
357 0 : return -1;
358 : }
359 :
360 0 : for (i=0; i < num_members; i++) {
361 0 : bool match;
362 :
363 0 : match = dom_sid_equal(&members[i], &member_sid);
364 0 : if (match) {
365 0 : is_member = true;
366 0 : break;
367 : }
368 : }
369 :
370 0 : status = NT_STATUS_OK;
371 0 : action = "none";
372 0 : if (!is_member && mem->active) {
373 0 : action = "add";
374 0 : pdb_add_aliasmem(&alias_sid, &member_sid);
375 0 : } else if (is_member && !mem->active) {
376 0 : action = "delete";
377 0 : pdb_del_aliasmem(&alias_sid, &member_sid);
378 : }
379 0 : if (!NT_STATUS_IS_OK(status)) {
380 0 : DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
381 : action,
382 : dom_sid_str_buf(&member_sid, &buf1),
383 : dom_sid_str_buf(&alias_sid, &buf2),
384 : nt_errstr(status)));
385 0 : return -1;
386 : }
387 :
388 0 : return 0;
389 : }
390 :
391 0 : static int dssync_passdb_traverse_aliases(struct db_record *rec,
392 : void *private_data)
393 : {
394 0 : struct dssync_passdb_traverse_aliases *state =
395 : (struct dssync_passdb_traverse_aliases *)private_data;
396 0 : struct dssync_passdb *pctx =
397 0 : talloc_get_type_abort(state->ctx->private_data,
398 : struct dssync_passdb);
399 0 : struct dssync_passdb_traverse_amembers mstate;
400 0 : struct dssync_passdb_obj *obj;
401 0 : TDB_DATA value;
402 0 : NTSTATUS status;
403 :
404 0 : state->idx++;
405 0 : if (pctx->methods == NULL) {
406 0 : return -1;
407 : }
408 :
409 0 : value = dbwrap_record_get_value(rec);
410 0 : obj = dssync_parse_obj(value);
411 0 : if (obj == NULL) {
412 0 : return -1;
413 : }
414 :
415 0 : ZERO_STRUCT(mstate);
416 0 : mstate.ctx = state->ctx;
417 0 : mstate.name = "members";
418 0 : mstate.obj = obj;
419 0 : status = dbwrap_traverse_read(obj->members,
420 : dssync_passdb_traverse_amembers,
421 : &mstate, NULL);
422 0 : if (!NT_STATUS_IS_OK(status)) {
423 0 : return -1;
424 : }
425 :
426 0 : return 0;
427 : }
428 :
429 : struct dssync_passdb_traverse_gmembers {
430 : struct dssync_context *ctx;
431 : struct dssync_passdb_obj *obj;
432 : const char *name;
433 : uint32_t idx;
434 : };
435 :
436 : struct dssync_passdb_traverse_groups {
437 : struct dssync_context *ctx;
438 : const char *name;
439 : uint32_t idx;
440 : };
441 :
442 0 : static int dssync_passdb_traverse_gmembers(struct db_record *rec,
443 : void *private_data)
444 : {
445 0 : struct dssync_passdb_traverse_gmembers *state =
446 : (struct dssync_passdb_traverse_gmembers *)private_data;
447 0 : struct dssync_passdb *pctx =
448 0 : talloc_get_type_abort(state->ctx->private_data,
449 : struct dssync_passdb);
450 0 : struct dssync_passdb_mem *mem;
451 0 : NTSTATUS status;
452 0 : char *nt_member = NULL;
453 0 : char **unix_members;
454 0 : struct dom_sid group_sid;
455 0 : struct dom_sid member_sid;
456 0 : struct dom_sid_buf buf1, buf2;
457 0 : struct samu *member = NULL;
458 0 : const char *member_dn = NULL;
459 0 : GROUP_MAP *map;
460 0 : struct group *grp;
461 0 : uint32_t rid;
462 0 : bool is_unix_member = false;
463 0 : TDB_DATA value;
464 :
465 0 : state->idx++;
466 :
467 0 : group_sid = state->obj->cur->object.identifier->sid;
468 :
469 0 : status = dom_sid_split_rid(talloc_tos(), &group_sid, NULL, &rid);
470 0 : if (!NT_STATUS_IS_OK(status)) {
471 0 : return -1;
472 : }
473 :
474 0 : value = dbwrap_record_get_value(rec);
475 :
476 0 : mem = dssync_parse_mem(value);
477 0 : if (mem == NULL) {
478 0 : return -1;
479 : }
480 :
481 0 : member_sid = mem->cur->sid;
482 0 : member_dn = mem->cur->dn;
483 :
484 0 : mem->obj = dssync_search_obj_by_guid(pctx, pctx->all, &mem->cur->guid);
485 0 : if (mem->obj == NULL) {
486 0 : 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):
490 : member_dn));
491 0 : return 0;
492 : }
493 :
494 0 : member_sid = mem->obj->cur->object.identifier->sid;
495 0 : member_dn = mem->obj->cur->object.identifier->dn;
496 :
497 0 : switch (mem->obj->type) {
498 0 : case ATYPE_SECURITY_LOCAL_GROUP:
499 : case ATYPE_SECURITY_GLOBAL_GROUP:
500 0 : 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)));
503 0 : return 0;
504 :
505 0 : case ATYPE_DISTRIBUTION_LOCAL_GROUP:
506 : case ATYPE_DISTRIBUTION_GLOBAL_GROUP:
507 0 : DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
508 : dom_sid_str_buf(&group_sid, &buf1),
509 : member_dn));
510 0 : return 0;
511 0 : default:
512 0 : break;
513 : }
514 :
515 0 : map = talloc_zero(NULL, GROUP_MAP);
516 0 : if (!map) {
517 0 : return -1;
518 : }
519 :
520 0 : if (!get_domain_group_from_sid(group_sid, map)) {
521 0 : DEBUG(0, ("Could not find global group %s\n",
522 : dom_sid_str_buf(&group_sid, &buf1)));
523 : //return NT_STATUS_NO_SUCH_GROUP;
524 0 : TALLOC_FREE(map);
525 0 : return -1;
526 : }
527 :
528 0 : if (!(grp = getgrgid(map->gid))) {
529 0 : DEBUG(0, ("Could not find unix group %lu\n",
530 : (unsigned long)map->gid));
531 : //return NT_STATUS_NO_SUCH_GROUP;
532 0 : TALLOC_FREE(map);
533 0 : return -1;
534 : }
535 :
536 0 : TALLOC_FREE(map);
537 :
538 0 : DEBUG(0,("Group members of %s: ", grp->gr_name));
539 :
540 0 : if ( !(member = samu_new(talloc_tos())) ) {
541 : //return NT_STATUS_NO_MEMORY;
542 0 : return -1;
543 : }
544 :
545 0 : if (!pdb_getsampwsid(member, &member_sid)) {
546 0 : DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
547 : dom_sid_str_buf(&member_sid, &buf1),
548 : grp->gr_name));
549 0 : TALLOC_FREE(member);
550 0 : return -1;
551 : }
552 :
553 0 : if (pdb_get_group_rid(member) == rid) {
554 0 : DEBUGADD(0,("%s(primary),", pdb_get_username(member)));
555 0 : TALLOC_FREE(member);
556 0 : return -1;
557 : }
558 :
559 0 : DEBUGADD(0,("%s,", pdb_get_username(member)));
560 0 : nt_member = talloc_strdup(talloc_tos(), pdb_get_username(member));
561 0 : TALLOC_FREE(member);
562 :
563 0 : DEBUGADD(0,("\n"));
564 :
565 0 : unix_members = grp->gr_mem;
566 :
567 0 : while (*unix_members) {
568 0 : if (strcmp(*unix_members, nt_member) == 0) {
569 0 : is_unix_member = true;
570 0 : break;
571 : }
572 0 : unix_members += 1;
573 : }
574 :
575 0 : if (!is_unix_member && mem->active) {
576 0 : smb_add_user_group(grp->gr_name, nt_member);
577 0 : } else if (is_unix_member && !mem->active) {
578 0 : smb_delete_user_group(grp->gr_name, nt_member);
579 : }
580 :
581 0 : return 0;
582 : }
583 :
584 0 : static int dssync_passdb_traverse_groups(struct db_record *rec,
585 : void *private_data)
586 : {
587 0 : struct dssync_passdb_traverse_groups *state =
588 : (struct dssync_passdb_traverse_groups *)private_data;
589 0 : struct dssync_passdb *pctx =
590 0 : talloc_get_type_abort(state->ctx->private_data,
591 : struct dssync_passdb);
592 0 : struct dssync_passdb_traverse_gmembers mstate;
593 0 : struct dssync_passdb_obj *obj;
594 0 : TDB_DATA value;
595 0 : NTSTATUS status;
596 :
597 0 : state->idx++;
598 0 : if (pctx->methods == NULL) {
599 0 : return -1;
600 : }
601 :
602 0 : value = dbwrap_record_get_value(rec);
603 :
604 0 : obj = dssync_parse_obj(value);
605 0 : if (obj == NULL) {
606 0 : return -1;
607 : }
608 :
609 0 : ZERO_STRUCT(mstate);
610 0 : mstate.ctx = state->ctx;
611 0 : mstate.name = "members";
612 0 : mstate.obj = obj;
613 0 : status = dbwrap_traverse_read(obj->members,
614 : dssync_passdb_traverse_gmembers,
615 : &mstate, NULL);
616 0 : if (!NT_STATUS_IS_OK(status)) {
617 0 : return -1;
618 : }
619 :
620 0 : return 0;
621 : }
622 :
623 0 : static NTSTATUS passdb_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
624 : struct replUpToDateVectorBlob *new_utdv)
625 : {
626 0 : struct dssync_passdb *pctx =
627 0 : talloc_get_type_abort(ctx->private_data,
628 : struct dssync_passdb);
629 0 : struct dssync_passdb_traverse_aliases astate;
630 0 : struct dssync_passdb_traverse_groups gstate;
631 0 : NTSTATUS status;
632 :
633 0 : ZERO_STRUCT(astate);
634 0 : astate.ctx = ctx;
635 0 : astate.name = "aliases";
636 0 : status = dbwrap_traverse_read(pctx->aliases,
637 : dssync_passdb_traverse_aliases,
638 : &astate, NULL);
639 0 : if (!NT_STATUS_IS_OK(status)) {
640 0 : return NT_STATUS_INTERNAL_ERROR;
641 : }
642 :
643 0 : ZERO_STRUCT(gstate);
644 0 : gstate.ctx = ctx;
645 0 : gstate.name = "groups";
646 0 : status = dbwrap_traverse_read(pctx->groups,
647 : dssync_passdb_traverse_groups,
648 : &gstate, NULL);
649 0 : if (!NT_STATUS_IS_OK(status)) {
650 0 : return NT_STATUS_INTERNAL_ERROR;
651 : }
652 :
653 0 : TALLOC_FREE(pctx->methods);
654 0 : TALLOC_FREE(pctx);
655 :
656 0 : return NT_STATUS_OK;
657 : }
658 :
659 : /****************************************************************
660 : ****************************************************************/
661 :
662 0 : static NTSTATUS smb_create_user(TALLOC_CTX *mem_ctx,
663 : uint32_t acct_flags,
664 : const char *account,
665 : struct passwd **passwd_p)
666 : {
667 0 : const struct loadparm_substitution *lp_sub =
668 0 : loadparm_s3_global_substitution();
669 0 : struct passwd *passwd;
670 0 : char *add_script = NULL;
671 :
672 0 : passwd = Get_Pwnam_alloc(mem_ctx, account);
673 0 : if (passwd) {
674 0 : *passwd_p = passwd;
675 0 : return NT_STATUS_OK;
676 : }
677 :
678 : /* Create appropriate user */
679 0 : if (acct_flags & ACB_NORMAL) {
680 0 : add_script = lp_add_user_script(mem_ctx, lp_sub);
681 0 : } else if ( (acct_flags & ACB_WSTRUST) ||
682 0 : (acct_flags & ACB_SVRTRUST) ||
683 0 : (acct_flags & ACB_DOMTRUST) ) {
684 0 : add_script = lp_add_machine_script(mem_ctx, lp_sub);
685 : } else {
686 0 : DEBUG(1, ("Unknown user type: %s\n",
687 : pdb_encode_acct_ctrl(acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
688 0 : return NT_STATUS_UNSUCCESSFUL;
689 : }
690 :
691 0 : if (!add_script) {
692 0 : return NT_STATUS_NO_MEMORY;
693 : }
694 :
695 0 : if (*add_script) {
696 0 : int add_ret;
697 0 : add_script = talloc_all_string_sub(mem_ctx, add_script,
698 : "%u", account);
699 0 : if (!add_script) {
700 0 : return NT_STATUS_NO_MEMORY;
701 : }
702 0 : add_ret = smbrun(add_script, NULL, NULL);
703 0 : DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
704 : "gave %d\n", add_script, add_ret));
705 0 : if (add_ret == 0) {
706 0 : smb_nscd_flush_user_cache();
707 : }
708 : }
709 :
710 : /* try and find the possible unix account again */
711 0 : passwd = Get_Pwnam_alloc(mem_ctx, account);
712 0 : if (!passwd) {
713 0 : return NT_STATUS_NO_SUCH_USER;
714 : }
715 :
716 0 : *passwd_p = passwd;
717 :
718 0 : return NT_STATUS_OK;
719 : }
720 :
721 0 : static struct drsuapi_DsReplicaAttribute *find_drsuapi_attr(
722 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
723 : uint32_t attid)
724 : {
725 0 : uint32_t i = 0;
726 :
727 0 : for (i = 0; i < cur->object.attribute_ctr.num_attributes; i++) {
728 0 : struct drsuapi_DsReplicaAttribute *attr;
729 :
730 0 : attr = &cur->object.attribute_ctr.attributes[i];
731 :
732 0 : if (attr->attid == attid) {
733 0 : return attr;
734 : }
735 : }
736 :
737 0 : return NULL;
738 : }
739 :
740 0 : static NTSTATUS find_drsuapi_attr_string(TALLOC_CTX *mem_ctx,
741 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
742 : uint32_t attid,
743 : uint32_t *_count,
744 : char ***_array)
745 : {
746 0 : struct drsuapi_DsReplicaAttribute *attr;
747 0 : char **array;
748 0 : uint32_t a;
749 :
750 0 : attr = find_drsuapi_attr(cur, attid);
751 0 : if (attr == NULL) {
752 0 : return NT_STATUS_PROPSET_NOT_FOUND;
753 : }
754 :
755 0 : array = talloc_array(mem_ctx, char *, attr->value_ctr.num_values);
756 0 : if (array == NULL) {
757 0 : return NT_STATUS_NO_MEMORY;
758 : }
759 :
760 0 : for (a = 0; a < attr->value_ctr.num_values; a++) {
761 0 : const DATA_BLOB *blob;
762 0 : ssize_t ret;
763 :
764 0 : blob = attr->value_ctr.values[a].blob;
765 :
766 0 : if (blob == NULL) {
767 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
768 : }
769 :
770 0 : ret = pull_string_talloc(array, NULL, 0, &array[a],
771 0 : blob->data, blob->length,
772 : STR_UNICODE);
773 0 : if (ret == -1) {
774 : //TODO
775 0 : return NT_STATUS_INTERNAL_ERROR;
776 : }
777 : }
778 :
779 0 : *_count = attr->value_ctr.num_values;
780 0 : *_array = array;
781 0 : return NT_STATUS_OK;
782 : }
783 :
784 0 : static NTSTATUS find_drsuapi_attr_int32(TALLOC_CTX *mem_ctx,
785 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
786 : uint32_t attid,
787 : uint32_t *_count,
788 : int32_t **_array)
789 : {
790 0 : struct drsuapi_DsReplicaAttribute *attr;
791 0 : int32_t *array;
792 0 : uint32_t a;
793 :
794 0 : attr = find_drsuapi_attr(cur, attid);
795 0 : if (attr == NULL) {
796 0 : return NT_STATUS_PROPSET_NOT_FOUND;
797 : }
798 :
799 0 : array = talloc_array(mem_ctx, int32_t, attr->value_ctr.num_values);
800 0 : if (array == NULL) {
801 0 : return NT_STATUS_NO_MEMORY;
802 : }
803 :
804 0 : for (a = 0; a < attr->value_ctr.num_values; a++) {
805 0 : const DATA_BLOB *blob;
806 :
807 0 : blob = attr->value_ctr.values[a].blob;
808 :
809 0 : if (blob == NULL) {
810 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
811 : }
812 :
813 0 : if (blob->length != 4) {
814 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
815 : }
816 :
817 0 : array[a] = IVAL(blob->data, 0);
818 : }
819 :
820 0 : *_count = attr->value_ctr.num_values;
821 0 : *_array = array;
822 0 : return NT_STATUS_OK;
823 : }
824 :
825 0 : static NTSTATUS find_drsuapi_attr_blob(TALLOC_CTX *mem_ctx,
826 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
827 : uint32_t attid,
828 : uint32_t *_count,
829 : DATA_BLOB **_array)
830 : {
831 0 : struct drsuapi_DsReplicaAttribute *attr;
832 0 : DATA_BLOB *array;
833 0 : uint32_t a;
834 :
835 0 : attr = find_drsuapi_attr(cur, attid);
836 0 : if (attr == NULL) {
837 0 : return NT_STATUS_PROPSET_NOT_FOUND;
838 : }
839 :
840 0 : array = talloc_array(mem_ctx, DATA_BLOB, attr->value_ctr.num_values);
841 0 : if (array == NULL) {
842 0 : return NT_STATUS_NO_MEMORY;
843 : }
844 :
845 0 : for (a = 0; a < attr->value_ctr.num_values; a++) {
846 0 : const DATA_BLOB *blob;
847 :
848 0 : blob = attr->value_ctr.values[a].blob;
849 :
850 0 : if (blob == NULL) {
851 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
852 : }
853 :
854 0 : array[a] = data_blob_talloc(array, blob->data, blob->length);
855 0 : if (array[a].length != blob->length) {
856 0 : return NT_STATUS_NO_MEMORY;
857 : }
858 : }
859 0 : *_count = attr->value_ctr.num_values;
860 0 : *_array = array;
861 0 : return NT_STATUS_OK;
862 : }
863 :
864 0 : static NTSTATUS find_drsuapi_attr_int64(TALLOC_CTX *mem_ctx,
865 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
866 : uint32_t attid,
867 : uint32_t *_count,
868 : int64_t **_array)
869 : {
870 0 : struct drsuapi_DsReplicaAttribute *attr;
871 0 : int64_t *array;
872 0 : uint32_t a;
873 :
874 0 : attr = find_drsuapi_attr(cur, attid);
875 0 : if (attr == NULL) {
876 0 : return NT_STATUS_PROPSET_NOT_FOUND;
877 : }
878 :
879 0 : array = talloc_array(mem_ctx, int64_t, attr->value_ctr.num_values);
880 0 : if (array == NULL) {
881 0 : return NT_STATUS_NO_MEMORY;
882 : }
883 :
884 0 : for (a = 0; a < attr->value_ctr.num_values; a++) {
885 0 : const DATA_BLOB *blob;
886 :
887 0 : blob = attr->value_ctr.values[a].blob;
888 :
889 0 : if (blob == NULL) {
890 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
891 : }
892 :
893 0 : if (blob->length != 8) {
894 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
895 : }
896 :
897 0 : array[a] = BVAL(blob->data, 0);
898 : }
899 0 : *_count = attr->value_ctr.num_values;
900 0 : *_array = array;
901 0 : return NT_STATUS_OK;
902 : }
903 :
904 0 : static NTSTATUS find_drsuapi_attr_dn(TALLOC_CTX *mem_ctx,
905 : const struct drsuapi_DsReplicaObjectListItemEx *cur,
906 : uint32_t attid,
907 : uint32_t *_count,
908 : struct drsuapi_DsReplicaObjectIdentifier3 **_array)
909 : {
910 0 : struct drsuapi_DsReplicaAttribute *attr;
911 0 : struct drsuapi_DsReplicaObjectIdentifier3 *array;
912 0 : uint32_t a;
913 :
914 0 : attr = find_drsuapi_attr(cur, attid);
915 0 : if (attr == NULL) {
916 0 : return NT_STATUS_PROPSET_NOT_FOUND;
917 : }
918 :
919 0 : array = talloc_array(mem_ctx,
920 : struct drsuapi_DsReplicaObjectIdentifier3,
921 : attr->value_ctr.num_values);
922 0 : if (array == NULL) {
923 0 : return NT_STATUS_NO_MEMORY;
924 : }
925 :
926 0 : for (a = 0; a < attr->value_ctr.num_values; a++) {
927 0 : const DATA_BLOB *blob;
928 0 : enum ndr_err_code ndr_err;
929 0 : NTSTATUS status;
930 :
931 0 : blob = attr->value_ctr.values[a].blob;
932 :
933 0 : if (blob == NULL) {
934 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
935 : }
936 :
937 : /* windows sometimes sends an extra two pad bytes here */
938 0 : ndr_err = ndr_pull_struct_blob(blob, array, &array[a],
939 : (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
940 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
941 0 : status = ndr_map_error2ntstatus(ndr_err);
942 0 : return status;
943 : }
944 : }
945 0 : *_count = attr->value_ctr.num_values;
946 0 : *_array = array;
947 0 : return NT_STATUS_OK;
948 : }
949 :
950 : #define GET_BLOB_EX(attr, needed) do { \
951 : NTSTATUS _status; \
952 : uint32_t _cnt; \
953 : DATA_BLOB *_vals = NULL; \
954 : attr = data_blob_null; \
955 : _status = find_drsuapi_attr_blob(mem_ctx, cur, \
956 : DRSUAPI_ATTID_ ## attr, \
957 : &_cnt, &_vals); \
958 : if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
959 : if (!needed) { \
960 : _status = NT_STATUS_OK; \
961 : _cnt = 0; \
962 : } \
963 : } \
964 : if (!NT_STATUS_IS_OK(_status)) { \
965 : DEBUG(0,(__location__ "attr[%s] %s\n", \
966 : #attr, nt_errstr(_status))); \
967 : return _status; \
968 : } \
969 : if (_cnt == 0) { \
970 : if (needed) { \
971 : talloc_free(_vals); \
972 : DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
973 : return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
974 : } \
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; \
979 : } else { \
980 : attr = _vals[0]; \
981 : (void)talloc_steal(mem_ctx, _vals[0].data); \
982 : } \
983 : talloc_free(_vals); \
984 : } while(0)
985 :
986 : #define GET_STRING_EX(attr, needed) do { \
987 : NTSTATUS _status; \
988 : uint32_t _cnt; \
989 : char **_vals = NULL; \
990 : attr = NULL; \
991 : _status = find_drsuapi_attr_string(mem_ctx, cur, \
992 : DRSUAPI_ATTID_ ## attr, \
993 : &_cnt, &_vals); \
994 : if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
995 : if (!needed) { \
996 : _status = NT_STATUS_OK; \
997 : _cnt = 0; \
998 : } \
999 : } \
1000 : if (!NT_STATUS_IS_OK(_status)) { \
1001 : DEBUG(0,(__location__ "attr[%s] %s\n", \
1002 : #attr, nt_errstr(_status))); \
1003 : return _status; \
1004 : } \
1005 : if (_cnt == 0) { \
1006 : if (needed) { \
1007 : talloc_free(_vals); \
1008 : DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1009 : return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1010 : } \
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; \
1015 : } else { \
1016 : attr = talloc_move(mem_ctx, &_vals[0]); \
1017 : } \
1018 : talloc_free(_vals); \
1019 : } while(0)
1020 :
1021 : #define GET_UINT32_EX(attr, needed) do { \
1022 : NTSTATUS _status; \
1023 : uint32_t _cnt; \
1024 : int32_t*_vals = NULL; \
1025 : attr = 0; \
1026 : _status = find_drsuapi_attr_int32(mem_ctx, cur, \
1027 : DRSUAPI_ATTID_ ## attr, \
1028 : &_cnt, &_vals); \
1029 : if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1030 : if (!needed) { \
1031 : _status = NT_STATUS_OK; \
1032 : _cnt = 0; \
1033 : } \
1034 : } \
1035 : if (!NT_STATUS_IS_OK(_status)) { \
1036 : DEBUG(0,(__location__ "attr[%s] %s\n", \
1037 : #attr, nt_errstr(_status))); \
1038 : return _status; \
1039 : } \
1040 : if (_cnt == 0) { \
1041 : if (needed) { \
1042 : talloc_free(_vals); \
1043 : DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1044 : return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1045 : } \
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; \
1050 : } else { \
1051 : attr = (uint32_t)_vals[0]; \
1052 : } \
1053 : talloc_free(_vals); \
1054 : } while(0)
1055 :
1056 : #define GET_UINT64_EX(attr, needed) do { \
1057 : NTSTATUS _status; \
1058 : uint32_t _cnt; \
1059 : int64_t *_vals = NULL; \
1060 : attr = 0; \
1061 : _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1062 : DRSUAPI_ATTID_ ## attr, \
1063 : &_cnt, &_vals); \
1064 : if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1065 : if (!needed) { \
1066 : _status = NT_STATUS_OK; \
1067 : _cnt = 0; \
1068 : } \
1069 : } \
1070 : if (!NT_STATUS_IS_OK(_status)) { \
1071 : DEBUG(0,(__location__ "attr[%s] %s\n", \
1072 : #attr, nt_errstr(_status))); \
1073 : return _status; \
1074 : } \
1075 : if (_cnt == 0) { \
1076 : if (needed) { \
1077 : talloc_free(_vals); \
1078 : DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1079 : return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1080 : } \
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; \
1085 : } else { \
1086 : attr = (uint64_t)_vals[0]; \
1087 : } \
1088 : talloc_free(_vals); \
1089 : } while(0)
1090 :
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)
1095 :
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))
1100 :
1101 : #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1102 : (!(s1) && (s2)) ||\
1103 : ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1104 :
1105 : /****************************************************************
1106 : ****************************************************************/
1107 :
1108 0 : static NTSTATUS sam_account_from_object(struct samu *account,
1109 : struct drsuapi_DsReplicaObjectListItemEx *cur)
1110 : {
1111 0 : TALLOC_CTX *mem_ctx = account;
1112 0 : const char *old_string, *new_string;
1113 0 : struct dom_sid_buf buf;
1114 0 : time_t unix_time, stored_time;
1115 0 : NTSTATUS status;
1116 :
1117 0 : NTTIME lastLogon;
1118 0 : NTTIME lastLogoff;
1119 0 : NTTIME pwdLastSet;
1120 0 : NTTIME accountExpires;
1121 0 : const char *sAMAccountName;
1122 0 : const char *displayName;
1123 0 : const char *homeDirectory;
1124 0 : const char *homeDrive;
1125 0 : const char *scriptPath;
1126 0 : const char *profilePath;
1127 0 : const char *description;
1128 0 : const char *userWorkstations;
1129 0 : DATA_BLOB userParameters;
1130 0 : struct dom_sid objectSid;
1131 0 : uint32_t primaryGroupID;
1132 0 : uint32_t userAccountControl;
1133 0 : DATA_BLOB logonHours;
1134 0 : uint32_t badPwdCount;
1135 0 : uint32_t logonCount;
1136 0 : DATA_BLOB unicodePwd;
1137 0 : DATA_BLOB dBCSPwd;
1138 :
1139 0 : uint32_t rid = 0;
1140 0 : uint32_t acct_flags;
1141 0 : uint32_t units_per_week;
1142 :
1143 0 : objectSid = cur->object.identifier->sid;
1144 0 : GET_STRING_EX(sAMAccountName, true);
1145 0 : DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1146 : sAMAccountName,
1147 : dom_sid_str_buf(&objectSid, &buf)));
1148 0 : GET_UINT64(lastLogon);
1149 0 : GET_UINT64(lastLogoff);
1150 0 : GET_UINT64(pwdLastSet);
1151 0 : GET_UINT64(accountExpires);
1152 0 : GET_STRING(displayName);
1153 0 : GET_STRING(homeDirectory);
1154 0 : GET_STRING(homeDrive);
1155 0 : GET_STRING(scriptPath);
1156 0 : GET_STRING(profilePath);
1157 0 : GET_STRING(description);
1158 0 : GET_STRING(userWorkstations);
1159 0 : GET_BLOB(userParameters);
1160 0 : GET_UINT32(primaryGroupID);
1161 0 : GET_UINT32(userAccountControl);
1162 0 : GET_BLOB(logonHours);
1163 0 : GET_UINT32(badPwdCount);
1164 0 : GET_UINT32(logonCount);
1165 0 : GET_BLOB(unicodePwd);
1166 0 : GET_BLOB(dBCSPwd);
1167 :
1168 0 : status = dom_sid_split_rid(mem_ctx, &objectSid, NULL, &rid);
1169 0 : if (!NT_STATUS_IS_OK(status)) {
1170 0 : return status;
1171 : }
1172 0 : acct_flags = ds_uf2acb(userAccountControl);
1173 :
1174 : /* Username, fullname, home dir, dir drive, logon script, acct
1175 : desc, workstations, profile. */
1176 :
1177 0 : if (sAMAccountName) {
1178 0 : old_string = pdb_get_nt_username(account);
1179 0 : new_string = sAMAccountName;
1180 :
1181 0 : if (STRING_CHANGED) {
1182 0 : pdb_set_nt_username(account, new_string, PDB_CHANGED);
1183 : }
1184 :
1185 : /* Unix username is the same - for sanity */
1186 0 : old_string = pdb_get_username( account );
1187 0 : if (STRING_CHANGED) {
1188 0 : pdb_set_username(account, new_string, PDB_CHANGED);
1189 : }
1190 : }
1191 :
1192 0 : if (displayName) {
1193 0 : old_string = pdb_get_fullname(account);
1194 0 : new_string = displayName;
1195 :
1196 0 : if (STRING_CHANGED)
1197 0 : pdb_set_fullname(account, new_string, PDB_CHANGED);
1198 : }
1199 :
1200 0 : if (homeDirectory) {
1201 0 : old_string = pdb_get_homedir(account);
1202 0 : new_string = homeDirectory;
1203 :
1204 0 : if (STRING_CHANGED)
1205 0 : pdb_set_homedir(account, new_string, PDB_CHANGED);
1206 : }
1207 :
1208 0 : if (homeDrive) {
1209 0 : old_string = pdb_get_dir_drive(account);
1210 0 : new_string = homeDrive;
1211 :
1212 0 : if (STRING_CHANGED)
1213 0 : pdb_set_dir_drive(account, new_string, PDB_CHANGED);
1214 : }
1215 :
1216 0 : if (scriptPath) {
1217 0 : old_string = pdb_get_logon_script(account);
1218 0 : new_string = scriptPath;
1219 :
1220 0 : if (STRING_CHANGED)
1221 0 : pdb_set_logon_script(account, new_string, PDB_CHANGED);
1222 : }
1223 :
1224 0 : if (description) {
1225 0 : old_string = pdb_get_acct_desc(account);
1226 0 : new_string = description;
1227 :
1228 0 : if (STRING_CHANGED)
1229 0 : pdb_set_acct_desc(account, new_string, PDB_CHANGED);
1230 : }
1231 :
1232 0 : if (userWorkstations) {
1233 0 : old_string = pdb_get_workstations(account);
1234 0 : new_string = userWorkstations;
1235 :
1236 0 : if (STRING_CHANGED)
1237 0 : pdb_set_workstations(account, new_string, PDB_CHANGED);
1238 : }
1239 :
1240 0 : if (profilePath) {
1241 0 : old_string = pdb_get_profile_path(account);
1242 0 : new_string = profilePath;
1243 :
1244 0 : if (STRING_CHANGED)
1245 0 : pdb_set_profile_path(account, new_string, PDB_CHANGED);
1246 : }
1247 :
1248 0 : if (userParameters.data) {
1249 0 : char *newstr = NULL;
1250 0 : old_string = pdb_get_munged_dial(account);
1251 :
1252 0 : if (userParameters.length != 0) {
1253 0 : newstr = base64_encode_data_blob(talloc_tos(),
1254 : userParameters);
1255 0 : SMB_ASSERT(newstr != NULL);
1256 : }
1257 :
1258 0 : if (STRING_CHANGED_NC(old_string, newstr))
1259 0 : pdb_set_munged_dial(account, newstr, PDB_CHANGED);
1260 0 : TALLOC_FREE(newstr);
1261 : }
1262 :
1263 : /* User and group sid */
1264 0 : if (rid != 0 && pdb_get_user_rid(account) != rid) {
1265 0 : pdb_set_user_sid_from_rid(account, rid, PDB_CHANGED);
1266 : }
1267 0 : if (primaryGroupID != 0 && pdb_get_group_rid(account) != primaryGroupID) {
1268 0 : pdb_set_group_sid_from_rid(account, primaryGroupID, PDB_CHANGED);
1269 : }
1270 :
1271 : /* Logon and password information */
1272 0 : if (!nt_time_is_zero(&lastLogon)) {
1273 0 : unix_time = nt_time_to_unix(lastLogon);
1274 0 : stored_time = pdb_get_logon_time(account);
1275 0 : if (stored_time != unix_time)
1276 0 : pdb_set_logon_time(account, unix_time, PDB_CHANGED);
1277 : }
1278 :
1279 0 : if (!nt_time_is_zero(&lastLogoff)) {
1280 0 : unix_time = nt_time_to_unix(lastLogoff);
1281 0 : stored_time = pdb_get_logoff_time(account);
1282 0 : if (stored_time != unix_time)
1283 0 : pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
1284 : }
1285 :
1286 : /* Logon Divs */
1287 0 : units_per_week = logonHours.length * 8;
1288 :
1289 0 : if (pdb_get_logon_divs(account) != units_per_week) {
1290 0 : pdb_set_logon_divs(account, units_per_week, PDB_CHANGED);
1291 : }
1292 :
1293 : /* Logon Hours Len */
1294 0 : if (units_per_week/8 != pdb_get_hours_len(account)) {
1295 0 : pdb_set_hours_len(account, units_per_week/8, PDB_CHANGED);
1296 : }
1297 :
1298 : /* Logon Hours */
1299 0 : if (logonHours.data) {
1300 0 : char oldstr[44], newstr[44];
1301 0 : pdb_sethexhours(oldstr, pdb_get_hours(account));
1302 0 : pdb_sethexhours(newstr, logonHours.data);
1303 0 : if (!strequal(oldstr, newstr)) {
1304 0 : pdb_set_hours(account, logonHours.data,
1305 0 : logonHours.length, PDB_CHANGED);
1306 : }
1307 : }
1308 :
1309 0 : if (pdb_get_bad_password_count(account) != badPwdCount)
1310 0 : pdb_set_bad_password_count(account, badPwdCount, PDB_CHANGED);
1311 :
1312 0 : if (pdb_get_logon_count(account) != logonCount)
1313 0 : pdb_set_logon_count(account, logonCount, PDB_CHANGED);
1314 :
1315 0 : if (!nt_time_is_zero(&pwdLastSet)) {
1316 0 : unix_time = nt_time_to_unix(pwdLastSet);
1317 0 : stored_time = pdb_get_pass_last_set_time(account);
1318 0 : if (stored_time != unix_time)
1319 0 : pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
1320 : } else {
1321 : /* no last set time, make it now */
1322 0 : pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED);
1323 : }
1324 :
1325 0 : if (!nt_time_is_zero(&accountExpires)) {
1326 0 : unix_time = nt_time_to_unix(accountExpires);
1327 0 : stored_time = pdb_get_kickoff_time(account);
1328 0 : if (stored_time != unix_time)
1329 0 : pdb_set_kickoff_time(account, unix_time, PDB_CHANGED);
1330 : }
1331 :
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
1335 : in that case
1336 : */
1337 0 : if (dBCSPwd.length == 16 && !all_zero(dBCSPwd.data, 16)) {
1338 0 : pdb_set_lanman_passwd(account, dBCSPwd.data, PDB_CHANGED);
1339 : }
1340 :
1341 0 : if (unicodePwd.length == 16 && !all_zero(unicodePwd.data, 16)) {
1342 0 : pdb_set_nt_passwd(account, unicodePwd.data, PDB_CHANGED);
1343 : }
1344 :
1345 : /* TODO: history */
1346 :
1347 : /* TODO: account expiry time */
1348 :
1349 0 : pdb_set_acct_ctrl(account, acct_flags, PDB_CHANGED);
1350 :
1351 0 : pdb_set_domain(account, lp_workgroup(), PDB_CHANGED);
1352 :
1353 0 : DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1354 : sAMAccountName,
1355 : dom_sid_str_buf(&objectSid, &buf)));
1356 0 : return NT_STATUS_OK;
1357 : }
1358 :
1359 : /****************************************************************
1360 : ****************************************************************/
1361 :
1362 0 : static NTSTATUS handle_account_object(struct dssync_passdb *pctx,
1363 : TALLOC_CTX *mem_ctx,
1364 : struct dssync_passdb_obj *obj)
1365 : {
1366 0 : struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
1367 0 : NTSTATUS status;
1368 0 : fstring account;
1369 0 : struct samu *sam_account=NULL;
1370 0 : GROUP_MAP *map;
1371 0 : struct group *grp;
1372 0 : struct dom_sid user_sid;
1373 0 : struct dom_sid group_sid;
1374 0 : struct dom_sid_buf buf;
1375 0 : struct passwd *passwd = NULL;
1376 0 : uint32_t acct_flags;
1377 0 : uint32_t rid;
1378 :
1379 0 : const char *sAMAccountName;
1380 0 : uint32_t userAccountControl;
1381 :
1382 0 : user_sid = cur->object.identifier->sid;
1383 0 : GET_STRING_EX(sAMAccountName, true);
1384 0 : GET_UINT32_EX(userAccountControl, true);
1385 :
1386 0 : status = dom_sid_split_rid(mem_ctx, &user_sid, NULL, &rid);
1387 0 : if (!NT_STATUS_IS_OK(status)) {
1388 0 : return status;
1389 : }
1390 :
1391 0 : fstrcpy(account, sAMAccountName);
1392 0 : if (rid == DOMAIN_RID_GUEST) {
1393 : /*
1394 : * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1395 : * that's why we need to ignore it here.
1396 : *
1397 : * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1398 : * code...
1399 : */
1400 0 : DEBUG(0,("Ignore %s - %s\n",
1401 : account,
1402 : dom_sid_str_buf(&user_sid, &buf)));
1403 0 : return NT_STATUS_OK;
1404 : }
1405 0 : DEBUG(0,("Creating account: %s\n", account));
1406 :
1407 0 : if ( !(sam_account = samu_new(mem_ctx)) ) {
1408 0 : return NT_STATUS_NO_MEMORY;
1409 : }
1410 :
1411 0 : acct_flags = ds_uf2acb(userAccountControl);
1412 0 : status = smb_create_user(sam_account, acct_flags, account, &passwd);
1413 0 : if (!NT_STATUS_IS_OK(status)) {
1414 0 : DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1415 : account, nt_errstr(status)));
1416 0 : TALLOC_FREE(sam_account);
1417 0 : return status;
1418 : }
1419 :
1420 0 : DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1421 : dom_sid_str_buf(&user_sid, &buf),
1422 : account));
1423 0 : if (!pdb_getsampwsid(sam_account, &user_sid)) {
1424 0 : sam_account_from_object(sam_account, cur);
1425 0 : 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 0 : if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account))) {
1429 0 : DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1430 : account));
1431 0 : TALLOC_FREE(sam_account);
1432 0 : return NT_STATUS_ACCESS_DENIED;
1433 : }
1434 : } else {
1435 0 : sam_account_from_object(sam_account, cur);
1436 0 : 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 0 : if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account))) {
1440 0 : DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1441 : account));
1442 0 : TALLOC_FREE(sam_account);
1443 0 : return NT_STATUS_ACCESS_DENIED;
1444 : }
1445 : }
1446 :
1447 0 : if (pdb_get_group_sid(sam_account) == NULL) {
1448 0 : TALLOC_FREE(sam_account);
1449 0 : return NT_STATUS_UNSUCCESSFUL;
1450 : }
1451 :
1452 0 : group_sid = *pdb_get_group_sid(sam_account);
1453 :
1454 0 : map = talloc_zero(NULL, GROUP_MAP);
1455 0 : if (!map) {
1456 0 : return NT_STATUS_NO_MEMORY;
1457 : }
1458 :
1459 0 : if (!pdb_getgrsid(map, group_sid)) {
1460 0 : DEBUG(0, ("Primary group of %s has no mapping!\n",
1461 : pdb_get_username(sam_account)));
1462 : } else {
1463 0 : if (map->gid != passwd->pw_gid) {
1464 0 : if (!(grp = getgrgid(map->gid))) {
1465 0 : 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)));
1468 : } else {
1469 0 : smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
1470 : }
1471 : }
1472 : }
1473 :
1474 0 : TALLOC_FREE(map);
1475 :
1476 0 : if ( !passwd ) {
1477 0 : DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1478 : pdb_get_username(sam_account)));
1479 : }
1480 :
1481 0 : TALLOC_FREE(sam_account);
1482 0 : return NT_STATUS_OK;
1483 : }
1484 :
1485 : /****************************************************************
1486 : ****************************************************************/
1487 :
1488 0 : static NTSTATUS handle_alias_object(struct dssync_passdb *pctx,
1489 : TALLOC_CTX *mem_ctx,
1490 : struct dssync_passdb_obj *obj)
1491 : {
1492 0 : struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
1493 0 : NTSTATUS status;
1494 0 : struct group *grp = NULL;
1495 0 : struct dom_sid group_sid;
1496 0 : uint32_t rid = 0;
1497 0 : struct dom_sid *dom_sid = NULL;
1498 0 : struct dom_sid_buf sid_str;
1499 0 : GROUP_MAP *map;
1500 0 : bool insert = true;
1501 :
1502 0 : const char *sAMAccountName;
1503 0 : const char *description;
1504 0 : uint32_t i;
1505 0 : uint32_t num_members = 0;
1506 0 : struct drsuapi_DsReplicaObjectIdentifier3 *members = NULL;
1507 :
1508 0 : group_sid = cur->object.identifier->sid;
1509 0 : GET_STRING_EX(sAMAccountName, true);
1510 0 : GET_STRING(description);
1511 :
1512 0 : status = find_drsuapi_attr_dn(obj, cur, DRSUAPI_ATTID_member,
1513 : &num_members, &members);
1514 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_PROPSET_NOT_FOUND)) {
1515 0 : status = NT_STATUS_OK;
1516 : }
1517 0 : if (!NT_STATUS_IS_OK(status)) {
1518 0 : return status;
1519 : }
1520 :
1521 0 : dom_sid_split_rid(mem_ctx, &group_sid, &dom_sid, &rid);
1522 :
1523 0 : map = talloc_zero(mem_ctx, GROUP_MAP);
1524 0 : if (map == NULL) {
1525 0 : status = NT_STATUS_NO_MEMORY;
1526 0 : goto done;
1527 : }
1528 :
1529 0 : map->nt_name = talloc_strdup(map, sAMAccountName);
1530 0 : if (map->nt_name == NULL) {
1531 0 : status = NT_STATUS_NO_MEMORY;
1532 0 : goto done;
1533 : }
1534 :
1535 0 : if (description) {
1536 0 : map->comment = talloc_strdup(map, description);
1537 : } else {
1538 0 : map->comment = talloc_strdup(map, "");
1539 : }
1540 0 : if (map->comment == NULL) {
1541 0 : status = NT_STATUS_NO_MEMORY;
1542 0 : goto done;
1543 : }
1544 :
1545 0 : DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1546 : map->nt_name,
1547 : dom_sid_str_buf(&group_sid, &sid_str),
1548 : num_members));
1549 :
1550 0 : status = dssync_insert_obj(pctx, pctx->aliases, obj);
1551 0 : if (!NT_STATUS_IS_OK(status)) {
1552 0 : goto done;
1553 : }
1554 :
1555 0 : if (pdb_getgrsid(map, group_sid)) {
1556 0 : if (map->gid != -1) {
1557 0 : grp = getgrgid(map->gid);
1558 : }
1559 0 : insert = false;
1560 : }
1561 :
1562 0 : if (grp == NULL) {
1563 0 : gid_t gid;
1564 :
1565 : /* No group found from mapping, find it from its name. */
1566 0 : if ((grp = getgrnam(map->nt_name)) == NULL) {
1567 :
1568 : /* No appropriate group found, create one */
1569 :
1570 0 : DEBUG(0, ("Creating unix group: '%s'\n",
1571 : map->nt_name));
1572 :
1573 0 : if (smb_create_group(map->nt_name, &gid) != 0) {
1574 0 : status = NT_STATUS_ACCESS_DENIED;
1575 0 : goto done;
1576 : }
1577 :
1578 0 : if ((grp = getgrgid(gid)) == NULL) {
1579 0 : status = NT_STATUS_ACCESS_DENIED;
1580 0 : goto done;
1581 : }
1582 : }
1583 : }
1584 :
1585 0 : map->gid = grp->gr_gid;
1586 0 : map->sid = group_sid;
1587 :
1588 0 : if (dom_sid_equal(dom_sid, &global_sid_Builtin)) {
1589 : /*
1590 : * pdb_ldap does not like SID_NAME_WKN_GRP...
1591 : *
1592 : * map.sid_name_use = SID_NAME_WKN_GRP;
1593 : */
1594 0 : map->sid_name_use = SID_NAME_ALIAS;
1595 : } else {
1596 0 : map->sid_name_use = SID_NAME_ALIAS;
1597 : }
1598 :
1599 0 : if (insert) {
1600 0 : pdb_add_group_mapping_entry(map);
1601 : } else {
1602 0 : pdb_update_group_mapping_entry(map);
1603 : }
1604 :
1605 0 : for (i=0; i < num_members; i++) {
1606 0 : struct dssync_passdb_mem *mem;
1607 :
1608 0 : status = dssync_create_mem(pctx, obj,
1609 : true /* active */,
1610 0 : &members[i], &mem);
1611 0 : if (!NT_STATUS_IS_OK(status)) {
1612 0 : goto done;
1613 : }
1614 : }
1615 :
1616 0 : status = NT_STATUS_OK;
1617 :
1618 0 : done:
1619 0 : TALLOC_FREE(map);
1620 0 : return status;
1621 : }
1622 :
1623 : /****************************************************************
1624 : ****************************************************************/
1625 :
1626 0 : static NTSTATUS handle_group_object(struct dssync_passdb *pctx,
1627 : TALLOC_CTX *mem_ctx,
1628 : struct dssync_passdb_obj *obj)
1629 : {
1630 0 : struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
1631 0 : NTSTATUS status;
1632 0 : struct group *grp = NULL;
1633 0 : struct dom_sid group_sid;
1634 0 : struct dom_sid_buf sid_str;
1635 0 : GROUP_MAP *map;
1636 0 : bool insert = true;
1637 :
1638 0 : const char *sAMAccountName;
1639 0 : const char *description;
1640 0 : uint32_t i;
1641 0 : uint32_t num_members = 0;
1642 0 : struct drsuapi_DsReplicaObjectIdentifier3 *members = NULL;
1643 :
1644 0 : group_sid = cur->object.identifier->sid;
1645 0 : GET_STRING_EX(sAMAccountName, true);
1646 0 : GET_STRING(description);
1647 :
1648 0 : status = find_drsuapi_attr_dn(obj, cur, DRSUAPI_ATTID_member,
1649 : &num_members, &members);
1650 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_PROPSET_NOT_FOUND)) {
1651 0 : status = NT_STATUS_OK;
1652 : }
1653 0 : if (!NT_STATUS_IS_OK(status)) {
1654 0 : return status;
1655 : }
1656 :
1657 0 : map = talloc_zero(NULL, GROUP_MAP);
1658 0 : if (!map) {
1659 0 : return NT_STATUS_NO_MEMORY;
1660 : }
1661 :
1662 0 : map->nt_name = talloc_strdup(map, sAMAccountName);
1663 0 : if (!map->nt_name) {
1664 0 : status = NT_STATUS_NO_MEMORY;
1665 0 : goto done;
1666 : }
1667 0 : if (description) {
1668 0 : map->comment = talloc_strdup(map, description);
1669 : } else {
1670 0 : map->comment = talloc_strdup(map, "");
1671 : }
1672 0 : if (!map->comment) {
1673 0 : status = NT_STATUS_NO_MEMORY;
1674 0 : goto done;
1675 : }
1676 :
1677 0 : DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1678 : map->nt_name,
1679 : dom_sid_str_buf(&group_sid, &sid_str),
1680 : num_members));
1681 :
1682 0 : status = dssync_insert_obj(pctx, pctx->groups, obj);
1683 0 : if (!NT_STATUS_IS_OK(status)) {
1684 0 : goto done;
1685 : }
1686 :
1687 0 : if (pdb_getgrsid(map, group_sid)) {
1688 0 : if (map->gid != -1) {
1689 0 : grp = getgrgid(map->gid);
1690 : }
1691 0 : insert = false;
1692 : }
1693 :
1694 0 : if (grp == NULL) {
1695 0 : gid_t gid;
1696 :
1697 : /* No group found from mapping, find it from its name. */
1698 0 : if ((grp = getgrnam(map->nt_name)) == NULL) {
1699 :
1700 : /* No appropriate group found, create one */
1701 :
1702 0 : DEBUG(0, ("Creating unix group: '%s'\n",
1703 : map->nt_name));
1704 :
1705 0 : if (smb_create_group(map->nt_name, &gid) != 0) {
1706 0 : status = NT_STATUS_ACCESS_DENIED;
1707 0 : goto done;
1708 : }
1709 :
1710 0 : if ((grp = getgrnam(map->nt_name)) == NULL) {
1711 0 : status = NT_STATUS_ACCESS_DENIED;
1712 0 : goto done;
1713 : }
1714 : }
1715 : }
1716 :
1717 0 : map->gid = grp->gr_gid;
1718 0 : map->sid = group_sid;
1719 0 : map->sid_name_use = SID_NAME_DOM_GRP;
1720 :
1721 0 : if (insert) {
1722 0 : pdb_add_group_mapping_entry(map);
1723 : } else {
1724 0 : pdb_update_group_mapping_entry(map);
1725 : }
1726 :
1727 0 : for (i=0; i < num_members; i++) {
1728 0 : struct dssync_passdb_mem *mem;
1729 :
1730 0 : status = dssync_create_mem(pctx, obj,
1731 : true /* active */,
1732 0 : &members[i], &mem);
1733 0 : if (!NT_STATUS_IS_OK(status)) {
1734 0 : goto done;
1735 : }
1736 : }
1737 :
1738 0 : status = NT_STATUS_OK;
1739 :
1740 0 : done:
1741 0 : TALLOC_FREE(map);
1742 0 : return status;
1743 : }
1744 :
1745 : /****************************************************************
1746 : ****************************************************************/
1747 :
1748 0 : static NTSTATUS handle_interdomain_trust_object(struct dssync_passdb *pctx,
1749 : TALLOC_CTX *mem_ctx,
1750 : struct dssync_passdb_obj *obj)
1751 : {
1752 0 : struct drsuapi_DsReplicaObjectListItemEx *cur = obj->cur;
1753 0 : DEBUG(0,("trust: %s\n", cur->object.identifier->dn));
1754 0 : return NT_STATUS_NOT_IMPLEMENTED;
1755 : }
1756 :
1757 : /****************************************************************
1758 : ****************************************************************/
1759 :
1760 : struct dssync_object_table_t {
1761 : uint32_t type;
1762 : NTSTATUS (*fn) (struct dssync_passdb *pctx,
1763 : TALLOC_CTX *mem_ctx,
1764 : struct dssync_passdb_obj *obj);
1765 : };
1766 :
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 },
1773 : };
1774 :
1775 : /****************************************************************
1776 : ****************************************************************/
1777 :
1778 0 : static NTSTATUS parse_object(struct dssync_passdb *pctx,
1779 : TALLOC_CTX *mem_ctx,
1780 : struct drsuapi_DsReplicaObjectListItemEx *cur)
1781 : {
1782 0 : NTSTATUS status = NT_STATUS_OK;
1783 0 : DATA_BLOB *blob = NULL;
1784 0 : uint32_t i = 0;
1785 0 : size_t a = 0;
1786 :
1787 0 : char *name = NULL;
1788 0 : uint32_t sam_type = 0;
1789 :
1790 0 : DEBUG(3, ("parsing object '%s'\n", cur->object.identifier->dn));
1791 :
1792 0 : for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
1793 0 : struct drsuapi_DsReplicaAttribute *attr =
1794 0 : &cur->object.attribute_ctr.attributes[i];
1795 :
1796 0 : if (attr->value_ctr.num_values != 1) {
1797 0 : continue;
1798 : }
1799 :
1800 0 : if (!attr->value_ctr.values[0].blob) {
1801 0 : continue;
1802 : }
1803 :
1804 0 : blob = attr->value_ctr.values[0].blob;
1805 :
1806 0 : switch (attr->attid) {
1807 0 : case DRSUAPI_ATTID_sAMAccountName:
1808 0 : pull_string_talloc(mem_ctx, NULL, 0, &name,
1809 0 : blob->data, blob->length,
1810 : STR_UNICODE);
1811 0 : break;
1812 0 : case DRSUAPI_ATTID_sAMAccountType:
1813 0 : sam_type = IVAL(blob->data, 0);
1814 0 : break;
1815 0 : default:
1816 0 : break;
1817 : }
1818 : }
1819 :
1820 0 : for (a=0; a < ARRAY_SIZE(dssync_object_table); a++) {
1821 0 : if (sam_type == dssync_object_table[a].type) {
1822 0 : if (dssync_object_table[a].fn) {
1823 0 : struct dssync_passdb_obj *obj = NULL;
1824 0 : status = dssync_create_obj(pctx, pctx->all,
1825 : sam_type, cur, &obj);
1826 0 : if (!NT_STATUS_IS_OK(status)) {
1827 0 : break;
1828 : }
1829 0 : status = dssync_object_table[a].fn(pctx,
1830 : mem_ctx,
1831 : obj);
1832 0 : break;
1833 : }
1834 : }
1835 : }
1836 :
1837 0 : return status;
1838 : }
1839 :
1840 0 : static NTSTATUS parse_link(struct dssync_passdb *pctx,
1841 : TALLOC_CTX *mem_ctx,
1842 : struct drsuapi_DsReplicaLinkedAttribute *cur)
1843 : {
1844 0 : struct drsuapi_DsReplicaObjectIdentifier3 *id3;
1845 0 : const DATA_BLOB *blob;
1846 0 : enum ndr_err_code ndr_err;
1847 0 : NTSTATUS status;
1848 0 : bool active = false;
1849 0 : struct dssync_passdb_mem *mem;
1850 0 : struct dssync_passdb_obj *obj;
1851 :
1852 0 : if (cur->attid != DRSUAPI_ATTID_member) {
1853 0 : return NT_STATUS_OK;
1854 : }
1855 :
1856 0 : if (cur->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) {
1857 0 : active = true;
1858 : }
1859 :
1860 0 : DEBUG(3, ("parsing link '%s' - %s\n",
1861 : cur->identifier->dn, active?"adding":"deleting"));
1862 :
1863 0 : blob = cur->value.blob;
1864 :
1865 0 : if (blob == NULL) {
1866 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1867 : }
1868 :
1869 0 : obj = dssync_search_obj_by_guid(pctx, pctx->all, &cur->identifier->guid);
1870 0 : if (obj == NULL) {
1871 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1872 : }
1873 :
1874 0 : id3 = talloc_zero(obj, struct drsuapi_DsReplicaObjectIdentifier3);
1875 0 : if (id3 == NULL) {
1876 0 : return NT_STATUS_NO_MEMORY;
1877 : }
1878 :
1879 : /* windows sometimes sends an extra two pad bytes here */
1880 0 : ndr_err = ndr_pull_struct_blob(blob, id3, id3,
1881 : (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1882 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1883 0 : status = ndr_map_error2ntstatus(ndr_err);
1884 0 : return status;
1885 : }
1886 :
1887 0 : status = dssync_create_mem(pctx, obj,
1888 : active,
1889 : id3, &mem);
1890 0 : if (!NT_STATUS_IS_OK(status)) {
1891 0 : return status;
1892 : }
1893 :
1894 0 : return NT_STATUS_OK;
1895 : }
1896 :
1897 : /****************************************************************
1898 : ****************************************************************/
1899 :
1900 0 : 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)
1904 : {
1905 0 : NTSTATUS status = NT_STATUS_OK;
1906 0 : struct dssync_passdb *pctx =
1907 0 : talloc_get_type_abort(ctx->private_data,
1908 : struct dssync_passdb);
1909 :
1910 0 : for (; cur; cur = cur->next_object) {
1911 0 : status = parse_object(pctx, mem_ctx, cur);
1912 0 : if (!NT_STATUS_IS_OK(status)) {
1913 0 : goto out;
1914 : }
1915 : }
1916 :
1917 0 : out:
1918 0 : return status;
1919 : }
1920 :
1921 : /****************************************************************
1922 : ****************************************************************/
1923 :
1924 0 : static NTSTATUS passdb_process_links(struct dssync_context *ctx,
1925 : TALLOC_CTX *mem_ctx,
1926 : uint32_t count,
1927 : struct drsuapi_DsReplicaLinkedAttribute *links,
1928 : struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr)
1929 : {
1930 0 : NTSTATUS status = NT_STATUS_OK;
1931 0 : struct dssync_passdb *pctx =
1932 0 : talloc_get_type_abort(ctx->private_data,
1933 : struct dssync_passdb);
1934 0 : uint32_t i;
1935 :
1936 0 : for (i = 0; i < count; i++) {
1937 0 : status = parse_link(pctx, mem_ctx, &links[i]);
1938 0 : if (!NT_STATUS_IS_OK(status)) {
1939 0 : goto out;
1940 : }
1941 : }
1942 :
1943 0 : out:
1944 0 : return status;
1945 : }
1946 :
1947 : /****************************************************************
1948 : ****************************************************************/
1949 :
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,
1955 : };
|