source: branches/samba-3.5.x/source4/libnet/libnet_samsync_ldb.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 38.1 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Extract the user/system database from a remote SamSync server
5
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Andrew Tridgell 2004
8 Copyright (C) Volker Lendecke 2004
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24
25#include "includes.h"
26#include "libnet/libnet.h"
27#include "libcli/ldap/ldap_ndr.h"
28#include "dsdb/samdb/samdb.h"
29#include "auth/auth.h"
30#include "../lib/util/util_ldb.h"
31#include "librpc/gen_ndr/ndr_misc.h"
32#include "ldb_wrap.h"
33#include "libcli/security/security.h"
34#include "librpc/rpc/dcerpc.h"
35#include "param/param.h"
36
37struct samsync_ldb_secret {
38 struct samsync_ldb_secret *prev, *next;
39 DATA_BLOB secret;
40 char *name;
41 NTTIME mtime;
42};
43
44struct samsync_ldb_trusted_domain {
45 struct samsync_ldb_trusted_domain *prev, *next;
46 struct dom_sid *sid;
47 char *name;
48};
49
50struct samsync_ldb_state {
51 /* Values from the LSA lookup */
52 const struct libnet_SamSync_state *samsync_state;
53
54 struct dom_sid *dom_sid[3];
55 struct ldb_context *sam_ldb, *remote_ldb;
56 struct ldb_dn *base_dn[3];
57 struct samsync_ldb_secret *secrets;
58 struct samsync_ldb_trusted_domain *trusted_domains;
59};
60
61static NTSTATUS samsync_ldb_add_foreignSecurityPrincipal(TALLOC_CTX *mem_ctx,
62 struct samsync_ldb_state *state,
63 struct dom_sid *sid,
64 struct ldb_dn **fsp_dn,
65 char **error_string)
66{
67 const char *sidstr = dom_sid_string(mem_ctx, sid);
68 /* We assume that ForeignSecurityPrincipals are under the BASEDN of the main domain */
69 struct ldb_dn *basedn = samdb_search_dn(state->sam_ldb, mem_ctx,
70 state->base_dn[SAM_DATABASE_DOMAIN],
71 "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
72 struct ldb_message *msg;
73 int ret;
74
75 if (!sidstr) {
76 return NT_STATUS_NO_MEMORY;
77 }
78
79 if (basedn == NULL) {
80 *error_string = talloc_asprintf(mem_ctx,
81 "Failed to find DN for "
82 "ForeignSecurityPrincipal container under %s",
83 ldb_dn_get_linearized(state->base_dn[SAM_DATABASE_DOMAIN]));
84 return NT_STATUS_INTERNAL_DB_CORRUPTION;
85 }
86
87 msg = ldb_msg_new(mem_ctx);
88 if (msg == NULL) {
89 return NT_STATUS_NO_MEMORY;
90 }
91
92 /* add core elements to the ldb_message for the alias */
93 msg->dn = basedn;
94 if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr))
95 return NT_STATUS_UNSUCCESSFUL;
96
97 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg,
98 "objectClass",
99 "foreignSecurityPrincipal");
100
101 *fsp_dn = msg->dn;
102
103 /* create the alias */
104 ret = ldb_add(state->sam_ldb, msg);
105 if (ret != 0) {
106 *error_string = talloc_asprintf(mem_ctx, "Failed to create foreignSecurityPrincipal "
107 "record %s: %s",
108 ldb_dn_get_linearized(msg->dn),
109 ldb_errstring(state->sam_ldb));
110 return NT_STATUS_INTERNAL_DB_CORRUPTION;
111 }
112 return NT_STATUS_OK;
113}
114
115static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx,
116 struct samsync_ldb_state *state,
117 enum netr_SamDatabaseID database,
118 struct netr_DELTA_ENUM *delta,
119 char **error_string)
120{
121 struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain;
122 const char *domain_name = domain->domain_name.string;
123 struct ldb_message *msg;
124 int ret;
125
126 msg = ldb_msg_new(mem_ctx);
127 if (msg == NULL) {
128 return NT_STATUS_NO_MEMORY;
129 }
130
131 if (database == SAM_DATABASE_DOMAIN) {
132 struct ldb_dn *partitions_basedn;
133 const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL};
134 struct ldb_message **msgs_domain;
135 int ret_domain;
136
137 partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
138
139 ret_domain = gendb_search(state->sam_ldb, mem_ctx, partitions_basedn, &msgs_domain, domain_attrs,
140 "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
141 domain_name);
142 if (ret_domain == -1) {
143 *error_string = talloc_asprintf(mem_ctx, "gendb_search for domain failed: %s", ldb_errstring(state->sam_ldb));
144 return NT_STATUS_INTERNAL_DB_CORRUPTION;
145 }
146
147 if (ret_domain != 1) {
148 *error_string = talloc_asprintf(mem_ctx, "Failed to find existing domain record for %s: %d results", domain_name,
149 ret_domain);
150 return NT_STATUS_NO_SUCH_DOMAIN;
151 }
152
153 state->base_dn[database] = samdb_result_dn(state->sam_ldb, state, msgs_domain[0], "nCName", NULL);
154
155 if (state->dom_sid[database]) {
156 /* Update the domain sid with the incoming
157 * domain (found on LSA pipe, database sid may
158 * be random) */
159 samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx,
160 msg, "objectSid", state->dom_sid[database]);
161 } else {
162 /* Well, we will have to use the one from the database */
163 state->dom_sid[database] = samdb_search_dom_sid(state->sam_ldb, state,
164 state->base_dn[database],
165 "objectSid", NULL);
166 }
167
168 if (state->samsync_state->domain_guid) {
169 enum ndr_err_code ndr_err;
170 struct ldb_val v;
171 ndr_err = ndr_push_struct_blob(&v, msg, NULL,
172 state->samsync_state->domain_guid,
173 (ndr_push_flags_fn_t)ndr_push_GUID);
174 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
175 *error_string = talloc_asprintf(mem_ctx, "ndr_push of domain GUID failed!");
176 return ndr_map_error2ntstatus(ndr_err);
177 }
178
179 ldb_msg_add_value(msg, "objectGUID", &v, NULL);
180 }
181 } else if (database == SAM_DATABASE_BUILTIN) {
182 /* work out the builtin_dn - useful for so many calls its worth
183 fetching here */
184 const char *dnstring = samdb_search_string(state->sam_ldb, mem_ctx, NULL,
185 "distinguishedName", "objectClass=builtinDomain");
186 state->base_dn[database] = ldb_dn_new(state, state->sam_ldb, dnstring);
187 if ( ! ldb_dn_validate(state->base_dn[database])) {
188 return NT_STATUS_INTERNAL_ERROR;
189 }
190 } else {
191 /* PRIVs DB */
192 return NT_STATUS_INVALID_PARAMETER;
193 }
194
195 msg->dn = talloc_reference(mem_ctx, state->base_dn[database]);
196 if (!msg->dn) {
197 return NT_STATUS_NO_MEMORY;
198 }
199
200 samdb_msg_add_string(state->sam_ldb, mem_ctx,
201 msg, "oEMInformation", domain->oem_information.string);
202
203 samdb_msg_add_int64(state->sam_ldb, mem_ctx,
204 msg, "forceLogoff", domain->force_logoff_time);
205
206 samdb_msg_add_uint(state->sam_ldb, mem_ctx,
207 msg, "minPwdLen", domain->min_password_length);
208
209 samdb_msg_add_int64(state->sam_ldb, mem_ctx,
210 msg, "maxPwdAge", domain->max_password_age);
211
212 samdb_msg_add_int64(state->sam_ldb, mem_ctx,
213 msg, "minPwdAge", domain->min_password_age);
214
215 samdb_msg_add_uint(state->sam_ldb, mem_ctx,
216 msg, "pwdHistoryLength", domain->password_history_length);
217
218 samdb_msg_add_uint64(state->sam_ldb, mem_ctx,
219 msg, "modifiedCount",
220 domain->sequence_num);
221
222 samdb_msg_add_uint64(state->sam_ldb, mem_ctx,
223 msg, "creationTime", domain->domain_create_time);
224
225 /* TODO: Account lockout, password properties */
226
227 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
228
229 if (ret) {
230 return NT_STATUS_INTERNAL_ERROR;
231 }
232 return NT_STATUS_OK;
233}
234
235static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx,
236 struct samsync_ldb_state *state,
237 enum netr_SamDatabaseID database,
238 struct netr_DELTA_ENUM *delta,
239 char **error_string)
240{
241 uint32_t rid = delta->delta_id_union.rid;
242 struct netr_DELTA_USER *user = delta->delta_union.user;
243 const char *container, *obj_class;
244 char *cn_name;
245 int cn_name_len;
246 const struct dom_sid *user_sid;
247 struct ldb_message *msg;
248 struct ldb_message **msgs;
249 struct ldb_message **remote_msgs = NULL;
250 int ret, i;
251 uint32_t acb;
252 bool add = false;
253 const char *attrs[] = { NULL };
254 /* we may change this to a global search, then fill in only the things not in ldap later */
255 const char *remote_attrs[] = { "userPrincipalName", "servicePrincipalName",
256 "msDS-KeyVersionNumber", "objectGUID", NULL};
257
258 user_sid = dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid);
259 if (!user_sid) {
260 return NT_STATUS_NO_MEMORY;
261 }
262
263 msg = ldb_msg_new(mem_ctx);
264 if (msg == NULL) {
265 return NT_STATUS_NO_MEMORY;
266 }
267
268 msg->dn = NULL;
269 /* search for the user, by rid */
270 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database],
271 &msgs, attrs, "(&(objectClass=user)(objectSid=%s))",
272 ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
273
274 if (ret == -1) {
275 *error_string = talloc_asprintf(mem_ctx, "LDB for user %s failed: %s",
276 dom_sid_string(mem_ctx, user_sid),
277 ldb_errstring(state->sam_ldb));
278 return NT_STATUS_INTERNAL_DB_CORRUPTION;
279 } else if (ret == 0) {
280 add = true;
281 } else if (ret > 1) {
282 *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s in local LDB",
283 dom_sid_string(mem_ctx, user_sid));
284 return NT_STATUS_INTERNAL_DB_CORRUPTION;
285 } else {
286 msg->dn = msgs[0]->dn;
287 talloc_steal(msg, msgs[0]->dn);
288 }
289
290 /* and do the same on the remote database */
291 if (state->remote_ldb) {
292 ret = gendb_search(state->remote_ldb, mem_ctx, state->base_dn[database],
293 &remote_msgs, remote_attrs, "(&(objectClass=user)(objectSid=%s))",
294 ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
295
296 if (ret == -1) {
297 *error_string = talloc_asprintf(mem_ctx, "remote LDAP for user %s failed: %s",
298 dom_sid_string(mem_ctx, user_sid),
299 ldb_errstring(state->remote_ldb));
300 return NT_STATUS_INTERNAL_DB_CORRUPTION;
301 } else if (ret == 0) {
302 *error_string = talloc_asprintf(mem_ctx, "User exists in samsync but not in remote LDAP domain! (base: %s, SID: %s)",
303 ldb_dn_get_linearized(state->base_dn[database]),
304 dom_sid_string(mem_ctx, user_sid));
305 return NT_STATUS_NO_SUCH_USER;
306 } else if (ret > 1) {
307 *error_string = talloc_asprintf(mem_ctx, "More than one user in remote LDAP domain with SID: %s",
308 dom_sid_string(mem_ctx, user_sid));
309 return NT_STATUS_INTERNAL_DB_CORRUPTION;
310
311 /* Try to put things in the same location as the remote server */
312 } else if (add) {
313 msg->dn = remote_msgs[0]->dn;
314 talloc_steal(msg, remote_msgs[0]->dn);
315 }
316 }
317
318 cn_name = talloc_strdup(mem_ctx, user->account_name.string);
319 NT_STATUS_HAVE_NO_MEMORY(cn_name);
320 cn_name_len = strlen(cn_name);
321
322#define ADD_OR_DEL(type, attrib, field) do { \
323 if (user->field) { \
324 samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
325 attrib, user->field); \
326 } else if (!add) { \
327 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
328 attrib); \
329 } \
330 } while (0);
331
332 ADD_OR_DEL(string, "samAccountName", account_name.string);
333 ADD_OR_DEL(string, "displayName", full_name.string);
334
335 if (samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx, msg,
336 "objectSid", dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid))) {
337 return NT_STATUS_NO_MEMORY;
338 }
339
340 ADD_OR_DEL(uint, "primaryGroupID", primary_gid);
341 ADD_OR_DEL(string, "homeDirectory", home_directory.string);
342 ADD_OR_DEL(string, "homeDrive", home_drive.string);
343 ADD_OR_DEL(string, "scriptPath", logon_script.string);
344 ADD_OR_DEL(string, "description", description.string);
345 ADD_OR_DEL(string, "userWorkstations", workstations.string);
346
347 ADD_OR_DEL(uint64, "lastLogon", last_logon);
348 ADD_OR_DEL(uint64, "lastLogoff", last_logoff);
349
350 if (samdb_msg_add_logon_hours(state->sam_ldb, mem_ctx, msg, "logonHours", &user->logon_hours) != 0) {
351 return NT_STATUS_NO_MEMORY;
352 }
353
354 ADD_OR_DEL(uint, "badPwdCount", bad_password_count);
355 ADD_OR_DEL(uint, "logonCount", logon_count);
356
357 ADD_OR_DEL(uint64, "pwdLastSet", last_password_change);
358 ADD_OR_DEL(uint64, "accountExpires", acct_expiry);
359
360 if (samdb_msg_add_acct_flags(state->sam_ldb, mem_ctx, msg,
361 "userAccountControl", user->acct_flags) != 0) {
362 return NT_STATUS_NO_MEMORY;
363 }
364
365 if (!add) {
366 /* Passwords. Ensure there is no plaintext stored against
367 * this entry, as we only have hashes */
368 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
369 "userPassword");
370 }
371 if (user->lm_password_present) {
372 samdb_msg_add_hash(state->sam_ldb, mem_ctx, msg,
373 "dBCSPwd", &user->lmpassword);
374 } else if (!add) {
375 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
376 "dBCSPwd");
377 }
378 if (user->nt_password_present) {
379 samdb_msg_add_hash(state->sam_ldb, mem_ctx, msg,
380 "unicodePwd", &user->ntpassword);
381 } else if (!add) {
382 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
383 "unicodePwd");
384 }
385
386 ADD_OR_DEL(string, "comment", comment.string);
387
388 if (samdb_msg_add_parameters(state->sam_ldb, mem_ctx, msg, "userParameters", &user->parameters) != 0) {
389 return NT_STATUS_NO_MEMORY;
390 }
391
392 ADD_OR_DEL(uint, "countryCode", country_code);
393 ADD_OR_DEL(uint, "codePage", code_page);
394
395 ADD_OR_DEL(string, "profilePath", profile_path.string);
396
397#undef ADD_OR_DEL
398
399 for (i=0; remote_attrs[i]; i++) {
400 struct ldb_message_element *el = ldb_msg_find_element(remote_msgs[0], remote_attrs[i]);
401 if (!el) {
402 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
403 remote_attrs[i]);
404 } else {
405 ldb_msg_add(msg, el, LDB_FLAG_MOD_REPLACE);
406 }
407 }
408
409 acb = user->acct_flags;
410 if (acb & (ACB_WSTRUST)) {
411 cn_name[cn_name_len - 1] = '\0';
412 container = "Computers";
413 obj_class = "computer";
414
415 } else if (acb & ACB_SVRTRUST) {
416 if (cn_name[cn_name_len - 1] != '$') {
417 return NT_STATUS_FOOBAR;
418 }
419 cn_name[cn_name_len - 1] = '\0';
420 container = "Domain Controllers";
421 obj_class = "computer";
422 } else {
423 container = "Users";
424 obj_class = "user";
425 }
426 if (add) {
427 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg,
428 "objectClass", obj_class);
429 if (!msg->dn) {
430 msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]);
431 ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container);
432 if (!msg->dn) {
433 return NT_STATUS_NO_MEMORY;
434 }
435 }
436
437 ret = ldb_add(state->sam_ldb, msg);
438 if (ret != 0) {
439 struct ldb_dn *first_try_dn = msg->dn;
440 /* Try again with the default DN */
441 if (!remote_msgs) {
442 *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried %s: %s",
443 ldb_dn_get_linearized(first_try_dn),
444 ldb_errstring(state->sam_ldb));
445 return NT_STATUS_INTERNAL_DB_CORRUPTION;
446 } else {
447 msg->dn = talloc_steal(msg, remote_msgs[0]->dn);
448 ret = ldb_add(state->sam_ldb, msg);
449 if (ret != 0) {
450 *error_string = talloc_asprintf(mem_ctx, "Failed to create user record. Tried both %s and %s: %s",
451 ldb_dn_get_linearized(first_try_dn),
452 ldb_dn_get_linearized(msg->dn),
453 ldb_errstring(state->sam_ldb));
454 return NT_STATUS_INTERNAL_DB_CORRUPTION;
455 }
456 }
457 }
458 } else {
459 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
460 if (ret != 0) {
461 *error_string = talloc_asprintf(mem_ctx, "Failed to modify user record %s: %s",
462 ldb_dn_get_linearized(msg->dn),
463 ldb_errstring(state->sam_ldb));
464 return NT_STATUS_INTERNAL_DB_CORRUPTION;
465 }
466 }
467
468 return NT_STATUS_OK;
469}
470
471static NTSTATUS samsync_ldb_delete_user(TALLOC_CTX *mem_ctx,
472 struct samsync_ldb_state *state,
473 enum netr_SamDatabaseID database,
474 struct netr_DELTA_ENUM *delta,
475 char **error_string)
476{
477 uint32_t rid = delta->delta_id_union.rid;
478 struct ldb_message **msgs;
479 int ret;
480 const char *attrs[] = { NULL };
481
482 /* search for the user, by rid */
483 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database],
484 &msgs, attrs, "(&(objectClass=user)(objectSid=%s))",
485 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
486
487 if (ret == -1) {
488 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
489 return NT_STATUS_INTERNAL_DB_CORRUPTION;
490 } else if (ret == 0) {
491 return NT_STATUS_NO_SUCH_USER;
492 } else if (ret > 1) {
493 *error_string = talloc_asprintf(mem_ctx, "More than one user with SID: %s",
494 dom_sid_string(mem_ctx,
495 dom_sid_add_rid(mem_ctx,
496 state->dom_sid[database],
497 rid)));
498 return NT_STATUS_INTERNAL_DB_CORRUPTION;
499 }
500
501 ret = ldb_delete(state->sam_ldb, msgs[0]->dn);
502 if (ret != 0) {
503 *error_string = talloc_asprintf(mem_ctx, "Failed to delete user record %s: %s",
504 ldb_dn_get_linearized(msgs[0]->dn),
505 ldb_errstring(state->sam_ldb));
506 return NT_STATUS_INTERNAL_DB_CORRUPTION;
507 }
508
509 return NT_STATUS_OK;
510}
511
512static NTSTATUS samsync_ldb_handle_group(TALLOC_CTX *mem_ctx,
513 struct samsync_ldb_state *state,
514 enum netr_SamDatabaseID database,
515 struct netr_DELTA_ENUM *delta,
516 char **error_string)
517{
518 uint32_t rid = delta->delta_id_union.rid;
519 struct netr_DELTA_GROUP *group = delta->delta_union.group;
520 const char *container, *obj_class;
521 const char *cn_name;
522
523 struct ldb_message *msg;
524 struct ldb_message **msgs;
525 int ret;
526 bool add = false;
527 const char *attrs[] = { NULL };
528
529 msg = ldb_msg_new(mem_ctx);
530 if (msg == NULL) {
531 return NT_STATUS_NO_MEMORY;
532 }
533
534 /* search for the group, by rid */
535 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
536 "(&(objectClass=group)(objectSid=%s))",
537 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
538
539 if (ret == -1) {
540 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
541 return NT_STATUS_INTERNAL_DB_CORRUPTION;
542 } else if (ret == 0) {
543 add = true;
544 } else if (ret > 1) {
545 *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
546 dom_sid_string(mem_ctx,
547 dom_sid_add_rid(mem_ctx,
548 state->dom_sid[database],
549 rid)));
550 return NT_STATUS_INTERNAL_DB_CORRUPTION;
551 } else {
552 msg->dn = talloc_steal(msg, msgs[0]->dn);
553 }
554
555 cn_name = group->group_name.string;
556
557#define ADD_OR_DEL(type, attrib, field) do { \
558 if (group->field) { \
559 samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
560 attrib, group->field); \
561 } else if (!add) { \
562 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
563 attrib); \
564 } \
565 } while (0);
566
567 ADD_OR_DEL(string, "samAccountName", group_name.string);
568
569 if (samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx, msg,
570 "objectSid", dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid))) {
571 return NT_STATUS_NO_MEMORY;
572 }
573
574 ADD_OR_DEL(string, "description", description.string);
575
576#undef ADD_OR_DEL
577
578 container = "Users";
579 obj_class = "group";
580
581 if (add) {
582 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg,
583 "objectClass", obj_class);
584 msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]);
585 ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container);
586 if (!msg->dn) {
587 return NT_STATUS_NO_MEMORY;
588 }
589
590 ret = ldb_add(state->sam_ldb, msg);
591 if (ret != 0) {
592 *error_string = talloc_asprintf(mem_ctx, "Failed to create group record %s: %s",
593 ldb_dn_get_linearized(msg->dn),
594 ldb_errstring(state->sam_ldb));
595 return NT_STATUS_INTERNAL_DB_CORRUPTION;
596 }
597 } else {
598 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
599 if (ret != 0) {
600 *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
601 ldb_dn_get_linearized(msg->dn),
602 ldb_errstring(state->sam_ldb));
603 return NT_STATUS_INTERNAL_DB_CORRUPTION;
604 }
605 }
606
607 return NT_STATUS_OK;
608}
609
610static NTSTATUS samsync_ldb_delete_group(TALLOC_CTX *mem_ctx,
611 struct samsync_ldb_state *state,
612 enum netr_SamDatabaseID database,
613 struct netr_DELTA_ENUM *delta,
614 char **error_string)
615{
616 uint32_t rid = delta->delta_id_union.rid;
617 struct ldb_message **msgs;
618 int ret;
619 const char *attrs[] = { NULL };
620
621 /* search for the group, by rid */
622 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
623 "(&(objectClass=group)(objectSid=%s))",
624 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
625
626 if (ret == -1) {
627 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
628 return NT_STATUS_INTERNAL_DB_CORRUPTION;
629 } else if (ret == 0) {
630 return NT_STATUS_NO_SUCH_GROUP;
631 } else if (ret > 1) {
632 *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
633 dom_sid_string(mem_ctx,
634 dom_sid_add_rid(mem_ctx,
635 state->dom_sid[database],
636 rid)));
637 return NT_STATUS_INTERNAL_DB_CORRUPTION;
638 }
639
640 ret = ldb_delete(state->sam_ldb, msgs[0]->dn);
641 if (ret != 0) {
642 *error_string = talloc_asprintf(mem_ctx, "Failed to delete group record %s: %s",
643 ldb_dn_get_linearized(msgs[0]->dn),
644 ldb_errstring(state->sam_ldb));
645 return NT_STATUS_INTERNAL_DB_CORRUPTION;
646 }
647
648 return NT_STATUS_OK;
649}
650
651static NTSTATUS samsync_ldb_handle_group_member(TALLOC_CTX *mem_ctx,
652 struct samsync_ldb_state *state,
653 enum netr_SamDatabaseID database,
654 struct netr_DELTA_ENUM *delta,
655 char **error_string)
656{
657 uint32_t rid = delta->delta_id_union.rid;
658 struct netr_DELTA_GROUP_MEMBER *group_member = delta->delta_union.group_member;
659 struct ldb_message *msg;
660 struct ldb_message **msgs;
661 int ret;
662 const char *attrs[] = { NULL };
663 int i;
664
665 msg = ldb_msg_new(mem_ctx);
666 if (msg == NULL) {
667 return NT_STATUS_NO_MEMORY;
668 }
669
670 /* search for the group, by rid */
671 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
672 "(&(objectClass=group)(objectSid=%s))",
673 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
674
675 if (ret == -1) {
676 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
677 return NT_STATUS_INTERNAL_DB_CORRUPTION;
678 } else if (ret == 0) {
679 return NT_STATUS_NO_SUCH_GROUP;
680 } else if (ret > 1) {
681 *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
682 dom_sid_string(mem_ctx,
683 dom_sid_add_rid(mem_ctx,
684 state->dom_sid[database],
685 rid)));
686 return NT_STATUS_INTERNAL_DB_CORRUPTION;
687 } else {
688 msg->dn = talloc_steal(msg, msgs[0]->dn);
689 }
690
691 talloc_free(msgs);
692
693 for (i=0; i<group_member->num_rids; i++) {
694 /* search for the group, by rid */
695 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
696 "(&(objectClass=user)(objectSid=%s))",
697 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], group_member->rids[i])));
698
699 if (ret == -1) {
700 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
701 return NT_STATUS_INTERNAL_DB_CORRUPTION;
702 } else if (ret == 0) {
703 return NT_STATUS_NO_SUCH_USER;
704 } else if (ret > 1) {
705 return NT_STATUS_INTERNAL_DB_CORRUPTION;
706 } else {
707 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "member", ldb_dn_alloc_linearized(mem_ctx, msgs[0]->dn));
708 }
709
710 talloc_free(msgs);
711 }
712
713 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
714 if (ret != 0) {
715 *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
716 ldb_dn_get_linearized(msg->dn),
717 ldb_errstring(state->sam_ldb));
718 return NT_STATUS_INTERNAL_DB_CORRUPTION;
719 }
720
721 return NT_STATUS_OK;
722}
723
724static NTSTATUS samsync_ldb_handle_alias(TALLOC_CTX *mem_ctx,
725 struct samsync_ldb_state *state,
726 enum netr_SamDatabaseID database,
727 struct netr_DELTA_ENUM *delta,
728 char **error_string)
729{
730 uint32_t rid = delta->delta_id_union.rid;
731 struct netr_DELTA_ALIAS *alias = delta->delta_union.alias;
732 const char *container, *obj_class;
733 const char *cn_name;
734
735 struct ldb_message *msg;
736 struct ldb_message **msgs;
737 int ret;
738 bool add = false;
739 const char *attrs[] = { NULL };
740
741 msg = ldb_msg_new(mem_ctx);
742 if (msg == NULL) {
743 return NT_STATUS_NO_MEMORY;
744 }
745
746 /* search for the alias, by rid */
747 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
748 "(&(objectClass=group)(objectSid=%s))",
749 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
750
751 if (ret == -1) {
752 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
753 return NT_STATUS_INTERNAL_DB_CORRUPTION;
754 } else if (ret == 0) {
755 add = true;
756 } else if (ret > 1) {
757 *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
758 dom_sid_string(mem_ctx,
759 dom_sid_add_rid(mem_ctx,
760 state->dom_sid[database],
761 rid)));
762 return NT_STATUS_INTERNAL_DB_CORRUPTION;
763 } else {
764 msg->dn = talloc_steal(mem_ctx, msgs[0]->dn);
765 }
766
767 cn_name = alias->alias_name.string;
768
769#define ADD_OR_DEL(type, attrib, field) do { \
770 if (alias->field) { \
771 samdb_msg_add_ ## type(state->sam_ldb, mem_ctx, msg, \
772 attrib, alias->field); \
773 } else if (!add) { \
774 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg, \
775 attrib); \
776 } \
777 } while (0);
778
779 ADD_OR_DEL(string, "samAccountName", alias_name.string);
780
781 if (samdb_msg_add_dom_sid(state->sam_ldb, mem_ctx, msg,
782 "objectSid", dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid))) {
783 return NT_STATUS_NO_MEMORY;
784 }
785
786 ADD_OR_DEL(string, "description", description.string);
787
788#undef ADD_OR_DEL
789
790 samdb_msg_add_uint(state->sam_ldb, mem_ctx, msg, "groupType", 0x80000004);
791
792 container = "Users";
793 obj_class = "group";
794
795 if (add) {
796 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg,
797 "objectClass", obj_class);
798 msg->dn = ldb_dn_copy(mem_ctx, state->base_dn[database]);
799 ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=%s", cn_name, container);
800 if (!msg->dn) {
801 return NT_STATUS_NO_MEMORY;
802 }
803
804 ret = ldb_add(state->sam_ldb, msg);
805 if (ret != 0) {
806 *error_string = talloc_asprintf(mem_ctx, "Failed to create alias record %s: %s",
807 ldb_dn_get_linearized(msg->dn),
808 ldb_errstring(state->sam_ldb));
809 return NT_STATUS_INTERNAL_DB_CORRUPTION;
810 }
811 } else {
812 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
813 if (ret != 0) {
814 *error_string = talloc_asprintf(mem_ctx, "Failed to modify alias record %s: %s",
815 ldb_dn_get_linearized(msg->dn),
816 ldb_errstring(state->sam_ldb));
817 return NT_STATUS_INTERNAL_DB_CORRUPTION;
818 }
819 }
820
821 return NT_STATUS_OK;
822}
823
824static NTSTATUS samsync_ldb_delete_alias(TALLOC_CTX *mem_ctx,
825 struct samsync_ldb_state *state,
826 enum netr_SamDatabaseID database,
827 struct netr_DELTA_ENUM *delta,
828 char **error_string)
829{
830 uint32_t rid = delta->delta_id_union.rid;
831 struct ldb_message **msgs;
832 int ret;
833 const char *attrs[] = { NULL };
834
835 /* search for the alias, by rid */
836 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
837 "(&(objectClass=group)(objectSid=%s))",
838 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
839
840 if (ret == -1) {
841 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
842 return NT_STATUS_INTERNAL_DB_CORRUPTION;
843 } else if (ret == 0) {
844 return NT_STATUS_NO_SUCH_ALIAS;
845 } else if (ret > 1) {
846 return NT_STATUS_INTERNAL_DB_CORRUPTION;
847 }
848
849 ret = ldb_delete(state->sam_ldb, msgs[0]->dn);
850 if (ret != 0) {
851 *error_string = talloc_asprintf(mem_ctx, "Failed to delete alias record %s: %s",
852 ldb_dn_get_linearized(msgs[0]->dn),
853 ldb_errstring(state->sam_ldb));
854 return NT_STATUS_INTERNAL_DB_CORRUPTION;
855 }
856
857 return NT_STATUS_OK;
858}
859
860static NTSTATUS samsync_ldb_handle_alias_member(TALLOC_CTX *mem_ctx,
861 struct samsync_ldb_state *state,
862 enum netr_SamDatabaseID database,
863 struct netr_DELTA_ENUM *delta,
864 char **error_string)
865{
866 uint32_t rid = delta->delta_id_union.rid;
867 struct netr_DELTA_ALIAS_MEMBER *alias_member = delta->delta_union.alias_member;
868 struct ldb_message *msg;
869 struct ldb_message **msgs;
870 int ret;
871 const char *attrs[] = { NULL };
872 int i;
873
874 msg = ldb_msg_new(mem_ctx);
875 if (msg == NULL) {
876 return NT_STATUS_NO_MEMORY;
877 }
878
879 /* search for the alias, by rid */
880 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[database], &msgs, attrs,
881 "(&(objectClass=group)(objectSid=%s))",
882 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid_add_rid(mem_ctx, state->dom_sid[database], rid)));
883
884 if (ret == -1) {
885 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
886 return NT_STATUS_INTERNAL_DB_CORRUPTION;
887 } else if (ret == 0) {
888 return NT_STATUS_NO_SUCH_GROUP;
889 } else if (ret > 1) {
890 *error_string = talloc_asprintf(mem_ctx, "More than one group/alias with SID: %s",
891 dom_sid_string(mem_ctx,
892 dom_sid_add_rid(mem_ctx,
893 state->dom_sid[database],
894 rid)));
895 return NT_STATUS_INTERNAL_DB_CORRUPTION;
896 } else {
897 msg->dn = talloc_steal(msg, msgs[0]->dn);
898 }
899
900 talloc_free(msgs);
901
902 for (i=0; i<alias_member->sids.num_sids; i++) {
903 struct ldb_dn *alias_member_dn;
904 /* search for members, in the top basedn (normal users are builtin aliases) */
905 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN], &msgs, attrs,
906 "(objectSid=%s)",
907 ldap_encode_ndr_dom_sid(mem_ctx, alias_member->sids.sids[i].sid));
908
909 if (ret == -1) {
910 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
911 return NT_STATUS_INTERNAL_DB_CORRUPTION;
912 } else if (ret == 0) {
913 NTSTATUS nt_status;
914 nt_status = samsync_ldb_add_foreignSecurityPrincipal(mem_ctx, state,
915 alias_member->sids.sids[i].sid,
916 &alias_member_dn,
917 error_string);
918 if (!NT_STATUS_IS_OK(nt_status)) {
919 return nt_status;
920 }
921 } else if (ret > 1) {
922 return NT_STATUS_INTERNAL_DB_CORRUPTION;
923 } else {
924 alias_member_dn = msgs[0]->dn;
925 }
926 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "member", ldb_dn_alloc_linearized(mem_ctx, alias_member_dn));
927
928 talloc_free(msgs);
929 }
930
931 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
932 if (ret != 0) {
933 *error_string = talloc_asprintf(mem_ctx, "Failed to modify group record %s: %s",
934 ldb_dn_get_linearized(msg->dn),
935 ldb_errstring(state->sam_ldb));
936 return NT_STATUS_INTERNAL_DB_CORRUPTION;
937 }
938
939 return NT_STATUS_OK;
940}
941
942static NTSTATUS samsync_ldb_handle_account(TALLOC_CTX *mem_ctx,
943 struct samsync_ldb_state *state,
944 enum netr_SamDatabaseID database,
945 struct netr_DELTA_ENUM *delta,
946 char **error_string)
947{
948 struct dom_sid *sid = delta->delta_id_union.sid;
949 struct netr_DELTA_ACCOUNT *account = delta->delta_union.account;
950
951 struct ldb_message *msg;
952 struct ldb_message **msgs;
953 struct ldb_dn *privilege_dn;
954 int ret;
955 const char *attrs[] = { NULL };
956 int i;
957
958 msg = ldb_msg_new(mem_ctx);
959 if (msg == NULL) {
960 return NT_STATUS_NO_MEMORY;
961 }
962
963 /* search for the account, by sid, in the top basedn */
964 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN], &msgs, attrs,
965 "(objectSid=%s)", ldap_encode_ndr_dom_sid(mem_ctx, sid));
966
967 if (ret == -1) {
968 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
969 return NT_STATUS_INTERNAL_DB_CORRUPTION;
970 } else if (ret == 0) {
971 NTSTATUS nt_status;
972 nt_status = samsync_ldb_add_foreignSecurityPrincipal(mem_ctx, state,
973 sid,
974 &privilege_dn,
975 error_string);
976 privilege_dn = talloc_steal(msg, privilege_dn);
977 if (!NT_STATUS_IS_OK(nt_status)) {
978 return nt_status;
979 }
980 } else if (ret > 1) {
981 *error_string = talloc_asprintf(mem_ctx, "More than one account with SID: %s",
982 dom_sid_string(mem_ctx, sid));
983 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 } else {
985 privilege_dn = talloc_steal(msg, msgs[0]->dn);
986 }
987
988 msg->dn = privilege_dn;
989
990 for (i=0; i< account->privilege_entries; i++) {
991 samdb_msg_add_string(state->sam_ldb, mem_ctx, msg, "privilege",
992 account->privilege_name[i].string);
993 }
994
995 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
996 if (ret != 0) {
997 *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s",
998 ldb_dn_get_linearized(msg->dn));
999 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1000 }
1001
1002 return NT_STATUS_OK;
1003}
1004
1005static NTSTATUS samsync_ldb_delete_account(TALLOC_CTX *mem_ctx,
1006 struct samsync_ldb_state *state,
1007 enum netr_SamDatabaseID database,
1008 struct netr_DELTA_ENUM *delta,
1009 char **error_string)
1010{
1011 struct dom_sid *sid = delta->delta_id_union.sid;
1012
1013 struct ldb_message *msg;
1014 struct ldb_message **msgs;
1015 int ret;
1016 const char *attrs[] = { NULL };
1017
1018 msg = ldb_msg_new(mem_ctx);
1019 if (msg == NULL) {
1020 return NT_STATUS_NO_MEMORY;
1021 }
1022
1023 /* search for the account, by sid, in the top basedn */
1024 ret = gendb_search(state->sam_ldb, mem_ctx, state->base_dn[SAM_DATABASE_DOMAIN], &msgs, attrs,
1025 "(objectSid=%s)",
1026 ldap_encode_ndr_dom_sid(mem_ctx, sid));
1027
1028 if (ret == -1) {
1029 *error_string = talloc_asprintf(mem_ctx, "gendb_search failed: %s", ldb_errstring(state->sam_ldb));
1030 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1031 } else if (ret == 0) {
1032 return NT_STATUS_NO_SUCH_USER;
1033 } else if (ret > 1) {
1034 *error_string = talloc_asprintf(mem_ctx, "More than one account with SID: %s",
1035 dom_sid_string(mem_ctx, sid));
1036 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1037 } else {
1038 msg->dn = talloc_steal(msg, msgs[0]->dn);
1039 }
1040
1041 samdb_msg_add_delete(state->sam_ldb, mem_ctx, msg,
1042 "privilege");
1043
1044 ret = samdb_replace(state->sam_ldb, mem_ctx, msg);
1045 if (ret != 0) {
1046 *error_string = talloc_asprintf(mem_ctx, "Failed to modify privilege record %s",
1047 ldb_dn_get_linearized(msg->dn));
1048 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1049 }
1050
1051 return NT_STATUS_OK;
1052}
1053
1054static NTSTATUS libnet_samsync_ldb_fn(TALLOC_CTX *mem_ctx,
1055 void *private_data,
1056 enum netr_SamDatabaseID database,
1057 struct netr_DELTA_ENUM *delta,
1058 char **error_string)
1059{
1060 NTSTATUS nt_status = NT_STATUS_OK;
1061 struct samsync_ldb_state *state = talloc_get_type(private_data, struct samsync_ldb_state);
1062
1063 *error_string = NULL;
1064 switch (delta->delta_type) {
1065 case NETR_DELTA_DOMAIN:
1066 {
1067 nt_status = samsync_ldb_handle_domain(mem_ctx,
1068 state,
1069 database,
1070 delta,
1071 error_string);
1072 break;
1073 }
1074 case NETR_DELTA_USER:
1075 {
1076 nt_status = samsync_ldb_handle_user(mem_ctx,
1077 state,
1078 database,
1079 delta,
1080 error_string);
1081 break;
1082 }
1083 case NETR_DELTA_DELETE_USER:
1084 {
1085 nt_status = samsync_ldb_delete_user(mem_ctx,
1086 state,
1087 database,
1088 delta,
1089 error_string);
1090 break;
1091 }
1092 case NETR_DELTA_GROUP:
1093 {
1094 nt_status = samsync_ldb_handle_group(mem_ctx,
1095 state,
1096 database,
1097 delta,
1098 error_string);
1099 break;
1100 }
1101 case NETR_DELTA_DELETE_GROUP:
1102 {
1103 nt_status = samsync_ldb_delete_group(mem_ctx,
1104 state,
1105 database,
1106 delta,
1107 error_string);
1108 break;
1109 }
1110 case NETR_DELTA_GROUP_MEMBER:
1111 {
1112 nt_status = samsync_ldb_handle_group_member(mem_ctx,
1113 state,
1114 database,
1115 delta,
1116 error_string);
1117 break;
1118 }
1119 case NETR_DELTA_ALIAS:
1120 {
1121 nt_status = samsync_ldb_handle_alias(mem_ctx,
1122 state,
1123 database,
1124 delta,
1125 error_string);
1126 break;
1127 }
1128 case NETR_DELTA_DELETE_ALIAS:
1129 {
1130 nt_status = samsync_ldb_delete_alias(mem_ctx,
1131 state,
1132 database,
1133 delta,
1134 error_string);
1135 break;
1136 }
1137 case NETR_DELTA_ALIAS_MEMBER:
1138 {
1139 nt_status = samsync_ldb_handle_alias_member(mem_ctx,
1140 state,
1141 database,
1142 delta,
1143 error_string);
1144 break;
1145 }
1146 case NETR_DELTA_ACCOUNT:
1147 {
1148 nt_status = samsync_ldb_handle_account(mem_ctx,
1149 state,
1150 database,
1151 delta,
1152 error_string);
1153 break;
1154 }
1155 case NETR_DELTA_DELETE_ACCOUNT:
1156 {
1157 nt_status = samsync_ldb_delete_account(mem_ctx,
1158 state,
1159 database,
1160 delta,
1161 error_string);
1162 break;
1163 }
1164 default:
1165 /* Can't dump them all right now */
1166 break;
1167 }
1168 if (!NT_STATUS_IS_OK(nt_status) && !*error_string) {
1169 *error_string = talloc_asprintf(mem_ctx, "Failed to handle samsync delta: %s", nt_errstr(nt_status));
1170 }
1171 return nt_status;
1172}
1173
1174static NTSTATUS libnet_samsync_ldb_init(TALLOC_CTX *mem_ctx,
1175 void *private_data,
1176 struct libnet_SamSync_state *samsync_state,
1177 char **error_string)
1178{
1179 struct samsync_ldb_state *state = talloc_get_type(private_data, struct samsync_ldb_state);
1180 const char *server = dcerpc_server_name(samsync_state->netlogon_pipe);
1181 char *ldap_url;
1182
1183 state->samsync_state = samsync_state;
1184
1185 ZERO_STRUCT(state->dom_sid);
1186 if (state->samsync_state->domain_sid) {
1187 state->dom_sid[SAM_DATABASE_DOMAIN] = dom_sid_dup(state, state->samsync_state->domain_sid);
1188 }
1189
1190 state->dom_sid[SAM_DATABASE_BUILTIN] = dom_sid_parse_talloc(state, SID_BUILTIN);
1191
1192 if (state->samsync_state->realm) {
1193 if (!server || !*server) {
1194 /* huh? how do we not have a server name? */
1195 *error_string = talloc_strdup(mem_ctx, "No DCE/RPC server name available. How did we connect?");
1196 return NT_STATUS_INVALID_PARAMETER;
1197 }
1198 ldap_url = talloc_asprintf(state, "ldap://%s", server);
1199
1200 state->remote_ldb = ldb_wrap_connect(mem_ctx,
1201 state->samsync_state->machine_net_ctx->event_ctx,
1202 state->samsync_state->machine_net_ctx->lp_ctx,
1203 ldap_url,
1204 NULL, state->samsync_state->machine_net_ctx->cred,
1205 0, NULL);
1206 if (!state->remote_ldb) {
1207 *error_string = talloc_asprintf(mem_ctx, "Failed to connect to remote LDAP server at %s (used to extract additional data in SamSync replication)", ldap_url);
1208 return NT_STATUS_NO_LOGON_SERVERS;
1209 }
1210 } else {
1211 state->remote_ldb = NULL;
1212 }
1213 return NT_STATUS_OK;
1214}
1215
1216NTSTATUS libnet_samsync_ldb(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_samsync_ldb *r)
1217{
1218 NTSTATUS nt_status;
1219 struct libnet_SamSync r2;
1220 struct samsync_ldb_state *state = talloc(mem_ctx, struct samsync_ldb_state);
1221
1222 if (!state) {
1223 return NT_STATUS_NO_MEMORY;
1224 }
1225
1226 state->secrets = NULL;
1227 state->trusted_domains = NULL;
1228
1229 state->sam_ldb = samdb_connect(mem_ctx,
1230 ctx->event_ctx,
1231 ctx->lp_ctx,
1232 r->in.session_info);
1233
1234 r2.out.error_string = NULL;
1235 r2.in.binding_string = r->in.binding_string;
1236 r2.in.init_fn = libnet_samsync_ldb_init;
1237 r2.in.delta_fn = libnet_samsync_ldb_fn;
1238 r2.in.fn_ctx = state;
1239 r2.in.machine_account = NULL; /* TODO: Create a machine account, fill this in, and the delete it */
1240 nt_status = libnet_SamSync_netlogon(ctx, state, &r2);
1241 r->out.error_string = r2.out.error_string;
1242 talloc_steal(mem_ctx, r->out.error_string);
1243
1244 if (!NT_STATUS_IS_OK(nt_status)) {
1245 talloc_free(state);
1246 return nt_status;
1247 }
1248 talloc_free(state);
1249 return nt_status;
1250}
Note: See TracBrowser for help on using the repository browser.