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