Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : pdb glue module for direct access to the dsdb via LDB APIs
4 : Copyright (C) Volker Lendecke 2009-2011
5 : Copyright (C) Andrew Bartlett 2010-2012
6 : Copyright (C) Matthias Dieter Wallnöfer 2009
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : /* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
23 :
24 : #include "includes.h"
25 : #include "source3/include/passdb.h"
26 : #include "source4/dsdb/samdb/samdb.h"
27 : #include "ldb_errors.h"
28 : #include "libcli/security/dom_sid.h"
29 : #include "source4/winbind/idmap.h"
30 : #include "librpc/gen_ndr/ndr_security.h"
31 : #include "librpc/gen_ndr/ndr_drsblobs.h"
32 : #include "librpc/gen_ndr/ndr_lsa.h"
33 : #include "libds/common/flag_mapping.h"
34 : #include "source4/lib/events/events.h"
35 : #include "source4/auth/session.h"
36 : #include "source4/auth/system_session_proto.h"
37 : #include "lib/param/param.h"
38 : #include "source4/dsdb/common/util.h"
39 : #include "source3/include/secrets.h"
40 : #include "source4/auth/auth_sam.h"
41 : #include "auth/credentials/credentials.h"
42 : #include "lib/util/base64.h"
43 : #include "libcli/ldap/ldap_ndr.h"
44 : #include "lib/util/util_ldb.h"
45 :
46 : struct pdb_samba_dsdb_state {
47 : struct tevent_context *ev;
48 : struct ldb_context *ldb;
49 : struct idmap_context *idmap_ctx;
50 : struct loadparm_context *lp_ctx;
51 : };
52 :
53 : static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
54 : struct samu *sam_acct,
55 : const struct dom_sid *sid);
56 : static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
57 : const char *filter,
58 : TALLOC_CTX *mem_ctx,
59 : struct ldb_message **pmsg);
60 : static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
61 : struct unixid *id);
62 :
63 9260 : static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
64 : time_t *ptime)
65 : {
66 : uint64_t tmp;
67 9260 : if (! ldb_msg_find_element(msg, attr)) {
68 1170 : return false;
69 : }
70 8090 : tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
71 8090 : *ptime = nt_time_to_unix(tmp);
72 8090 : return true;
73 : }
74 :
75 3996 : static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
76 : struct pdb_methods *m, TALLOC_CTX *mem_ctx)
77 : {
78 3996 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
79 : m->private_data, struct pdb_samba_dsdb_state);
80 : struct pdb_domain_info *info;
81 : struct dom_sid *domain_sid;
82 : struct ldb_dn *forest_dn, *domain_dn;
83 3996 : struct ldb_result *dom_res = NULL;
84 3996 : const char *dom_attrs[] = {
85 : "objectSid",
86 : "objectGUID",
87 : "fSMORoleOwner",
88 : NULL
89 : };
90 : char *p;
91 : int ret;
92 :
93 3996 : info = talloc(mem_ctx, struct pdb_domain_info);
94 3996 : if (info == NULL) {
95 0 : return NULL;
96 : }
97 :
98 3996 : domain_dn = ldb_get_default_basedn(state->ldb);
99 :
100 3996 : ret = ldb_search(state->ldb, info, &dom_res,
101 : domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
102 3996 : if (ret != LDB_SUCCESS) {
103 0 : goto fail;
104 : }
105 3996 : if (dom_res->count != 1) {
106 0 : goto fail;
107 : }
108 :
109 3996 : info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
110 :
111 3996 : domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
112 3996 : if (!domain_sid) {
113 0 : goto fail;
114 : }
115 3996 : info->sid = *domain_sid;
116 :
117 3996 : TALLOC_FREE(dom_res);
118 :
119 3996 : info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
120 3996 : info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
121 :
122 3996 : if (!info->dns_domain) {
123 0 : goto fail;
124 : }
125 3996 : p = strchr(info->dns_domain, '/');
126 3996 : if (p) {
127 3996 : *p = '\0';
128 : }
129 :
130 3996 : forest_dn = ldb_get_root_basedn(state->ldb);
131 3996 : if (!forest_dn) {
132 0 : goto fail;
133 : }
134 :
135 3996 : info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
136 3996 : if (!info->dns_forest) {
137 0 : goto fail;
138 : }
139 3996 : p = strchr(info->dns_forest, '/');
140 3996 : if (p) {
141 3996 : *p = '\0';
142 : }
143 :
144 3996 : return info;
145 :
146 0 : fail:
147 0 : TALLOC_FREE(dom_res);
148 0 : TALLOC_FREE(info);
149 0 : return NULL;
150 : }
151 :
152 2305 : static struct ldb_message *pdb_samba_dsdb_get_samu_private(
153 : struct pdb_methods *m, struct samu *sam)
154 : {
155 2305 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
156 : m->private_data, struct pdb_samba_dsdb_state);
157 : struct ldb_message *msg;
158 : struct dom_sid_buf sidstr;
159 : char *filter;
160 : NTSTATUS status;
161 :
162 2305 : msg = (struct ldb_message *)
163 2305 : pdb_get_backend_private_data(sam, m);
164 :
165 2305 : if (msg != NULL) {
166 2305 : return talloc_get_type_abort(msg, struct ldb_message);
167 : }
168 :
169 0 : filter = talloc_asprintf(
170 0 : talloc_tos(),
171 : "(&(objectsid=%s)(objectclass=user))",
172 : dom_sid_str_buf(pdb_get_user_sid(sam), &sidstr));
173 0 : if (filter == NULL) {
174 0 : return NULL;
175 : }
176 :
177 0 : status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
178 0 : TALLOC_FREE(filter);
179 0 : if (!NT_STATUS_IS_OK(status)) {
180 0 : return NULL;
181 : }
182 :
183 0 : return msg;
184 : }
185 :
186 2315 : static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
187 : struct samu *sam,
188 : struct ldb_message *msg)
189 : {
190 2315 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
191 : m->private_data, struct pdb_samba_dsdb_state);
192 2315 : TALLOC_CTX *frame = talloc_stackframe();
193 2315 : NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
194 : const char *str;
195 : time_t tmp_time;
196 : struct dom_sid *sid, group_sid;
197 : uint64_t n;
198 : const DATA_BLOB *blob;
199 :
200 2315 : str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
201 2315 : if (str == NULL) {
202 0 : DEBUG(10, ("no samAccountName\n"));
203 0 : goto fail;
204 : }
205 2315 : pdb_set_username(sam, str, PDB_SET);
206 :
207 2315 : if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
208 1769 : pdb_set_logon_time(sam, tmp_time, PDB_SET);
209 : }
210 2315 : if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
211 1691 : pdb_set_logoff_time(sam, tmp_time, PDB_SET);
212 : }
213 2315 : if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
214 2315 : pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
215 : }
216 2315 : if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
217 2315 : pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
218 : }
219 :
220 2315 : str = ldb_msg_find_attr_as_string(msg, "displayName",
221 : NULL);
222 2315 : if (str != NULL) {
223 3 : pdb_set_fullname(sam, str, PDB_SET);
224 : }
225 :
226 2315 : str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
227 : NULL);
228 2315 : if (str != NULL) {
229 3 : pdb_set_homedir(sam, str, PDB_SET);
230 : }
231 :
232 2315 : str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
233 2315 : if (str != NULL) {
234 13 : pdb_set_dir_drive(sam, str, PDB_SET);
235 : }
236 :
237 2315 : str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
238 2315 : if (str != NULL) {
239 3 : pdb_set_logon_script(sam, str, PDB_SET);
240 : }
241 :
242 2315 : str = ldb_msg_find_attr_as_string(msg, "profilePath",
243 : NULL);
244 2315 : if (str != NULL) {
245 3 : pdb_set_profile_path(sam, str, PDB_SET);
246 : }
247 :
248 2315 : str = ldb_msg_find_attr_as_string(msg, "comment",
249 : NULL);
250 2315 : if (str != NULL) {
251 0 : pdb_set_comment(sam, str, PDB_SET);
252 : }
253 :
254 2315 : str = ldb_msg_find_attr_as_string(msg, "description",
255 : NULL);
256 2315 : if (str != NULL) {
257 2294 : pdb_set_acct_desc(sam, str, PDB_SET);
258 : }
259 :
260 2315 : str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
261 : NULL);
262 2315 : if (str != NULL) {
263 0 : pdb_set_workstations(sam, str, PDB_SET);
264 : }
265 :
266 2315 : blob = ldb_msg_find_ldb_val(msg, "userParameters");
267 2315 : if (blob != NULL) {
268 0 : str = base64_encode_data_blob(frame, *blob);
269 0 : if (str == NULL) {
270 0 : DEBUG(0, ("base64_encode_data_blob() failed\n"));
271 0 : goto fail;
272 : }
273 0 : pdb_set_munged_dial(sam, str, PDB_SET);
274 : }
275 :
276 2315 : sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
277 2315 : if (!sid) {
278 0 : DEBUG(10, ("Could not pull SID\n"));
279 0 : goto fail;
280 : }
281 2315 : pdb_set_user_sid(sam, sid, PDB_SET);
282 :
283 2315 : n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
284 2315 : if (n == 0) {
285 0 : DEBUG(10, ("Could not pull userAccountControl\n"));
286 0 : goto fail;
287 : }
288 2315 : pdb_set_acct_ctrl(sam, n, PDB_SET);
289 :
290 2315 : blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
291 2315 : if (blob) {
292 2314 : if (blob->length != NT_HASH_LEN) {
293 0 : DEBUG(0, ("Got NT hash of length %d, expected %d\n",
294 : (int)blob->length, NT_HASH_LEN));
295 0 : goto fail;
296 : }
297 2314 : pdb_set_nt_passwd(sam, blob->data, PDB_SET);
298 : }
299 :
300 2315 : blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
301 2315 : if (blob) {
302 3 : if (blob->length != LM_HASH_LEN) {
303 0 : DEBUG(0, ("Got LM hash of length %d, expected %d\n",
304 : (int)blob->length, LM_HASH_LEN));
305 0 : goto fail;
306 : }
307 3 : pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
308 : }
309 :
310 2315 : n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
311 2315 : if (n == 0) {
312 0 : DEBUG(10, ("Could not pull primaryGroupID\n"));
313 0 : goto fail;
314 : }
315 2315 : sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
316 2315 : pdb_set_group_sid(sam, &group_sid, PDB_SET);
317 :
318 2315 : status = NT_STATUS_OK;
319 2315 : fail:
320 2315 : TALLOC_FREE(frame);
321 2315 : return status;
322 : }
323 :
324 9 : static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
325 : const char *attrib, time_t t)
326 : {
327 : uint64_t nt_time;
328 :
329 9 : unix_to_nt_time(&nt_time, t);
330 :
331 9 : return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
332 : }
333 :
334 11 : static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
335 : bool (*need_update)(const struct samu *,
336 : enum pdb_elements),
337 : struct ldb_dn *dn,
338 : struct samu *sam)
339 : {
340 11 : TALLOC_CTX *frame = talloc_stackframe();
341 11 : int ret = LDB_SUCCESS;
342 : const char *pw;
343 : struct ldb_message *msg;
344 : struct ldb_request *req;
345 11 : uint32_t dsdb_flags = 0;
346 : /* TODO: All fields :-) */
347 :
348 11 : msg = ldb_msg_new(frame);
349 11 : if (!msg) {
350 0 : talloc_free(frame);
351 0 : return false;
352 : }
353 :
354 11 : msg->dn = dn;
355 :
356 : /* build modify request */
357 11 : ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
358 : ldb_op_default_callback,
359 : NULL);
360 11 : if (ret != LDB_SUCCESS) {
361 0 : talloc_free(frame);
362 0 : return ret;
363 : }
364 :
365 : /* If we set a plaintext password, the system will
366 : * force the pwdLastSet to now() */
367 11 : if (need_update(sam, PDB_PASSLASTSET)) {
368 6 : dsdb_flags |= DSDB_PASSWORD_BYPASS_LAST_SET;
369 :
370 6 : ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
371 : pdb_get_pass_last_set_time(sam));
372 : }
373 :
374 11 : pw = pdb_get_plaintext_passwd(sam);
375 11 : if (need_update(sam, PDB_PLAINTEXT_PW)) {
376 : struct ldb_val pw_utf16;
377 3 : if (pw == NULL) {
378 0 : talloc_free(frame);
379 0 : return LDB_ERR_OPERATIONS_ERROR;
380 : }
381 :
382 3 : if (!convert_string_talloc(msg,
383 : CH_UNIX, CH_UTF16,
384 : pw, strlen(pw),
385 : (void *)&pw_utf16.data,
386 : &pw_utf16.length)) {
387 0 : talloc_free(frame);
388 0 : return LDB_ERR_OPERATIONS_ERROR;
389 : }
390 3 : ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
391 : } else {
392 8 : bool changed_lm_pw = false;
393 8 : bool changed_nt_pw = false;
394 8 : bool changed_history = false;
395 8 : if (need_update(sam, PDB_LMPASSWD)) {
396 : struct ldb_val val;
397 1 : val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
398 1 : if (!val.data) {
399 0 : samdb_msg_add_delete(state->ldb, msg, msg,
400 : "dBCSPwd");
401 : } else {
402 1 : val.length = LM_HASH_LEN;
403 1 : ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
404 : }
405 1 : changed_lm_pw = true;
406 : }
407 8 : if (need_update(sam, PDB_NTPASSWD)) {
408 : struct ldb_val val;
409 2 : val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
410 2 : if (!val.data) {
411 0 : samdb_msg_add_delete(state->ldb, msg, msg,
412 : "unicodePwd");
413 : } else {
414 2 : val.length = NT_HASH_LEN;
415 2 : ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
416 : }
417 2 : changed_nt_pw = true;
418 : }
419 :
420 : /* Try to ensure we don't get out of sync */
421 8 : if (changed_lm_pw && !changed_nt_pw) {
422 0 : samdb_msg_add_delete(state->ldb, msg, msg,
423 : "unicodePwd");
424 8 : } else if (changed_nt_pw && !changed_lm_pw) {
425 1 : samdb_msg_add_delete(state->ldb, msg, msg,
426 : "dBCSPwd");
427 : }
428 8 : if (changed_lm_pw || changed_nt_pw) {
429 2 : samdb_msg_add_delete(state->ldb, msg, msg,
430 : "supplementalCredentials");
431 :
432 : }
433 :
434 8 : if (need_update(sam, PDB_PWHISTORY)) {
435 : uint32_t current_hist_len;
436 2 : const uint8_t *history = pdb_get_pw_history(sam, ¤t_hist_len);
437 :
438 2 : bool invalid_history = false;
439 2 : struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
440 : current_hist_len);
441 2 : if (!history) {
442 2 : invalid_history = true;
443 : } else {
444 : unsigned int i;
445 : /* Parse the history into the correct format */
446 0 : for (i = 0; i < current_hist_len; i++) {
447 0 : if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
448 : 16)) {
449 : /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
450 0 : invalid_history = true;
451 0 : break;
452 : }
453 : /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
454 0 : memcpy(history_hashes[i].hash,
455 0 : &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
456 : sizeof(history_hashes[i].hash));
457 : }
458 : }
459 2 : if (invalid_history) {
460 2 : ret |= samdb_msg_add_delete(state->ldb, msg, msg,
461 : "ntPwdHistory");
462 :
463 2 : ret |= samdb_msg_add_delete(state->ldb, msg, msg,
464 : "lmPwdHistory");
465 : } else {
466 0 : ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
467 : "ntPwdHistory",
468 : history_hashes,
469 : current_hist_len);
470 : }
471 2 : changed_history = true;
472 : }
473 8 : if (changed_lm_pw || changed_nt_pw || changed_history) {
474 : /* These attributes can only be modified directly by using a special control */
475 2 : dsdb_flags |= DSDB_BYPASS_PASSWORD_HASH;
476 : }
477 : }
478 :
479 : /* PDB_USERSID is only allowed on ADD, handled in caller */
480 11 : if (need_update(sam, PDB_GROUPSID)) {
481 0 : const struct dom_sid *sid = pdb_get_group_sid(sam);
482 : uint32_t rid;
483 0 : NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
484 0 : if (!NT_STATUS_IS_OK(status)) {
485 0 : talloc_free(frame);
486 0 : return LDB_ERR_OPERATIONS_ERROR;
487 : }
488 0 : if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
489 0 : talloc_free(frame);
490 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
491 : }
492 0 : ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
493 : }
494 11 : if (need_update(sam, PDB_FULLNAME)) {
495 1 : ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
496 : }
497 :
498 11 : if (need_update(sam, PDB_SMBHOME)) {
499 1 : ret |= ldb_msg_add_string(msg, "homeDirectory",
500 : pdb_get_homedir(sam));
501 : }
502 :
503 11 : if (need_update(sam, PDB_PROFILE)) {
504 1 : ret |= ldb_msg_add_string(msg, "profilePath",
505 : pdb_get_profile_path(sam));
506 : }
507 :
508 11 : if (need_update(sam, PDB_DRIVE)) {
509 1 : ret |= ldb_msg_add_string(msg, "homeDrive",
510 : pdb_get_dir_drive(sam));
511 : }
512 :
513 11 : if (need_update(sam, PDB_LOGONSCRIPT)) {
514 1 : ret |= ldb_msg_add_string(msg, "scriptPath",
515 : pdb_get_logon_script(sam));
516 : }
517 :
518 11 : if (need_update(sam, PDB_KICKOFFTIME)) {
519 1 : ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
520 : pdb_get_kickoff_time(sam));
521 : }
522 :
523 11 : if (need_update(sam, PDB_LOGONTIME)) {
524 1 : ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
525 : pdb_get_logon_time(sam));
526 : }
527 :
528 11 : if (need_update(sam, PDB_LOGOFFTIME)) {
529 1 : ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
530 : pdb_get_logoff_time(sam));
531 : }
532 :
533 11 : if (need_update(sam, PDB_USERNAME)) {
534 1 : ret |= ldb_msg_add_string(msg, "samAccountName",
535 : pdb_get_username(sam));
536 : }
537 :
538 11 : if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
539 0 : struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
540 0 : ret |= ldb_msg_add_value(msg, "logonHours",
541 : &hours, NULL);
542 : }
543 :
544 11 : if (need_update(sam, PDB_ACCTCTRL)) {
545 7 : ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
546 : "userAccountControl", pdb_get_acct_ctrl(sam));
547 : }
548 :
549 11 : if (need_update(sam, PDB_COMMENT)) {
550 0 : ret |= ldb_msg_add_string(msg, "comment",
551 : pdb_get_comment(sam));
552 : }
553 :
554 11 : if (need_update(sam, PDB_ACCTDESC)) {
555 0 : ret |= ldb_msg_add_string(msg, "description",
556 : pdb_get_acct_desc(sam));
557 : }
558 :
559 11 : if (need_update(sam, PDB_WORKSTATIONS)) {
560 0 : ret |= ldb_msg_add_string(msg, "userWorkstations",
561 : pdb_get_workstations(sam));
562 : }
563 :
564 : /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
565 11 : if (need_update(sam, PDB_MUNGEDDIAL)) {
566 0 : const char *base64_munged_dial = NULL;
567 :
568 0 : base64_munged_dial = pdb_get_munged_dial(sam);
569 0 : if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
570 : struct ldb_val blob;
571 :
572 0 : blob = base64_decode_data_blob_talloc(msg,
573 : base64_munged_dial);
574 0 : if (blob.data == NULL) {
575 0 : DEBUG(0, ("Failed to decode userParameters from "
576 : "munged dialback string[%s] for %s\n",
577 : base64_munged_dial,
578 : ldb_dn_get_linearized(msg->dn)));
579 0 : talloc_free(frame);
580 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
581 : }
582 0 : ret |= ldb_msg_add_steal_value(msg, "userParameters",
583 : &blob);
584 : }
585 : }
586 :
587 11 : if (need_update(sam, PDB_COUNTRY_CODE)) {
588 0 : ret |= ldb_msg_add_fmt(msg, "countryCode",
589 0 : "%i", (int)pdb_get_country_code(sam));
590 : }
591 :
592 11 : if (need_update(sam, PDB_CODE_PAGE)) {
593 0 : ret |= ldb_msg_add_fmt(msg, "codePage",
594 0 : "%i", (int)pdb_get_code_page(sam));
595 : }
596 :
597 : /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
598 : PDB_BAD_PASSWORD_TIME,
599 : PDB_CANCHANGETIME, - these are calculated per policy, not stored
600 : PDB_DOMAIN,
601 : PDB_NTUSERNAME, - this makes no sense, and never really did
602 : PDB_LOGONDIVS,
603 : PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
604 : PDB_FIELDS_PRESENT,
605 : PDB_BAD_PASSWORD_COUNT,
606 : PDB_LOGON_COUNT,
607 : PDB_UNKNOWN6,
608 : PDB_BACKEND_PRIVATE_DATA,
609 :
610 : */
611 11 : if (ret != LDB_SUCCESS) {
612 0 : talloc_free(frame);
613 0 : return LDB_ERR_OPERATIONS_ERROR;
614 : }
615 :
616 11 : if (msg->num_elements == 0) {
617 1 : talloc_free(frame);
618 : /* Nothing to do, just return success */
619 1 : return LDB_SUCCESS;
620 : }
621 :
622 10 : ret = dsdb_replace(state->ldb, msg, dsdb_flags);
623 :
624 10 : if (ret != LDB_SUCCESS) {
625 0 : DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
626 : ldb_dn_get_linearized(msg->dn),
627 : ldb_errstring(state->ldb)));
628 : }
629 :
630 10 : talloc_free(frame);
631 10 : return ret;
632 : }
633 :
634 2316 : static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
635 : const char *filter,
636 : TALLOC_CTX *mem_ctx,
637 : struct ldb_message **msg)
638 : {
639 2316 : const char * attrs[] = {
640 : "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
641 : "sAMAccountName", "displayName", "homeDirectory",
642 : "homeDrive", "scriptPath", "profilePath", "description",
643 : "userWorkstations", "comment", "userParameters", "objectSid",
644 : "primaryGroupID", "userAccountControl",
645 : "msDS-User-Account-Control-Computed", "logonHours",
646 : "badPwdCount", "logonCount", "countryCode", "codePage",
647 : "unicodePwd", "dBCSPwd", NULL };
648 :
649 2316 : int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
650 2316 : if (rc != LDB_SUCCESS) {
651 1 : DEBUG(10, ("ldap_search failed %s\n",
652 : ldb_errstring(state->ldb)));
653 1 : return NT_STATUS_LDAP(rc);
654 : }
655 :
656 2315 : return NT_STATUS_OK;
657 : }
658 :
659 : static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
660 : struct pdb_samba_dsdb_state *state,
661 : struct samu *sam_acct,
662 : const char *exp_fmt, ...)
663 : PRINTF_ATTRIBUTE(4,5);
664 :
665 2316 : static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
666 : struct pdb_samba_dsdb_state *state,
667 : struct samu *sam_acct,
668 : const char *exp_fmt, ...)
669 : {
670 : struct ldb_message *priv;
671 : NTSTATUS status;
672 : va_list ap;
673 2316 : char *expression = NULL;
674 2316 : TALLOC_CTX *tmp_ctx = talloc_new(state);
675 2316 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
676 :
677 2316 : va_start(ap, exp_fmt);
678 2316 : expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
679 2316 : va_end(ap);
680 :
681 2316 : if (!expression) {
682 0 : talloc_free(tmp_ctx);
683 0 : return NT_STATUS_NO_MEMORY;
684 : }
685 :
686 2316 : status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
687 2316 : talloc_free(tmp_ctx);
688 2316 : if (!NT_STATUS_IS_OK(status)) {
689 1 : DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
690 : nt_errstr(status)));
691 1 : return status;
692 : }
693 :
694 2315 : status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
695 2315 : if (!NT_STATUS_IS_OK(status)) {
696 0 : DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
697 : nt_errstr(status)));
698 0 : TALLOC_FREE(priv);
699 0 : return status;
700 : }
701 :
702 2315 : pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
703 2315 : return NT_STATUS_OK;
704 : }
705 :
706 18 : static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
707 : struct samu *sam_acct,
708 : const char *username)
709 : {
710 18 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
711 : m->private_data, struct pdb_samba_dsdb_state);
712 :
713 18 : return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
714 : "(&(samaccountname=%s)(objectclass=user))",
715 : username);
716 : }
717 :
718 2298 : static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
719 : struct samu *sam_acct,
720 : const struct dom_sid *sid)
721 : {
722 : NTSTATUS status;
723 2298 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
724 : m->private_data, struct pdb_samba_dsdb_state);
725 : struct dom_sid_buf buf;
726 :
727 2298 : status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
728 : "(&(objectsid=%s)(objectclass=user))",
729 : dom_sid_str_buf(sid, &buf));
730 2298 : return status;
731 : }
732 :
733 1 : static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
734 : TALLOC_CTX *mem_ctx,
735 : const char *name, uint32_t acct_flags,
736 : uint32_t *rid)
737 : {
738 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
739 : m->private_data, struct pdb_samba_dsdb_state);
740 : struct dom_sid *sid;
741 : struct ldb_dn *dn;
742 : NTSTATUS status;
743 1 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
744 1 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
745 :
746 : /* Internally this uses transactions to ensure all the steps
747 : * happen or fail as one */
748 1 : status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
749 : &sid, &dn);
750 1 : if (!NT_STATUS_IS_OK(status)) {
751 0 : talloc_free(tmp_ctx);
752 0 : return status;
753 : }
754 1 : sid_peek_rid(sid, rid);
755 1 : talloc_free(tmp_ctx);
756 1 : return NT_STATUS_OK;
757 : }
758 :
759 2 : static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
760 : TALLOC_CTX *mem_ctx,
761 : struct samu *sam)
762 : {
763 2 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
764 : m->private_data, struct pdb_samba_dsdb_state);
765 : struct ldb_dn *dn;
766 : int rc;
767 : struct dom_sid_buf buf;
768 2 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
769 2 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
770 :
771 2 : dn = ldb_dn_new_fmt(
772 : tmp_ctx,
773 : state->ldb,
774 : "<SID=%s>",
775 : dom_sid_str_buf(pdb_get_user_sid(sam), &buf));
776 2 : if (!dn || !ldb_dn_validate(dn)) {
777 0 : talloc_free(tmp_ctx);
778 0 : return NT_STATUS_NO_MEMORY;
779 : }
780 2 : rc = ldb_delete(state->ldb, dn);
781 :
782 2 : if (rc != LDB_SUCCESS) {
783 0 : DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
784 : ldb_errstring(state->ldb)));
785 0 : talloc_free(tmp_ctx);
786 0 : return NT_STATUS_LDAP(rc);
787 : }
788 2 : talloc_free(tmp_ctx);
789 2 : return NT_STATUS_OK;
790 : }
791 :
792 : /* This interface takes a fully populated struct samu and places it in
793 : * the database. This is not implemented at this time as we need to
794 : * be careful around the creation of arbitrary SIDs (ie, we must ensure
795 : * they are not left in a RID pool */
796 1 : static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
797 : struct samu *sampass)
798 : {
799 : int ret;
800 : NTSTATUS status;
801 : struct ldb_dn *dn;
802 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
803 : m->private_data, struct pdb_samba_dsdb_state);
804 1 : uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
805 1 : const char *username = pdb_get_username(sampass);
806 1 : const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
807 1 : TALLOC_CTX *tframe = talloc_stackframe();
808 :
809 1 : acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
810 :
811 1 : ret = ldb_transaction_start(state->ldb);
812 1 : if (ret != LDB_SUCCESS) {
813 0 : talloc_free(tframe);
814 0 : return NT_STATUS_LOCK_NOT_GRANTED;
815 : }
816 :
817 1 : status = dsdb_add_user(state->ldb, talloc_tos(), username,
818 : acb_flags, user_sid, NULL, &dn);
819 1 : if (!NT_STATUS_IS_OK(status)) {
820 0 : ldb_transaction_cancel(state->ldb);
821 0 : talloc_free(tframe);
822 0 : return status;
823 : }
824 :
825 1 : ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
826 : dn, sampass);
827 1 : if (ret != LDB_SUCCESS) {
828 0 : ldb_transaction_cancel(state->ldb);
829 0 : talloc_free(tframe);
830 0 : return dsdb_ldb_err_to_ntstatus(ret);
831 : }
832 :
833 1 : ret = ldb_transaction_commit(state->ldb);
834 1 : if (ret != LDB_SUCCESS) {
835 0 : DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
836 : ldb_dn_get_linearized(dn),
837 : ldb_errstring(state->ldb)));
838 0 : talloc_free(tframe);
839 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
840 : }
841 1 : talloc_free(tframe);
842 1 : return NT_STATUS_OK;
843 : }
844 :
845 : /*
846 : * Update the Samba_Dsdb LDB with the changes from a struct samu.
847 : *
848 : * This takes care not to update elements that have not been changed
849 : * by the caller
850 : */
851 10 : static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
852 : struct samu *sam)
853 : {
854 10 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
855 : m->private_data, struct pdb_samba_dsdb_state);
856 10 : struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
857 : m, sam);
858 : int ret;
859 :
860 10 : ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
861 : sam);
862 10 : return dsdb_ldb_err_to_ntstatus(ret);
863 : }
864 :
865 2 : static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
866 : struct samu *username)
867 : {
868 : NTSTATUS status;
869 2 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
870 2 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
871 2 : status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
872 2 : talloc_free(tmp_ctx);
873 2 : return status;
874 : }
875 :
876 0 : static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
877 : struct samu *oldname,
878 : const char *newname)
879 : {
880 0 : return NT_STATUS_NOT_IMPLEMENTED;
881 : }
882 :
883 : /* This is not implemented, as this module is expected to be used
884 : * with auth_samba_dsdb, and this is responsible for login counters etc
885 : *
886 : */
887 1 : static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
888 : struct samu *sam_acct,
889 : bool success)
890 : {
891 1 : return NT_STATUS_NOT_IMPLEMENTED;
892 : }
893 :
894 : static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
895 : GROUP_MAP *map,
896 : const char *exp_fmt, ...)
897 : PRINTF_ATTRIBUTE(3,4);
898 :
899 2001 : static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
900 : const char *exp_fmt, ...)
901 : {
902 2001 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
903 : m->private_data, struct pdb_samba_dsdb_state);
904 2001 : const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
905 : NULL };
906 : struct ldb_message *msg;
907 : va_list ap;
908 2001 : char *expression = NULL;
909 : struct dom_sid *sid;
910 : const char *str;
911 : int rc;
912 : struct id_map id_map;
913 : struct id_map *id_maps[2];
914 2001 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
915 2001 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
916 :
917 2001 : va_start(ap, exp_fmt);
918 2001 : expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
919 2001 : va_end(ap);
920 :
921 2001 : if (!expression) {
922 0 : talloc_free(tmp_ctx);
923 0 : return NT_STATUS_NO_MEMORY;
924 : }
925 :
926 2001 : rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
927 2001 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
928 0 : talloc_free(tmp_ctx);
929 0 : return NT_STATUS_NO_SUCH_GROUP;
930 2001 : } else if (rc != LDB_SUCCESS) {
931 0 : talloc_free(tmp_ctx);
932 0 : DEBUG(10, ("dsdb_search_one failed %s\n",
933 : ldb_errstring(state->ldb)));
934 0 : return NT_STATUS_LDAP(rc);
935 : }
936 :
937 2001 : sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
938 2001 : if (!sid) {
939 0 : talloc_free(tmp_ctx);
940 0 : DEBUG(10, ("Could not pull SID\n"));
941 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
942 : }
943 :
944 2001 : map->sid = *sid;
945 :
946 2001 : if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
947 : NTSTATUS status;
948 2001 : uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
949 2001 : switch (grouptype) {
950 2001 : case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
951 : case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
952 2001 : map->sid_name_use = SID_NAME_ALIAS;
953 2001 : break;
954 0 : case GTYPE_SECURITY_GLOBAL_GROUP:
955 0 : map->sid_name_use = SID_NAME_DOM_GRP;
956 0 : break;
957 0 : default:
958 0 : talloc_free(tmp_ctx);
959 0 : DEBUG(10, ("Could not pull groupType\n"));
960 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
961 : }
962 :
963 2001 : ZERO_STRUCT(id_map);
964 2001 : id_map.sid = sid;
965 2001 : id_maps[0] = &id_map;
966 2001 : id_maps[1] = NULL;
967 :
968 2001 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
969 :
970 2001 : if (!NT_STATUS_IS_OK(status)) {
971 0 : talloc_free(tmp_ctx);
972 0 : return status;
973 : }
974 2001 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
975 2001 : map->gid = id_map.xid.id;
976 : } else {
977 0 : DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
978 0 : talloc_free(tmp_ctx);
979 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
980 : }
981 0 : } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
982 0 : DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
983 0 : talloc_free(tmp_ctx);
984 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
985 : }
986 :
987 2001 : str = ldb_msg_find_attr_as_string(msg, "samAccountName",
988 : NULL);
989 2001 : if (str == NULL) {
990 0 : talloc_free(tmp_ctx);
991 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
992 : }
993 2001 : map->nt_name = talloc_strdup(map, str);
994 2001 : if (!map->nt_name) {
995 0 : talloc_free(tmp_ctx);
996 0 : return NT_STATUS_NO_MEMORY;
997 : }
998 :
999 2001 : str = ldb_msg_find_attr_as_string(msg, "description",
1000 : NULL);
1001 2001 : if (str != NULL) {
1002 2001 : map->comment = talloc_strdup(map, str);
1003 : } else {
1004 0 : map->comment = talloc_strdup(map, "");
1005 : }
1006 2001 : if (!map->comment) {
1007 0 : talloc_free(tmp_ctx);
1008 0 : return NT_STATUS_NO_MEMORY;
1009 : }
1010 :
1011 2001 : talloc_free(tmp_ctx);
1012 2001 : return NT_STATUS_OK;
1013 : }
1014 :
1015 2001 : static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1016 : struct dom_sid sid)
1017 : {
1018 : char *filter;
1019 : NTSTATUS status;
1020 : struct dom_sid_buf buf;
1021 :
1022 2001 : filter = talloc_asprintf(talloc_tos(),
1023 : "(&(objectsid=%s)(objectclass=group))",
1024 : dom_sid_str_buf(&sid, &buf));
1025 2001 : if (filter == NULL) {
1026 0 : return NT_STATUS_NO_MEMORY;
1027 : }
1028 :
1029 2001 : status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1030 2001 : TALLOC_FREE(filter);
1031 2001 : return status;
1032 : }
1033 :
1034 0 : static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1035 : gid_t gid)
1036 : {
1037 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1038 : m->private_data, struct pdb_samba_dsdb_state);
1039 : NTSTATUS status;
1040 : struct id_map id_map;
1041 : struct id_map *id_maps[2];
1042 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1043 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1044 :
1045 0 : id_map.xid.id = gid;
1046 0 : id_map.xid.type = ID_TYPE_GID;
1047 0 : id_maps[0] = &id_map;
1048 0 : id_maps[1] = NULL;
1049 :
1050 0 : status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1051 0 : if (!NT_STATUS_IS_OK(status)) {
1052 0 : talloc_free(tmp_ctx);
1053 0 : return status;
1054 : }
1055 0 : status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1056 0 : talloc_free(tmp_ctx);
1057 0 : return status;
1058 : }
1059 :
1060 0 : static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1061 : const char *name)
1062 : {
1063 : char *filter;
1064 : NTSTATUS status;
1065 :
1066 0 : filter = talloc_asprintf(talloc_tos(),
1067 : "(&(samaccountname=%s)(objectclass=group))",
1068 : name);
1069 0 : if (filter == NULL) {
1070 0 : return NT_STATUS_NO_MEMORY;
1071 : }
1072 :
1073 0 : status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1074 0 : TALLOC_FREE(filter);
1075 0 : return status;
1076 : }
1077 :
1078 0 : static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1079 : TALLOC_CTX *mem_ctx, const char *name,
1080 : uint32_t *rid)
1081 : {
1082 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1083 : m->private_data, struct pdb_samba_dsdb_state);
1084 : NTSTATUS status;
1085 : struct dom_sid *sid;
1086 : struct ldb_dn *dn;
1087 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1088 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1089 :
1090 0 : status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1091 0 : if (!NT_STATUS_IS_OK(status)) {
1092 0 : talloc_free(tmp_ctx);
1093 0 : return status;
1094 : }
1095 :
1096 0 : sid_peek_rid(sid, rid);
1097 0 : talloc_free(tmp_ctx);
1098 0 : return NT_STATUS_OK;
1099 : }
1100 :
1101 0 : static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1102 : TALLOC_CTX *mem_ctx, uint32_t rid)
1103 : {
1104 0 : const char *attrs[] = { NULL };
1105 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1106 : m->private_data, struct pdb_samba_dsdb_state);
1107 : struct dom_sid sid;
1108 : struct ldb_message *msg;
1109 : struct ldb_dn *dn;
1110 : int rc;
1111 : struct dom_sid_buf buf;
1112 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1113 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1114 :
1115 0 : sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1116 :
1117 0 : if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1118 0 : DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1119 0 : return NT_STATUS_INTERNAL_ERROR;
1120 : }
1121 :
1122 0 : dn = ldb_dn_new_fmt(
1123 : tmp_ctx,
1124 : state->ldb,
1125 : "<SID=%s>",
1126 : dom_sid_str_buf(&sid, &buf));
1127 0 : if (!dn || !ldb_dn_validate(dn)) {
1128 0 : talloc_free(tmp_ctx);
1129 0 : ldb_transaction_cancel(state->ldb);
1130 0 : return NT_STATUS_NO_MEMORY;
1131 : }
1132 0 : rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1133 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1134 0 : talloc_free(tmp_ctx);
1135 0 : ldb_transaction_cancel(state->ldb);
1136 0 : return NT_STATUS_NO_SUCH_GROUP;
1137 : }
1138 0 : rc = ldb_delete(state->ldb, dn);
1139 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1140 0 : talloc_free(tmp_ctx);
1141 0 : ldb_transaction_cancel(state->ldb);
1142 0 : return NT_STATUS_NO_SUCH_GROUP;
1143 0 : } else if (rc != LDB_SUCCESS) {
1144 0 : DEBUG(10, ("ldb_delete failed %s\n",
1145 : ldb_errstring(state->ldb)));
1146 0 : ldb_transaction_cancel(state->ldb);
1147 0 : return NT_STATUS_LDAP(rc);
1148 : }
1149 :
1150 0 : if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1151 0 : DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1152 0 : return NT_STATUS_INTERNAL_ERROR;
1153 : }
1154 0 : return NT_STATUS_OK;
1155 : }
1156 :
1157 0 : static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1158 : GROUP_MAP *map)
1159 : {
1160 0 : return NT_STATUS_NOT_IMPLEMENTED;
1161 : }
1162 :
1163 0 : static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1164 : GROUP_MAP *map)
1165 : {
1166 0 : return NT_STATUS_NOT_IMPLEMENTED;
1167 : }
1168 :
1169 0 : static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1170 : struct dom_sid sid)
1171 : {
1172 0 : return NT_STATUS_NOT_IMPLEMENTED;
1173 : }
1174 :
1175 0 : static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1176 : const struct dom_sid *sid,
1177 : enum lsa_SidType sid_name_use,
1178 : GROUP_MAP ***pp_rmap,
1179 : size_t *p_num_entries,
1180 : bool unix_only)
1181 : {
1182 0 : return NT_STATUS_NOT_IMPLEMENTED;
1183 : }
1184 :
1185 0 : static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1186 : TALLOC_CTX *mem_ctx,
1187 : const struct dom_sid *group,
1188 : uint32_t **pmembers,
1189 : size_t *pnum_members)
1190 : {
1191 : unsigned int i, num_sids, num_members;
1192 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1193 : m->private_data, struct pdb_samba_dsdb_state);
1194 : struct dom_sid *members_as_sids;
1195 : struct dom_sid *dom_sid;
1196 : uint32_t *members;
1197 : struct ldb_dn *dn;
1198 : NTSTATUS status;
1199 : struct dom_sid_buf buf;
1200 :
1201 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1202 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1203 :
1204 0 : dn = ldb_dn_new_fmt(
1205 : tmp_ctx,
1206 : state->ldb,
1207 : "<SID=%s>",
1208 : dom_sid_str_buf(group, &buf));
1209 0 : if (!dn || !ldb_dn_validate(dn)) {
1210 0 : return NT_STATUS_NO_MEMORY;
1211 : }
1212 :
1213 0 : status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1214 0 : if (!NT_STATUS_IS_OK(status)) {
1215 0 : talloc_free(tmp_ctx);
1216 0 : return status;
1217 : }
1218 0 : status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1219 0 : if (!NT_STATUS_IS_OK(status)) {
1220 0 : talloc_free(tmp_ctx);
1221 0 : return status;
1222 : }
1223 :
1224 0 : *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1225 0 : if (*pmembers == NULL) {
1226 0 : TALLOC_FREE(tmp_ctx);
1227 0 : return NT_STATUS_NO_MEMORY;
1228 : }
1229 0 : num_members = 0;
1230 :
1231 0 : for (i = 0; i < num_sids; i++) {
1232 0 : if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1233 0 : continue;
1234 : }
1235 0 : status = dom_sid_split_rid(NULL, &members_as_sids[i],
1236 0 : NULL, &members[num_members]);
1237 0 : if (!NT_STATUS_IS_OK(status)) {
1238 0 : talloc_free(tmp_ctx);
1239 0 : return status;
1240 : }
1241 0 : num_members++;
1242 : }
1243 0 : *pnum_members = num_members;
1244 0 : return NT_STATUS_OK;
1245 : }
1246 :
1247 : /* Just convert the primary group SID into a group */
1248 0 : static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1249 : TALLOC_CTX *mem_ctx,
1250 : struct samu *user,
1251 : struct dom_sid **pp_sids,
1252 : gid_t **pp_gids,
1253 : uint32_t *p_num_groups)
1254 : {
1255 : NTSTATUS status;
1256 0 : size_t num_groups = 0;
1257 0 : struct dom_sid *group_sids = NULL;
1258 0 : gid_t *gids = NULL;
1259 : TALLOC_CTX *tmp_ctx;
1260 :
1261 0 : tmp_ctx = talloc_new(mem_ctx);
1262 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1263 :
1264 0 : if (user->group_sid) {
1265 : struct id_map *id_maps[2];
1266 : struct id_map id_map;
1267 :
1268 0 : num_groups = 1;
1269 :
1270 0 : group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1271 0 : if (group_sids == NULL) {
1272 0 : talloc_free(tmp_ctx);
1273 0 : return NT_STATUS_NO_MEMORY;
1274 : }
1275 0 : gids = talloc_array(tmp_ctx, gid_t, num_groups);
1276 0 : if (gids == NULL) {
1277 0 : talloc_free(tmp_ctx);
1278 0 : return NT_STATUS_NO_MEMORY;
1279 : }
1280 :
1281 0 : group_sids[0] = *user->group_sid;
1282 :
1283 0 : ZERO_STRUCT(id_map);
1284 0 : id_map.sid = &group_sids[0];
1285 0 : id_maps[0] = &id_map;
1286 0 : id_maps[1] = NULL;
1287 :
1288 0 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1289 0 : if (!NT_STATUS_IS_OK(status)) {
1290 0 : talloc_free(tmp_ctx);
1291 0 : return status;
1292 : }
1293 0 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1294 0 : gids[0] = id_map.xid.id;
1295 : } else {
1296 : struct dom_sid_buf buf1, buf2;
1297 0 : DEBUG(1, (__location__
1298 : "Group %s, of which %s is a member, could not be converted to a GID\n",
1299 : dom_sid_str_buf(&group_sids[0], &buf1),
1300 : dom_sid_str_buf(&user->user_sid, &buf2)));
1301 0 : talloc_free(tmp_ctx);
1302 : /* We must error out, otherwise a user might
1303 : * avoid a DENY acl based on a group they
1304 : * missed out on */
1305 0 : return NT_STATUS_NO_SUCH_GROUP;
1306 : }
1307 : }
1308 :
1309 0 : *pp_sids = talloc_steal(mem_ctx, group_sids);
1310 0 : *pp_gids = talloc_steal(mem_ctx, gids);
1311 0 : *p_num_groups = num_groups;
1312 0 : talloc_free(tmp_ctx);
1313 0 : return NT_STATUS_OK;
1314 : }
1315 :
1316 2295 : static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1317 : TALLOC_CTX *mem_ctx,
1318 : struct samu *user,
1319 : struct dom_sid **pp_sids,
1320 : gid_t **pp_gids,
1321 : uint32_t *p_num_groups)
1322 : {
1323 2295 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1324 : m->private_data, struct pdb_samba_dsdb_state);
1325 2295 : struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1326 : m, user);
1327 2295 : const char *attrs[] = { "tokenGroups", NULL};
1328 : struct ldb_message *tokengroups_msg;
1329 : struct ldb_message_element *tokengroups;
1330 : int i, rc;
1331 : NTSTATUS status;
1332 2295 : unsigned int count = 0;
1333 : size_t num_groups;
1334 : struct dom_sid *group_sids;
1335 : gid_t *gids;
1336 : TALLOC_CTX *tmp_ctx;
1337 :
1338 2295 : if (msg == NULL) {
1339 : /* Fake up some things here */
1340 0 : return fake_enum_group_memberships(state,
1341 : mem_ctx,
1342 : user, pp_sids,
1343 : pp_gids, p_num_groups);
1344 : }
1345 :
1346 2295 : tmp_ctx = talloc_new(mem_ctx);
1347 2295 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1348 :
1349 2295 : rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1350 :
1351 2295 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1352 0 : talloc_free(tmp_ctx);
1353 0 : return NT_STATUS_NO_SUCH_USER;
1354 2295 : } else if (rc != LDB_SUCCESS) {
1355 0 : DEBUG(10, ("dsdb_search_one failed %s\n",
1356 : ldb_errstring(state->ldb)));
1357 0 : talloc_free(tmp_ctx);
1358 0 : return NT_STATUS_LDAP(rc);
1359 : }
1360 :
1361 2295 : tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1362 :
1363 2295 : if (tokengroups) {
1364 2295 : count = tokengroups->num_values;
1365 : }
1366 :
1367 2295 : group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1368 2295 : if (group_sids == NULL) {
1369 0 : talloc_free(tmp_ctx);
1370 0 : return NT_STATUS_NO_MEMORY;
1371 : }
1372 2295 : gids = talloc_array(tmp_ctx, gid_t, count);
1373 2295 : if (gids == NULL) {
1374 0 : talloc_free(tmp_ctx);
1375 0 : return NT_STATUS_NO_MEMORY;
1376 : }
1377 2295 : num_groups = 0;
1378 :
1379 32820 : for (i=0; i<count; i++) {
1380 : struct id_map *id_maps[2];
1381 : struct id_map id_map;
1382 18354 : struct ldb_val *v = &tokengroups->values[i];
1383 14466 : enum ndr_err_code ndr_err
1384 18354 : = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1385 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1386 18354 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1387 0 : talloc_free(tmp_ctx);
1388 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1389 : }
1390 :
1391 18354 : ZERO_STRUCT(id_map);
1392 18354 : id_map.sid = &group_sids[num_groups];
1393 18354 : id_maps[0] = &id_map;
1394 18354 : id_maps[1] = NULL;
1395 :
1396 18354 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1397 18354 : if (!NT_STATUS_IS_OK(status)) {
1398 0 : talloc_free(tmp_ctx);
1399 0 : return status;
1400 : }
1401 18354 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1402 18354 : gids[num_groups] = id_map.xid.id;
1403 : } else {
1404 : struct dom_sid_buf buf;
1405 0 : DEBUG(1, (__location__
1406 : "Group %s, of which %s is a member, could not be converted to a GID\n",
1407 : dom_sid_str_buf(&group_sids[num_groups],
1408 : &buf),
1409 : ldb_dn_get_linearized(msg->dn)));
1410 0 : talloc_free(tmp_ctx);
1411 : /* We must error out, otherwise a user might
1412 : * avoid a DENY acl based on a group they
1413 : * missed out on */
1414 0 : return NT_STATUS_NO_SUCH_GROUP;
1415 : }
1416 :
1417 18354 : num_groups += 1;
1418 18354 : if (num_groups == count) {
1419 2295 : break;
1420 : }
1421 : }
1422 :
1423 2295 : *pp_sids = talloc_steal(mem_ctx, group_sids);
1424 2295 : *pp_gids = talloc_steal(mem_ctx, gids);
1425 2295 : *p_num_groups = num_groups;
1426 2295 : talloc_free(tmp_ctx);
1427 2295 : return NT_STATUS_OK;
1428 : }
1429 :
1430 0 : static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1431 : TALLOC_CTX *mem_ctx,
1432 : struct samu *user)
1433 : {
1434 0 : return NT_STATUS_NOT_IMPLEMENTED;
1435 : }
1436 :
1437 0 : static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1438 : TALLOC_CTX *mem_ctx,
1439 : const struct dom_sid *groupsid,
1440 : const struct dom_sid *membersid,
1441 : int mod_op)
1442 : {
1443 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1444 : m->private_data, struct pdb_samba_dsdb_state);
1445 : struct ldb_message *msg;
1446 : int ret;
1447 : struct ldb_message_element *el;
1448 : struct dom_sid_buf buf;
1449 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1450 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1451 0 : msg = ldb_msg_new(tmp_ctx);
1452 0 : if (msg == NULL) {
1453 0 : TALLOC_FREE(tmp_ctx);
1454 0 : return NT_STATUS_NO_MEMORY;
1455 : }
1456 :
1457 0 : msg->dn = ldb_dn_new_fmt(
1458 : msg,
1459 : state->ldb,
1460 : "<SID=%s>",
1461 : dom_sid_str_buf(groupsid, &buf));
1462 0 : if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1463 0 : talloc_free(tmp_ctx);
1464 0 : return NT_STATUS_NO_MEMORY;
1465 : }
1466 0 : ret = ldb_msg_add_fmt(
1467 : msg,
1468 : "member",
1469 : "<SID=%s>",
1470 : dom_sid_str_buf(membersid, &buf));
1471 0 : if (ret != LDB_SUCCESS) {
1472 0 : talloc_free(tmp_ctx);
1473 0 : return NT_STATUS_NO_MEMORY;
1474 : }
1475 0 : el = ldb_msg_find_element(msg, "member");
1476 0 : el->flags = mod_op;
1477 :
1478 : /* No need for transactions here, the ldb auto-transaction
1479 : * code will handle things for the single operation */
1480 0 : ret = ldb_modify(state->ldb, msg);
1481 0 : talloc_free(tmp_ctx);
1482 0 : if (ret != LDB_SUCCESS) {
1483 0 : DEBUG(10, ("ldb_modify failed: %s\n",
1484 : ldb_errstring(state->ldb)));
1485 0 : if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1486 0 : return NT_STATUS_MEMBER_IN_GROUP;
1487 : }
1488 0 : if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1489 0 : return NT_STATUS_MEMBER_NOT_IN_GROUP;
1490 : }
1491 0 : return NT_STATUS_LDAP(ret);
1492 : }
1493 :
1494 0 : return NT_STATUS_OK;
1495 : }
1496 :
1497 0 : static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1498 : TALLOC_CTX *mem_ctx,
1499 : uint32_t grouprid, uint32_t memberrid,
1500 : int mod_op)
1501 : {
1502 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1503 : m->private_data, struct pdb_samba_dsdb_state);
1504 : const struct dom_sid *dom_sid, *groupsid, *membersid;
1505 : NTSTATUS status;
1506 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1507 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1508 :
1509 0 : dom_sid = samdb_domain_sid(state->ldb);
1510 :
1511 0 : groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1512 0 : if (groupsid == NULL) {
1513 0 : TALLOC_FREE(tmp_ctx);
1514 0 : return NT_STATUS_NO_MEMORY;
1515 : }
1516 0 : membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1517 0 : if (membersid == NULL) {
1518 0 : TALLOC_FREE(tmp_ctx);
1519 0 : return NT_STATUS_NO_MEMORY;
1520 : }
1521 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1522 0 : talloc_free(tmp_ctx);
1523 0 : return status;
1524 : }
1525 :
1526 0 : static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1527 : TALLOC_CTX *mem_ctx,
1528 : uint32_t group_rid, uint32_t member_rid)
1529 : {
1530 0 : return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1531 : LDB_FLAG_MOD_ADD);
1532 : }
1533 :
1534 0 : static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1535 : TALLOC_CTX *mem_ctx,
1536 : uint32_t group_rid, uint32_t member_rid)
1537 : {
1538 0 : return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1539 : LDB_FLAG_MOD_DELETE);
1540 : }
1541 :
1542 0 : static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1543 : const char *name, uint32_t *rid)
1544 : {
1545 0 : TALLOC_CTX *frame = talloc_stackframe();
1546 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1547 : m->private_data, struct pdb_samba_dsdb_state);
1548 : struct dom_sid *sid;
1549 :
1550 : struct ldb_dn *dn;
1551 : NTSTATUS status;
1552 :
1553 : /* Internally this uses transactions to ensure all the steps
1554 : * happen or fail as one */
1555 0 : status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1556 0 : if (!NT_STATUS_IS_OK(status)) {
1557 0 : TALLOC_FREE(frame);
1558 : }
1559 :
1560 0 : sid_peek_rid(sid, rid);
1561 0 : TALLOC_FREE(frame);
1562 0 : return NT_STATUS_OK;
1563 : }
1564 :
1565 0 : static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1566 : const struct dom_sid *sid)
1567 : {
1568 0 : const char *attrs[] = { NULL };
1569 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1570 : m->private_data, struct pdb_samba_dsdb_state);
1571 : struct ldb_message *msg;
1572 : struct ldb_dn *dn;
1573 : int rc;
1574 : struct dom_sid_buf buf;
1575 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1576 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1577 :
1578 0 : dn = ldb_dn_new_fmt(
1579 : tmp_ctx,
1580 : state->ldb,
1581 : "<SID=%s>",
1582 : dom_sid_str_buf(sid, &buf));
1583 0 : if (!dn || !ldb_dn_validate(dn)) {
1584 0 : talloc_free(tmp_ctx);
1585 0 : return NT_STATUS_NO_MEMORY;
1586 : }
1587 :
1588 0 : if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1589 0 : DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1590 0 : talloc_free(tmp_ctx);
1591 0 : return NT_STATUS_INTERNAL_ERROR;
1592 : }
1593 :
1594 0 : rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1595 : "(|(grouptype=%d)(grouptype=%d)))",
1596 : GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1597 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1598 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1599 0 : talloc_free(tmp_ctx);
1600 0 : ldb_transaction_cancel(state->ldb);
1601 0 : return NT_STATUS_NO_SUCH_ALIAS;
1602 : }
1603 0 : rc = ldb_delete(state->ldb, dn);
1604 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1605 0 : talloc_free(tmp_ctx);
1606 0 : ldb_transaction_cancel(state->ldb);
1607 0 : return NT_STATUS_NO_SUCH_ALIAS;
1608 0 : } else if (rc != LDB_SUCCESS) {
1609 0 : DEBUG(10, ("ldb_delete failed %s\n",
1610 : ldb_errstring(state->ldb)));
1611 0 : ldb_transaction_cancel(state->ldb);
1612 0 : talloc_free(tmp_ctx);
1613 0 : return NT_STATUS_LDAP(rc);
1614 : }
1615 :
1616 0 : if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1617 0 : DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1618 : ldb_errstring(state->ldb)));
1619 0 : talloc_free(tmp_ctx);
1620 0 : return NT_STATUS_INTERNAL_ERROR;
1621 : }
1622 :
1623 0 : talloc_free(tmp_ctx);
1624 0 : return NT_STATUS_OK;
1625 : }
1626 :
1627 0 : static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1628 : const struct dom_sid *alias,
1629 : const struct dom_sid *member)
1630 : {
1631 : NTSTATUS status;
1632 0 : TALLOC_CTX *frame = talloc_stackframe();
1633 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1634 0 : talloc_free(frame);
1635 0 : return status;
1636 : }
1637 :
1638 0 : static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1639 : const struct dom_sid *alias,
1640 : const struct dom_sid *member)
1641 : {
1642 : NTSTATUS status;
1643 0 : TALLOC_CTX *frame = talloc_stackframe();
1644 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1645 0 : talloc_free(frame);
1646 0 : return status;
1647 : }
1648 :
1649 0 : static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1650 : const struct dom_sid *alias,
1651 : TALLOC_CTX *mem_ctx,
1652 : struct dom_sid **pmembers,
1653 : size_t *pnum_members)
1654 : {
1655 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1656 : m->private_data, struct pdb_samba_dsdb_state);
1657 : struct ldb_dn *dn;
1658 : unsigned int num_members;
1659 : NTSTATUS status;
1660 : struct dom_sid_buf buf;
1661 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1662 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1663 :
1664 0 : dn = ldb_dn_new_fmt(
1665 : tmp_ctx,
1666 : state->ldb,
1667 : "<SID=%s>",
1668 : dom_sid_str_buf(alias, &buf));
1669 0 : if (!dn || !ldb_dn_validate(dn)) {
1670 0 : return NT_STATUS_NO_MEMORY;
1671 : }
1672 :
1673 0 : status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1674 0 : if (NT_STATUS_IS_OK(status)) {
1675 0 : *pnum_members = num_members;
1676 : }
1677 0 : talloc_free(tmp_ctx);
1678 0 : return status;
1679 : }
1680 :
1681 1334 : static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1682 : TALLOC_CTX *mem_ctx,
1683 : const struct dom_sid *domain_sid,
1684 : const struct dom_sid *members,
1685 : size_t num_members,
1686 : uint32_t **palias_rids,
1687 : size_t *pnum_alias_rids)
1688 : {
1689 1334 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1690 : m->private_data, struct pdb_samba_dsdb_state);
1691 1334 : uint32_t *alias_rids = NULL;
1692 1334 : size_t num_alias_rids = 0;
1693 : int i;
1694 1334 : struct dom_sid *groupSIDs = NULL;
1695 1334 : unsigned int num_groupSIDs = 0;
1696 : char *filter;
1697 : NTSTATUS status;
1698 : const char *sid_dn;
1699 : DATA_BLOB sid_blob;
1700 :
1701 1334 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1702 1334 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1703 : /*
1704 : * TODO: Get the filter right so that we only get the aliases from
1705 : * either the SAM or BUILTIN
1706 : */
1707 :
1708 1334 : filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1709 : GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1710 1334 : if (filter == NULL) {
1711 0 : return NT_STATUS_NO_MEMORY;
1712 : }
1713 :
1714 54840 : for (i = 0; i < num_members; i++) {
1715 : struct dom_sid_buf buf;
1716 :
1717 26100 : sid_dn = talloc_asprintf(
1718 : tmp_ctx,
1719 : "<SID=%s>",
1720 26100 : dom_sid_str_buf(&members[i], &buf));
1721 26100 : if (sid_dn == NULL) {
1722 0 : TALLOC_FREE(tmp_ctx);
1723 0 : return NT_STATUS_NO_MEMORY;
1724 : }
1725 :
1726 26100 : sid_blob = data_blob_string_const(sid_dn);
1727 :
1728 26100 : status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1729 : tmp_ctx, &groupSIDs, &num_groupSIDs);
1730 26100 : if (!NT_STATUS_IS_OK(status)) {
1731 0 : talloc_free(tmp_ctx);
1732 0 : return status;
1733 : }
1734 : }
1735 :
1736 1334 : alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1737 1334 : if (alias_rids == NULL) {
1738 0 : talloc_free(tmp_ctx);
1739 0 : return NT_STATUS_NO_MEMORY;
1740 : }
1741 :
1742 5164 : for (i=0; i<num_groupSIDs; i++) {
1743 3830 : if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1744 3830 : &alias_rids[num_alias_rids])) {
1745 1915 : num_alias_rids++;;
1746 : }
1747 : }
1748 :
1749 1334 : *palias_rids = alias_rids;
1750 1334 : *pnum_alias_rids = num_alias_rids;
1751 1334 : return NT_STATUS_OK;
1752 : }
1753 :
1754 2294 : static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1755 : const struct dom_sid *domain_sid,
1756 : int num_rids,
1757 : uint32_t *rids,
1758 : const char **names,
1759 : enum lsa_SidType *lsa_attrs)
1760 : {
1761 2294 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1762 : m->private_data, struct pdb_samba_dsdb_state);
1763 : NTSTATUS status;
1764 :
1765 : TALLOC_CTX *tmp_ctx;
1766 :
1767 2294 : if (num_rids == 0) {
1768 0 : return NT_STATUS_NONE_MAPPED;
1769 : }
1770 :
1771 2294 : tmp_ctx = talloc_stackframe();
1772 2294 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1773 :
1774 2294 : status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1775 2294 : talloc_free(tmp_ctx);
1776 2294 : return status;
1777 : }
1778 :
1779 0 : static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1780 : const struct dom_sid *domain_sid,
1781 : int num_names,
1782 : const char **pp_names,
1783 : uint32_t *rids,
1784 : enum lsa_SidType *attrs)
1785 : {
1786 0 : return NT_STATUS_NOT_IMPLEMENTED;
1787 : }
1788 :
1789 62 : static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1790 : enum pdb_policy_type type,
1791 : uint32_t *value)
1792 : {
1793 62 : return account_policy_get(type, value)
1794 62 : ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1795 : }
1796 :
1797 0 : static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1798 : enum pdb_policy_type type,
1799 : uint32_t value)
1800 : {
1801 0 : return account_policy_set(type, value)
1802 0 : ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1803 : }
1804 :
1805 0 : static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1806 : time_t *seq_num_out)
1807 : {
1808 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1809 : m->private_data, struct pdb_samba_dsdb_state);
1810 : uint64_t seq_num;
1811 0 : int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1812 0 : if (ret == LDB_SUCCESS) {
1813 0 : *seq_num_out = seq_num;
1814 0 : return NT_STATUS_OK;
1815 : } else {
1816 0 : return NT_STATUS_UNSUCCESSFUL;
1817 : }
1818 : }
1819 :
1820 : struct pdb_samba_dsdb_search_state {
1821 : uint32_t acct_flags;
1822 : struct samr_displayentry *entries;
1823 : uint32_t num_entries;
1824 : ssize_t array_size;
1825 : uint32_t current;
1826 : };
1827 :
1828 0 : static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1829 : struct samr_displayentry *entry)
1830 : {
1831 0 : struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1832 : search->private_data, struct pdb_samba_dsdb_search_state);
1833 :
1834 0 : if (state->current == state->num_entries) {
1835 0 : return false;
1836 : }
1837 :
1838 0 : entry->idx = state->entries[state->current].idx;
1839 0 : entry->rid = state->entries[state->current].rid;
1840 0 : entry->acct_flags = state->entries[state->current].acct_flags;
1841 :
1842 0 : entry->account_name = talloc_strdup(
1843 0 : search, state->entries[state->current].account_name);
1844 0 : entry->fullname = talloc_strdup(
1845 0 : search, state->entries[state->current].fullname);
1846 0 : entry->description = talloc_strdup(
1847 0 : search, state->entries[state->current].description);
1848 :
1849 0 : state->current += 1;
1850 0 : return true;
1851 : }
1852 :
1853 0 : static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1854 : {
1855 0 : struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1856 : search->private_data, struct pdb_samba_dsdb_search_state);
1857 0 : talloc_free(state);
1858 0 : }
1859 :
1860 : static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1861 : struct pdb_search *search,
1862 : struct pdb_samba_dsdb_search_state **pstate,
1863 : const char *exp_fmt, ...)
1864 : PRINTF_ATTRIBUTE(4, 5);
1865 :
1866 0 : static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1867 : struct pdb_search *search,
1868 : struct pdb_samba_dsdb_search_state **pstate,
1869 : const char *exp_fmt, ...)
1870 : {
1871 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1872 : m->private_data, struct pdb_samba_dsdb_state);
1873 : struct pdb_samba_dsdb_search_state *sstate;
1874 0 : const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1875 : "userAccountControl", "description", NULL };
1876 : struct ldb_result *res;
1877 : int i, rc, num_users;
1878 :
1879 : va_list ap;
1880 0 : char *expression = NULL;
1881 :
1882 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1883 0 : if (!tmp_ctx) {
1884 0 : return false;
1885 : }
1886 :
1887 0 : va_start(ap, exp_fmt);
1888 0 : expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1889 0 : va_end(ap);
1890 :
1891 0 : if (!expression) {
1892 0 : talloc_free(tmp_ctx);
1893 0 : return LDB_ERR_OPERATIONS_ERROR;
1894 : }
1895 :
1896 0 : sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1897 0 : if (sstate == NULL) {
1898 0 : talloc_free(tmp_ctx);
1899 0 : return false;
1900 : }
1901 :
1902 0 : rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1903 0 : if (rc != LDB_SUCCESS) {
1904 0 : talloc_free(tmp_ctx);
1905 0 : DEBUG(10, ("dsdb_search failed: %s\n",
1906 : ldb_errstring(state->ldb)));
1907 0 : return false;
1908 : }
1909 :
1910 0 : num_users = res->count;
1911 :
1912 0 : sstate->entries = talloc_array(sstate, struct samr_displayentry,
1913 : num_users);
1914 0 : if (sstate->entries == NULL) {
1915 0 : talloc_free(tmp_ctx);
1916 0 : DEBUG(10, ("talloc failed\n"));
1917 0 : return false;
1918 : }
1919 :
1920 0 : sstate->num_entries = 0;
1921 :
1922 0 : for (i=0; i<num_users; i++) {
1923 : struct samr_displayentry *e;
1924 : struct dom_sid *sid;
1925 :
1926 0 : e = &sstate->entries[sstate->num_entries];
1927 :
1928 0 : e->idx = sstate->num_entries;
1929 0 : sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1930 0 : if (!sid) {
1931 0 : talloc_free(tmp_ctx);
1932 0 : DEBUG(10, ("Could not pull SID\n"));
1933 0 : return false;
1934 : }
1935 0 : sid_peek_rid(sid, &e->rid);
1936 :
1937 0 : e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1938 0 : e->account_name = ldb_msg_find_attr_as_string(
1939 0 : res->msgs[i], "samAccountName", NULL);
1940 0 : if (e->account_name == NULL) {
1941 0 : talloc_free(tmp_ctx);
1942 0 : return false;
1943 : }
1944 0 : e->fullname = ldb_msg_find_attr_as_string(
1945 0 : res->msgs[i], "displayName", "");
1946 0 : e->description = ldb_msg_find_attr_as_string(
1947 0 : res->msgs[i], "description", "");
1948 :
1949 0 : sstate->num_entries += 1;
1950 0 : if (sstate->num_entries >= num_users) {
1951 0 : break;
1952 : }
1953 : }
1954 0 : talloc_steal(sstate->entries, res->msgs);
1955 0 : search->private_data = talloc_steal(search, sstate);
1956 0 : search->next_entry = pdb_samba_dsdb_next_entry;
1957 0 : search->search_end = pdb_samba_dsdb_search_end;
1958 0 : *pstate = sstate;
1959 0 : talloc_free(tmp_ctx);
1960 0 : return true;
1961 : }
1962 :
1963 0 : static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1964 : struct pdb_search *search,
1965 : uint32_t acct_flags)
1966 : {
1967 : struct pdb_samba_dsdb_search_state *sstate;
1968 : bool ret;
1969 :
1970 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
1971 0 : if (!ret) {
1972 0 : return false;
1973 : }
1974 0 : sstate->acct_flags = acct_flags;
1975 0 : return true;
1976 : }
1977 :
1978 0 : static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
1979 : struct pdb_search *search)
1980 : {
1981 : struct pdb_samba_dsdb_search_state *sstate;
1982 : bool ret;
1983 :
1984 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
1985 : "(&(grouptype=%d)(objectclass=group))",
1986 : GTYPE_SECURITY_GLOBAL_GROUP);
1987 0 : if (!ret) {
1988 0 : return false;
1989 : }
1990 0 : sstate->acct_flags = 0;
1991 0 : return true;
1992 : }
1993 :
1994 0 : static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
1995 : struct pdb_search *search,
1996 : const struct dom_sid *sid)
1997 : {
1998 : struct pdb_samba_dsdb_search_state *sstate;
1999 : bool ret;
2000 :
2001 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2002 : "(&(grouptype=%d)(objectclass=group))",
2003 0 : sid_check_is_builtin(sid)
2004 : ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2005 : : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2006 0 : if (!ret) {
2007 0 : return false;
2008 : }
2009 0 : sstate->acct_flags = 0;
2010 0 : return true;
2011 : }
2012 :
2013 : /*
2014 : * Instead of taking a gid or uid, this function takes a pointer to a
2015 : * unixid.
2016 : *
2017 : * This acts as an in-out variable so that the idmap functions can correctly
2018 : * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2019 : * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID.
2020 : */
2021 118 : static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2022 : struct dom_sid *sid)
2023 : {
2024 118 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2025 : m->private_data, struct pdb_samba_dsdb_state);
2026 : NTSTATUS status;
2027 : struct id_map id_map;
2028 : struct id_map *id_maps[2];
2029 118 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2030 118 : if (!tmp_ctx) {
2031 0 : return false;
2032 : }
2033 :
2034 118 : id_map.xid = *id;
2035 118 : id_maps[0] = &id_map;
2036 118 : id_maps[1] = NULL;
2037 :
2038 118 : status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2039 118 : if (!NT_STATUS_IS_OK(status)) {
2040 0 : talloc_free(tmp_ctx);
2041 0 : return false;
2042 : }
2043 :
2044 118 : if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2045 118 : id->type = id_map.xid.type;
2046 : }
2047 118 : *sid = *id_map.sid;
2048 118 : talloc_free(tmp_ctx);
2049 118 : return true;
2050 : }
2051 :
2052 992 : static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2053 : struct unixid *id)
2054 : {
2055 992 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2056 : m->private_data, struct pdb_samba_dsdb_state);
2057 : struct id_map id_map;
2058 : struct id_map *id_maps[2];
2059 : NTSTATUS status;
2060 992 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2061 992 : if (!tmp_ctx) {
2062 0 : return false;
2063 : }
2064 :
2065 992 : ZERO_STRUCT(id_map);
2066 992 : id_map.sid = discard_const_p(struct dom_sid, sid);
2067 992 : id_maps[0] = &id_map;
2068 992 : id_maps[1] = NULL;
2069 :
2070 992 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2071 992 : talloc_free(tmp_ctx);
2072 992 : if (!NT_STATUS_IS_OK(status)) {
2073 0 : return false;
2074 : }
2075 992 : if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2076 992 : *id = id_map.xid;
2077 992 : return true;
2078 : }
2079 0 : return false;
2080 : }
2081 :
2082 203 : static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2083 : {
2084 203 : return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2085 : }
2086 :
2087 0 : static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2088 : {
2089 0 : return false;
2090 : }
2091 :
2092 0 : static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2093 : const char *domain, char** pwd,
2094 : struct dom_sid *sid,
2095 : time_t *pass_last_set_time)
2096 : {
2097 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2098 : m->private_data, struct pdb_samba_dsdb_state);
2099 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2100 0 : const char * const attrs[] = {
2101 : "securityIdentifier",
2102 : "flatName",
2103 : "trustPartner",
2104 : "trustAuthOutgoing",
2105 : "whenCreated",
2106 : "msDS-SupportedEncryptionTypes",
2107 : "trustAttributes",
2108 : "trustDirection",
2109 : "trustType",
2110 : NULL
2111 : };
2112 : struct ldb_message *msg;
2113 : const struct ldb_val *password_val;
2114 : int trust_direction_flags;
2115 : int trust_type;
2116 : int i;
2117 : DATA_BLOB password_utf16;
2118 : struct trustAuthInOutBlob password_blob;
2119 : struct AuthenticationInformationArray *auth_array;
2120 : char *password_talloc;
2121 : size_t password_len;
2122 : enum ndr_err_code ndr_err;
2123 : NTSTATUS status;
2124 0 : const char *netbios_domain = NULL;
2125 0 : const struct dom_sid *domain_sid = NULL;
2126 :
2127 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2128 : attrs, tmp_ctx, &msg);
2129 0 : if (!NT_STATUS_IS_OK(status)) {
2130 : /*
2131 : * This can be called to work out of a domain is
2132 : * trusted, rather than just to get the password
2133 : */
2134 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2135 : "It may not be a trusted domain.\n", domain,
2136 : nt_errstr(status)));
2137 0 : TALLOC_FREE(tmp_ctx);
2138 0 : return false;
2139 : }
2140 :
2141 0 : netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2142 0 : if (netbios_domain == NULL) {
2143 0 : DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2144 : domain));
2145 0 : TALLOC_FREE(tmp_ctx);
2146 0 : return false;
2147 : }
2148 :
2149 0 : domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2150 0 : if (domain_sid == NULL) {
2151 0 : DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2152 : domain));
2153 0 : TALLOC_FREE(tmp_ctx);
2154 0 : return false;
2155 : }
2156 :
2157 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2158 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2159 0 : DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2160 : domain);
2161 0 : TALLOC_FREE(tmp_ctx);
2162 0 : return false;
2163 : }
2164 :
2165 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2166 0 : if (trust_type == LSA_TRUST_TYPE_MIT) {
2167 0 : DBG_WARNING("Trusted domain %s is not an AD trust "
2168 : "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2169 0 : TALLOC_FREE(tmp_ctx);
2170 0 : return false;
2171 : }
2172 :
2173 0 : password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2174 0 : if (password_val == NULL) {
2175 0 : DEBUG(2, ("Failed to get trusted domain password for %s, "
2176 : "attribute trustAuthOutgoing not returned.\n", domain));
2177 0 : TALLOC_FREE(tmp_ctx);
2178 0 : return false;
2179 : }
2180 :
2181 0 : ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2182 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2183 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2184 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2185 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2186 : domain,
2187 : ndr_map_error2string(ndr_err)));
2188 0 : TALLOC_FREE(tmp_ctx);
2189 0 : return false;
2190 : }
2191 :
2192 0 : auth_array = &password_blob.current;
2193 :
2194 0 : for (i=0; i < auth_array->count; i++) {
2195 0 : if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2196 0 : break;
2197 : }
2198 : }
2199 :
2200 0 : if (i == auth_array->count) {
2201 0 : DEBUG(0, ("Trusted domain %s does not have a "
2202 : "clear-text password stored\n",
2203 : domain));
2204 0 : TALLOC_FREE(tmp_ctx);
2205 0 : return false;
2206 : }
2207 :
2208 0 : password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2209 0 : auth_array->array[i].AuthInfo.clear.size);
2210 :
2211 : /*
2212 : * In the future, make this function return a
2213 : * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2214 : * but for now convert to UTF8 and fail if the string can not be converted.
2215 : *
2216 : * We can't safely convert the random strings windows uses into
2217 : * utf8.
2218 : */
2219 0 : if (!convert_string_talloc(tmp_ctx,
2220 : CH_UTF16MUNGED, CH_UTF8,
2221 0 : password_utf16.data, password_utf16.length,
2222 : (void *)&password_talloc,
2223 : &password_len)) {
2224 0 : DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2225 : " to UTF8. This may be a password set from Windows.\n",
2226 : domain));
2227 0 : TALLOC_FREE(tmp_ctx);
2228 0 : return false;
2229 : }
2230 0 : *pwd = SMB_STRNDUP(password_talloc, password_len);
2231 0 : if (pass_last_set_time) {
2232 0 : *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2233 : }
2234 :
2235 0 : if (sid != NULL) {
2236 0 : sid_copy(sid, domain_sid);
2237 : }
2238 :
2239 0 : TALLOC_FREE(tmp_ctx);
2240 0 : return true;
2241 : }
2242 :
2243 0 : static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2244 : const char *domain,
2245 : TALLOC_CTX *mem_ctx,
2246 : struct cli_credentials **_creds)
2247 : {
2248 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2249 : m->private_data, struct pdb_samba_dsdb_state);
2250 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2251 0 : const char * const attrs[] = {
2252 : "securityIdentifier",
2253 : "flatName",
2254 : "trustPartner",
2255 : "trustAuthOutgoing",
2256 : "whenCreated",
2257 : "msDS-SupportedEncryptionTypes",
2258 : "trustAttributes",
2259 : "trustDirection",
2260 : "trustType",
2261 : NULL
2262 : };
2263 : struct ldb_message *msg;
2264 : const struct ldb_val *password_val;
2265 : int trust_direction_flags;
2266 : int trust_type;
2267 : int i;
2268 0 : DATA_BLOB password_utf16 = {};
2269 0 : struct samr_Password *password_nt = NULL;
2270 0 : uint32_t password_version = 0;
2271 0 : DATA_BLOB old_password_utf16 = {};
2272 0 : struct samr_Password *old_password_nt = NULL;
2273 : struct trustAuthInOutBlob password_blob;
2274 : enum ndr_err_code ndr_err;
2275 : NTSTATUS status;
2276 0 : time_t last_set_time = 0;
2277 0 : struct cli_credentials *creds = NULL;
2278 : bool ok;
2279 0 : const char *my_netbios_name = NULL;
2280 0 : const char *my_netbios_domain = NULL;
2281 0 : const char *my_dns_domain = NULL;
2282 0 : const char *netbios_domain = NULL;
2283 0 : char *account_name = NULL;
2284 0 : char *principal_name = NULL;
2285 0 : const char *dns_domain = NULL;
2286 :
2287 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2288 : attrs, tmp_ctx, &msg);
2289 0 : if (!NT_STATUS_IS_OK(status)) {
2290 : /*
2291 : * This can be called to work out of a domain is
2292 : * trusted, rather than just to get the password
2293 : */
2294 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2295 : "It may not be a trusted domain.\n", domain,
2296 : nt_errstr(status)));
2297 0 : TALLOC_FREE(tmp_ctx);
2298 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2299 : }
2300 :
2301 0 : netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2302 0 : if (netbios_domain == NULL) {
2303 0 : DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2304 : domain));
2305 0 : TALLOC_FREE(tmp_ctx);
2306 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2307 : }
2308 :
2309 0 : dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2310 :
2311 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2312 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2313 0 : DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2314 : domain);
2315 0 : TALLOC_FREE(tmp_ctx);
2316 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2317 : }
2318 :
2319 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2320 0 : if (trust_type == LSA_TRUST_TYPE_MIT) {
2321 0 : DBG_WARNING("Trusted domain %s is not an AD trust "
2322 : "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2323 0 : TALLOC_FREE(tmp_ctx);
2324 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2325 : }
2326 :
2327 0 : password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2328 0 : if (password_val == NULL) {
2329 0 : DEBUG(2, ("Failed to get trusted domain password for %s, "
2330 : "attribute trustAuthOutgoing not returned.\n", domain));
2331 0 : TALLOC_FREE(tmp_ctx);
2332 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2333 : }
2334 :
2335 0 : ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2336 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2337 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2338 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2339 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2340 : domain,
2341 : ndr_map_error2string(ndr_err)));
2342 0 : TALLOC_FREE(tmp_ctx);
2343 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2344 : }
2345 :
2346 0 : for (i=0; i < password_blob.current.count; i++) {
2347 0 : struct AuthenticationInformation *a =
2348 0 : &password_blob.current.array[i];
2349 :
2350 0 : switch (a->AuthType) {
2351 0 : case TRUST_AUTH_TYPE_NONE:
2352 0 : break;
2353 :
2354 0 : case TRUST_AUTH_TYPE_VERSION:
2355 0 : password_version = a->AuthInfo.version.version;
2356 0 : break;
2357 :
2358 0 : case TRUST_AUTH_TYPE_CLEAR:
2359 0 : last_set_time = nt_time_to_unix(a->LastUpdateTime);
2360 :
2361 0 : password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2362 0 : a->AuthInfo.clear.size);
2363 0 : password_nt = NULL;
2364 0 : break;
2365 :
2366 0 : case TRUST_AUTH_TYPE_NT4OWF:
2367 0 : if (password_utf16.length != 0) {
2368 0 : break;
2369 : }
2370 :
2371 0 : last_set_time = nt_time_to_unix(a->LastUpdateTime);
2372 :
2373 0 : password_nt = &a->AuthInfo.nt4owf.password;
2374 0 : break;
2375 : }
2376 : }
2377 :
2378 0 : for (i=0; i < password_blob.previous.count; i++) {
2379 0 : struct AuthenticationInformation *a = &password_blob.previous.array[i];
2380 :
2381 0 : switch (a->AuthType) {
2382 0 : case TRUST_AUTH_TYPE_NONE:
2383 0 : break;
2384 :
2385 0 : case TRUST_AUTH_TYPE_VERSION:
2386 0 : break;
2387 :
2388 0 : case TRUST_AUTH_TYPE_CLEAR:
2389 0 : old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2390 0 : a->AuthInfo.clear.size);
2391 0 : old_password_nt = NULL;
2392 0 : break;
2393 :
2394 0 : case TRUST_AUTH_TYPE_NT4OWF:
2395 0 : if (old_password_utf16.length != 0) {
2396 0 : break;
2397 : }
2398 :
2399 0 : old_password_nt = &a->AuthInfo.nt4owf.password;
2400 0 : break;
2401 : }
2402 : }
2403 :
2404 0 : if (password_utf16.length == 0 && password_nt == NULL) {
2405 0 : DEBUG(0, ("Trusted domain %s does not have a "
2406 : "clear-text nor nt password stored\n",
2407 : domain));
2408 0 : TALLOC_FREE(tmp_ctx);
2409 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2410 : }
2411 :
2412 0 : my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2413 0 : my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2414 0 : my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2415 :
2416 0 : creds = cli_credentials_init(tmp_ctx);
2417 0 : if (creds == NULL) {
2418 0 : TALLOC_FREE(tmp_ctx);
2419 0 : return NT_STATUS_NO_MEMORY;
2420 : }
2421 :
2422 0 : ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2423 0 : if (!ok) {
2424 0 : TALLOC_FREE(tmp_ctx);
2425 0 : return NT_STATUS_NO_MEMORY;
2426 : }
2427 :
2428 0 : ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2429 0 : if (!ok) {
2430 0 : TALLOC_FREE(tmp_ctx);
2431 0 : return NT_STATUS_NO_MEMORY;
2432 : }
2433 0 : ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2434 0 : if (!ok) {
2435 0 : TALLOC_FREE(tmp_ctx);
2436 0 : return NT_STATUS_NO_MEMORY;
2437 : }
2438 :
2439 0 : if (my_dns_domain != NULL && dns_domain != NULL) {
2440 0 : cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2441 0 : account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2442 0 : if (account_name == NULL) {
2443 0 : TALLOC_FREE(tmp_ctx);
2444 0 : return NT_STATUS_NO_MEMORY;
2445 : }
2446 0 : principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2447 : cli_credentials_get_realm(creds));
2448 0 : if (principal_name == NULL) {
2449 0 : TALLOC_FREE(tmp_ctx);
2450 0 : return NT_STATUS_NO_MEMORY;
2451 : }
2452 : } else {
2453 0 : cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2454 0 : account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2455 0 : if (account_name == NULL) {
2456 0 : TALLOC_FREE(tmp_ctx);
2457 0 : return NT_STATUS_NO_MEMORY;
2458 : }
2459 0 : principal_name = NULL;
2460 : }
2461 :
2462 0 : ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2463 0 : if (!ok) {
2464 0 : TALLOC_FREE(tmp_ctx);
2465 0 : return NT_STATUS_NO_MEMORY;
2466 : }
2467 :
2468 0 : if (principal_name != NULL) {
2469 0 : ok = cli_credentials_set_principal(creds, principal_name,
2470 : CRED_SPECIFIED);
2471 0 : if (!ok) {
2472 0 : TALLOC_FREE(tmp_ctx);
2473 0 : return NT_STATUS_NO_MEMORY;
2474 : }
2475 : }
2476 :
2477 0 : if (old_password_nt != NULL) {
2478 0 : ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2479 0 : if (!ok) {
2480 0 : TALLOC_FREE(tmp_ctx);
2481 0 : return NT_STATUS_NO_MEMORY;
2482 : }
2483 : }
2484 :
2485 0 : if (old_password_utf16.length > 0) {
2486 0 : ok = cli_credentials_set_old_utf16_password(creds,
2487 : &old_password_utf16);
2488 0 : if (!ok) {
2489 0 : TALLOC_FREE(tmp_ctx);
2490 0 : return NT_STATUS_NO_MEMORY;
2491 : }
2492 : }
2493 :
2494 0 : if (password_nt != NULL) {
2495 0 : ok = cli_credentials_set_nt_hash(creds, password_nt,
2496 : CRED_SPECIFIED);
2497 0 : if (!ok) {
2498 0 : TALLOC_FREE(tmp_ctx);
2499 0 : return NT_STATUS_NO_MEMORY;
2500 : }
2501 : }
2502 :
2503 0 : if (password_utf16.length > 0) {
2504 0 : ok = cli_credentials_set_utf16_password(creds,
2505 : &password_utf16,
2506 : CRED_SPECIFIED);
2507 0 : if (!ok) {
2508 0 : TALLOC_FREE(tmp_ctx);
2509 0 : return NT_STATUS_NO_MEMORY;
2510 : }
2511 : }
2512 :
2513 0 : cli_credentials_set_password_last_changed_time(creds, last_set_time);
2514 0 : cli_credentials_set_kvno(creds, password_version);
2515 :
2516 0 : if (password_utf16.length > 0 && dns_domain != NULL) {
2517 : /*
2518 : * Force kerberos if this is an active directory domain
2519 : */
2520 0 : cli_credentials_set_kerberos_state(creds,
2521 : CRED_USE_KERBEROS_REQUIRED,
2522 : CRED_SPECIFIED);
2523 : } else {
2524 : /*
2525 : * TODO: we should allow krb5 with the raw nt hash.
2526 : */
2527 0 : cli_credentials_set_kerberos_state(creds,
2528 : CRED_USE_KERBEROS_DISABLED,
2529 : CRED_SPECIFIED);
2530 : }
2531 :
2532 0 : *_creds = talloc_move(mem_ctx, &creds);
2533 0 : TALLOC_FREE(tmp_ctx);
2534 0 : return NT_STATUS_OK;
2535 : }
2536 :
2537 0 : static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2538 : const char* domain, const char* pwd,
2539 : const struct dom_sid *sid)
2540 : {
2541 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2542 : m->private_data, struct pdb_samba_dsdb_state);
2543 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2544 0 : const char * const attrs[] = {
2545 : "trustAuthOutgoing",
2546 : "trustDirection",
2547 : "trustType",
2548 : NULL
2549 : };
2550 0 : struct ldb_message *msg = NULL;
2551 : int trust_direction_flags;
2552 : int trust_type;
2553 : uint32_t i; /* The same type as old_blob.current.count */
2554 0 : const struct ldb_val *old_val = NULL;
2555 0 : struct trustAuthInOutBlob old_blob = {};
2556 0 : uint32_t old_version = 0;
2557 0 : uint32_t new_version = 0;
2558 0 : DATA_BLOB new_utf16 = {};
2559 0 : struct trustAuthInOutBlob new_blob = {};
2560 0 : struct ldb_val new_val = {};
2561 0 : struct timeval tv = timeval_current();
2562 0 : NTTIME now = timeval_to_nttime(&tv);
2563 : enum ndr_err_code ndr_err;
2564 : NTSTATUS status;
2565 : bool ok;
2566 : int ret;
2567 :
2568 0 : ret = ldb_transaction_start(state->ldb);
2569 0 : if (ret != LDB_SUCCESS) {
2570 0 : DEBUG(2, ("Failed to start transaction.\n"));
2571 0 : TALLOC_FREE(tmp_ctx);
2572 0 : return false;
2573 : }
2574 :
2575 0 : ok = samdb_is_pdc(state->ldb);
2576 0 : if (!ok) {
2577 0 : DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2578 : domain));
2579 0 : TALLOC_FREE(tmp_ctx);
2580 0 : ldb_transaction_cancel(state->ldb);
2581 0 : return false;
2582 : }
2583 :
2584 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2585 : attrs, tmp_ctx, &msg);
2586 0 : if (!NT_STATUS_IS_OK(status)) {
2587 : /*
2588 : * This can be called to work out of a domain is
2589 : * trusted, rather than just to get the password
2590 : */
2591 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2592 : "It may not be a trusted domain.\n", domain,
2593 : nt_errstr(status)));
2594 0 : TALLOC_FREE(tmp_ctx);
2595 0 : ldb_transaction_cancel(state->ldb);
2596 0 : return false;
2597 : }
2598 :
2599 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2600 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2601 0 : DBG_WARNING("Trusted domain %s is not an outbound trust, can't set a password.\n",
2602 : domain);
2603 0 : TALLOC_FREE(tmp_ctx);
2604 0 : ldb_transaction_cancel(state->ldb);
2605 0 : return false;
2606 : }
2607 :
2608 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2609 0 : switch (trust_type) {
2610 0 : case LSA_TRUST_TYPE_DOWNLEVEL:
2611 : case LSA_TRUST_TYPE_UPLEVEL:
2612 0 : break;
2613 0 : default:
2614 0 : DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2615 : "password changes are not supported\n",
2616 : domain, (unsigned)trust_type));
2617 0 : TALLOC_FREE(tmp_ctx);
2618 0 : ldb_transaction_cancel(state->ldb);
2619 0 : return false;
2620 : }
2621 :
2622 0 : old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2623 0 : if (old_val != NULL) {
2624 0 : ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2625 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2626 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2627 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2628 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2629 : domain,
2630 : ndr_map_error2string(ndr_err)));
2631 0 : TALLOC_FREE(tmp_ctx);
2632 0 : ldb_transaction_cancel(state->ldb);
2633 0 : return false;
2634 : }
2635 : }
2636 :
2637 0 : for (i=0; i < old_blob.current.count; i++) {
2638 0 : struct AuthenticationInformation *a =
2639 0 : &old_blob.current.array[i];
2640 :
2641 0 : switch (a->AuthType) {
2642 0 : case TRUST_AUTH_TYPE_NONE:
2643 0 : break;
2644 :
2645 0 : case TRUST_AUTH_TYPE_VERSION:
2646 0 : old_version = a->AuthInfo.version.version;
2647 0 : break;
2648 :
2649 0 : case TRUST_AUTH_TYPE_CLEAR:
2650 0 : break;
2651 :
2652 0 : case TRUST_AUTH_TYPE_NT4OWF:
2653 0 : break;
2654 : }
2655 : }
2656 :
2657 0 : new_version = old_version + 1;
2658 0 : ok = convert_string_talloc(tmp_ctx,
2659 : CH_UNIX, CH_UTF16,
2660 : pwd, strlen(pwd),
2661 : (void *)&new_utf16.data,
2662 : &new_utf16.length);
2663 0 : if (!ok) {
2664 0 : DEBUG(0, ("Failed to generate new_utf16 password for domain %s\n",
2665 : domain));
2666 0 : TALLOC_FREE(tmp_ctx);
2667 0 : ldb_transaction_cancel(state->ldb);
2668 0 : return false;
2669 : }
2670 :
2671 0 : if (new_utf16.length < 28) {
2672 0 : DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2673 : new_utf16.length,
2674 : (unsigned)new_version,
2675 : domain));
2676 0 : TALLOC_FREE(tmp_ctx);
2677 0 : ldb_transaction_cancel(state->ldb);
2678 0 : return false;
2679 : }
2680 0 : if (new_utf16.length > 498) {
2681 0 : DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2682 : new_utf16.length,
2683 : (unsigned)new_version,
2684 : domain));
2685 0 : TALLOC_FREE(tmp_ctx);
2686 0 : ldb_transaction_cancel(state->ldb);
2687 0 : return false;
2688 : }
2689 :
2690 0 : new_blob.count = MAX(old_blob.current.count, 2);
2691 0 : new_blob.current.array = talloc_zero_array(tmp_ctx,
2692 : struct AuthenticationInformation,
2693 : new_blob.count);
2694 0 : if (new_blob.current.array == NULL) {
2695 0 : DEBUG(0, ("talloc_zero_array(%u) failed\n",
2696 : (unsigned)new_blob.count));
2697 0 : TALLOC_FREE(tmp_ctx);
2698 0 : ldb_transaction_cancel(state->ldb);
2699 0 : return false;
2700 : }
2701 0 : new_blob.previous.array = talloc_zero_array(tmp_ctx,
2702 : struct AuthenticationInformation,
2703 : new_blob.count);
2704 0 : if (new_blob.current.array == NULL) {
2705 0 : DEBUG(0, ("talloc_zero_array(%u) failed\n",
2706 : (unsigned)new_blob.count));
2707 0 : TALLOC_FREE(tmp_ctx);
2708 0 : ldb_transaction_cancel(state->ldb);
2709 0 : return false;
2710 : }
2711 :
2712 0 : for (i = 0; i < old_blob.current.count; i++) {
2713 0 : struct AuthenticationInformation *o =
2714 0 : &old_blob.current.array[i];
2715 0 : struct AuthenticationInformation *p =
2716 0 : &new_blob.previous.array[i];
2717 :
2718 0 : *p = *o;
2719 0 : new_blob.previous.count++;
2720 : }
2721 0 : for (; i < new_blob.count; i++) {
2722 0 : struct AuthenticationInformation *pi =
2723 0 : &new_blob.previous.array[i];
2724 :
2725 0 : if (i == 0) {
2726 : /*
2727 : * new_blob.previous is still empty so
2728 : * we'll do new_blob.previous = new_blob.current
2729 : * below.
2730 : */
2731 0 : break;
2732 : }
2733 :
2734 0 : pi->LastUpdateTime = now;
2735 0 : pi->AuthType = TRUST_AUTH_TYPE_NONE;
2736 0 : new_blob.previous.count++;
2737 : }
2738 :
2739 0 : for (i = 0; i < new_blob.count; i++) {
2740 0 : struct AuthenticationInformation *ci =
2741 0 : &new_blob.current.array[i];
2742 :
2743 0 : ci->LastUpdateTime = now;
2744 0 : switch (i) {
2745 0 : case 0:
2746 0 : ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2747 0 : ci->AuthInfo.clear.size = new_utf16.length;
2748 0 : ci->AuthInfo.clear.password = new_utf16.data;
2749 0 : break;
2750 0 : case 1:
2751 0 : ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2752 0 : ci->AuthInfo.version.version = new_version;
2753 0 : break;
2754 0 : default:
2755 0 : ci->AuthType = TRUST_AUTH_TYPE_NONE;
2756 0 : break;
2757 : }
2758 :
2759 0 : new_blob.current.count++;
2760 : }
2761 :
2762 0 : if (new_blob.previous.count == 0) {
2763 0 : TALLOC_FREE(new_blob.previous.array);
2764 0 : new_blob.previous = new_blob.current;
2765 : }
2766 :
2767 0 : ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2768 : (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2769 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2770 0 : DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2771 : "trusted domain password for %s: %s.\n",
2772 : domain, ndr_map_error2string(ndr_err)));
2773 0 : TALLOC_FREE(tmp_ctx);
2774 0 : ldb_transaction_cancel(state->ldb);
2775 0 : return false;
2776 : }
2777 :
2778 0 : msg->num_elements = 0;
2779 0 : ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2780 : &new_val, LDB_FLAG_MOD_REPLACE);
2781 0 : if (ret != LDB_SUCCESS) {
2782 0 : DEBUG(0, ("ldb_msg_append_value() failed\n"));
2783 0 : TALLOC_FREE(tmp_ctx);
2784 0 : ldb_transaction_cancel(state->ldb);
2785 0 : return false;
2786 : }
2787 :
2788 0 : ret = ldb_modify(state->ldb, msg);
2789 0 : if (ret != LDB_SUCCESS) {
2790 0 : DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2791 : "trusted domain password for %s: %s - %s\n",
2792 : domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2793 0 : TALLOC_FREE(tmp_ctx);
2794 0 : ldb_transaction_cancel(state->ldb);
2795 0 : return false;
2796 : }
2797 :
2798 0 : ret = ldb_transaction_commit(state->ldb);
2799 0 : if (ret != LDB_SUCCESS) {
2800 0 : DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2801 : "trusted domain password for %s: %s - %s\n",
2802 : domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2803 0 : TALLOC_FREE(tmp_ctx);
2804 0 : return false;
2805 : }
2806 :
2807 0 : DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2808 : "trusted domain password for %s.\n",
2809 : (unsigned)new_version, domain));
2810 0 : TALLOC_FREE(tmp_ctx);
2811 0 : return true;
2812 : }
2813 :
2814 0 : static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2815 : const char *domain)
2816 : {
2817 0 : return false;
2818 : }
2819 :
2820 0 : static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2821 : TALLOC_CTX *mem_ctx,
2822 : uint32_t *_num_domains,
2823 : struct trustdom_info ***_domains)
2824 : {
2825 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2826 : m->private_data, struct pdb_samba_dsdb_state);
2827 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2828 0 : const char * const attrs[] = {
2829 : "securityIdentifier",
2830 : "flatName",
2831 : "trustDirection",
2832 : NULL
2833 : };
2834 0 : struct ldb_result *res = NULL;
2835 : unsigned int i;
2836 0 : struct trustdom_info **domains = NULL;
2837 : NTSTATUS status;
2838 0 : uint32_t di = 0;
2839 :
2840 0 : *_num_domains = 0;
2841 0 : *_domains = NULL;
2842 :
2843 0 : status = dsdb_trust_search_tdos(state->ldb, NULL,
2844 : attrs, tmp_ctx, &res);
2845 0 : if (!NT_STATUS_IS_OK(status)) {
2846 0 : DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
2847 0 : TALLOC_FREE(tmp_ctx);
2848 0 : return status;
2849 : }
2850 :
2851 0 : if (res->count == 0) {
2852 0 : TALLOC_FREE(tmp_ctx);
2853 0 : return NT_STATUS_OK;
2854 : }
2855 :
2856 0 : domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2857 : res->count);
2858 0 : if (domains == NULL) {
2859 0 : TALLOC_FREE(tmp_ctx);
2860 0 : return NT_STATUS_NO_MEMORY;
2861 : }
2862 :
2863 0 : for (i = 0; i < res->count; i++) {
2864 0 : struct ldb_message *msg = res->msgs[i];
2865 0 : struct trustdom_info *d = NULL;
2866 0 : const char *name = NULL;
2867 0 : struct dom_sid *sid = NULL;
2868 : uint32_t direction;
2869 :
2870 0 : d = talloc_zero(domains, struct trustdom_info);
2871 0 : if (d == NULL) {
2872 0 : TALLOC_FREE(tmp_ctx);
2873 0 : return NT_STATUS_NO_MEMORY;
2874 : }
2875 :
2876 0 : name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2877 0 : if (name == NULL) {
2878 0 : TALLOC_FREE(tmp_ctx);
2879 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2880 : }
2881 0 : sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2882 0 : if (sid == NULL) {
2883 0 : continue;
2884 : }
2885 :
2886 0 : direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2887 0 : if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2888 0 : continue;
2889 : }
2890 :
2891 0 : d->name = talloc_strdup(d, name);
2892 0 : if (d->name == NULL) {
2893 0 : TALLOC_FREE(tmp_ctx);
2894 0 : return NT_STATUS_NO_MEMORY;
2895 : }
2896 0 : d->sid = *sid;
2897 :
2898 0 : domains[di++] = d;
2899 : }
2900 :
2901 0 : domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2902 0 : *_domains = talloc_move(mem_ctx, &domains);
2903 0 : *_num_domains = di;
2904 0 : TALLOC_FREE(tmp_ctx);
2905 0 : return NT_STATUS_OK;
2906 : }
2907 :
2908 761 : static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2909 : TALLOC_CTX *mem_ctx,
2910 : struct pdb_trusted_domain **_d)
2911 : {
2912 761 : struct pdb_trusted_domain *d = NULL;
2913 761 : const char *str = NULL;
2914 761 : struct dom_sid *sid = NULL;
2915 761 : const struct ldb_val *val = NULL;
2916 : uint64_t val64;
2917 :
2918 761 : *_d = NULL;
2919 :
2920 761 : d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
2921 761 : if (d == NULL) {
2922 0 : return NT_STATUS_NO_MEMORY;
2923 : }
2924 :
2925 761 : str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2926 761 : if (str == NULL) {
2927 0 : TALLOC_FREE(d);
2928 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2929 : }
2930 761 : d->netbios_name = talloc_strdup(d, str);
2931 761 : if (d->netbios_name == NULL) {
2932 0 : TALLOC_FREE(d);
2933 0 : return NT_STATUS_NO_MEMORY;
2934 : }
2935 :
2936 761 : str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2937 761 : if (str != NULL) {
2938 761 : d->domain_name = talloc_strdup(d, str);
2939 761 : if (d->domain_name == NULL) {
2940 0 : TALLOC_FREE(d);
2941 0 : return NT_STATUS_NO_MEMORY;
2942 : }
2943 : }
2944 :
2945 761 : sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
2946 761 : if (sid != NULL) {
2947 761 : d->security_identifier = *sid;
2948 761 : TALLOC_FREE(sid);
2949 : }
2950 :
2951 761 : val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2952 761 : if (val != NULL) {
2953 291 : d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
2954 291 : if (d->trust_auth_outgoing.data == NULL) {
2955 0 : TALLOC_FREE(d);
2956 0 : return NT_STATUS_NO_MEMORY;
2957 : }
2958 : }
2959 761 : val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2960 761 : if (val != NULL) {
2961 289 : d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
2962 289 : if (d->trust_auth_incoming.data == NULL) {
2963 0 : TALLOC_FREE(d);
2964 0 : return NT_STATUS_NO_MEMORY;
2965 : }
2966 : }
2967 :
2968 761 : d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2969 761 : d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
2970 761 : d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
2971 :
2972 761 : val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
2973 761 : if (val64 != UINT64_MAX) {
2974 0 : d->trust_posix_offset = talloc(d, uint32_t);
2975 0 : if (d->trust_posix_offset == NULL) {
2976 0 : TALLOC_FREE(d);
2977 0 : return NT_STATUS_NO_MEMORY;
2978 : }
2979 0 : *d->trust_posix_offset = (uint32_t)val64;
2980 : }
2981 :
2982 761 : val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
2983 761 : if (val64 != UINT64_MAX) {
2984 40 : d->supported_enc_type = talloc(d, uint32_t);
2985 40 : if (d->supported_enc_type == NULL) {
2986 0 : TALLOC_FREE(d);
2987 0 : return NT_STATUS_NO_MEMORY;
2988 : }
2989 40 : *d->supported_enc_type = (uint32_t)val64;
2990 : }
2991 :
2992 761 : val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
2993 761 : if (val != NULL) {
2994 42 : d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
2995 42 : if (d->trust_forest_trust_info.data == NULL) {
2996 0 : TALLOC_FREE(d);
2997 0 : return NT_STATUS_NO_MEMORY;
2998 : }
2999 : }
3000 :
3001 761 : *_d = d;
3002 761 : return NT_STATUS_OK;
3003 : }
3004 :
3005 2 : static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3006 : TALLOC_CTX *mem_ctx,
3007 : const char *domain,
3008 : struct pdb_trusted_domain **td)
3009 : {
3010 2 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3011 : m->private_data, struct pdb_samba_dsdb_state);
3012 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3013 2 : const char * const attrs[] = {
3014 : "securityIdentifier",
3015 : "flatName",
3016 : "trustPartner",
3017 : "trustAuthOutgoing",
3018 : "trustAuthIncoming",
3019 : "trustAttributes",
3020 : "trustDirection",
3021 : "trustType",
3022 : "trustPosixOffset",
3023 : "msDS-SupportedEncryptionTypes",
3024 : "msDS-TrustForestTrustInfo",
3025 : NULL
3026 : };
3027 2 : struct ldb_message *msg = NULL;
3028 2 : struct pdb_trusted_domain *d = NULL;
3029 : NTSTATUS status;
3030 :
3031 2 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3032 : attrs, tmp_ctx, &msg);
3033 2 : if (!NT_STATUS_IS_OK(status)) {
3034 0 : DBG_ERR("dsdb_trust_search_tdo(%s) - %s ",
3035 : domain, nt_errstr(status));
3036 0 : TALLOC_FREE(tmp_ctx);
3037 0 : return status;
3038 : }
3039 :
3040 2 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3041 2 : if (!NT_STATUS_IS_OK(status)) {
3042 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3043 : domain, nt_errstr(status));
3044 0 : TALLOC_FREE(tmp_ctx);
3045 0 : return status;
3046 : }
3047 :
3048 2 : *td = d;
3049 2 : TALLOC_FREE(tmp_ctx);
3050 2 : return NT_STATUS_OK;
3051 : }
3052 :
3053 0 : static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3054 : TALLOC_CTX *mem_ctx,
3055 : struct dom_sid *sid,
3056 : struct pdb_trusted_domain **td)
3057 : {
3058 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3059 : m->private_data, struct pdb_samba_dsdb_state);
3060 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3061 0 : const char * const attrs[] = {
3062 : "securityIdentifier",
3063 : "flatName",
3064 : "trustPartner",
3065 : "trustAuthOutgoing",
3066 : "trustAuthIncoming",
3067 : "trustAttributes",
3068 : "trustDirection",
3069 : "trustType",
3070 : "trustPosixOffset",
3071 : "msDS-SupportedEncryptionTypes",
3072 : "msDS-TrustForestTrustInfo",
3073 : NULL
3074 : };
3075 0 : struct ldb_message *msg = NULL;
3076 0 : struct pdb_trusted_domain *d = NULL;
3077 : struct dom_sid_buf buf;
3078 : NTSTATUS status;
3079 :
3080 0 : status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3081 : attrs, tmp_ctx, &msg);
3082 0 : if (!NT_STATUS_IS_OK(status)) {
3083 0 : DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s ",
3084 : dom_sid_str_buf(sid, &buf),
3085 : nt_errstr(status));
3086 0 : TALLOC_FREE(tmp_ctx);
3087 0 : return status;
3088 : }
3089 :
3090 0 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3091 0 : if (!NT_STATUS_IS_OK(status)) {
3092 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3093 : dom_sid_str_buf(sid, &buf),
3094 : nt_errstr(status));
3095 0 : TALLOC_FREE(tmp_ctx);
3096 0 : return status;
3097 : }
3098 :
3099 0 : *td = d;
3100 0 : TALLOC_FREE(tmp_ctx);
3101 0 : return NT_STATUS_OK;
3102 : }
3103 :
3104 0 : static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3105 : struct ldb_context *sam_ldb,
3106 : struct ldb_dn *base_dn,
3107 : const char *netbios_name,
3108 : struct trustAuthInOutBlob *taiob)
3109 : {
3110 0 : struct ldb_request *req = NULL;
3111 0 : struct ldb_message *msg = NULL;
3112 0 : struct ldb_dn *dn = NULL;
3113 : uint32_t i;
3114 : int ret;
3115 : bool ok;
3116 :
3117 0 : dn = ldb_dn_copy(mem_ctx, base_dn);
3118 0 : if (dn == NULL) {
3119 0 : return NT_STATUS_NO_MEMORY;
3120 : }
3121 0 : ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3122 0 : if (!ok) {
3123 0 : return NT_STATUS_NO_MEMORY;
3124 : }
3125 :
3126 0 : msg = ldb_msg_new(mem_ctx);
3127 0 : if (msg == NULL) {
3128 0 : return NT_STATUS_NO_MEMORY;
3129 : }
3130 0 : msg->dn = dn;
3131 :
3132 0 : ret = ldb_msg_add_string(msg, "objectClass", "user");
3133 0 : if (ret != LDB_SUCCESS) {
3134 0 : return NT_STATUS_NO_MEMORY;
3135 : }
3136 :
3137 0 : ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3138 0 : if (ret != LDB_SUCCESS) {
3139 0 : return NT_STATUS_NO_MEMORY;
3140 : }
3141 :
3142 0 : ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3143 : UF_INTERDOMAIN_TRUST_ACCOUNT);
3144 0 : if (ret != LDB_SUCCESS) {
3145 0 : return NT_STATUS_NO_MEMORY;
3146 : }
3147 :
3148 0 : for (i = 0; i < taiob->count; i++) {
3149 0 : struct AuthenticationInformation *auth_info =
3150 0 : &taiob->current.array[i];
3151 0 : const char *attribute = NULL;
3152 : struct ldb_val v;
3153 :
3154 0 : switch (taiob->current.array[i].AuthType) {
3155 0 : case TRUST_AUTH_TYPE_NT4OWF:
3156 0 : attribute = "unicodePwd";
3157 0 : v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3158 0 : v.length = 16;
3159 0 : break;
3160 :
3161 0 : case TRUST_AUTH_TYPE_CLEAR:
3162 0 : attribute = "clearTextPassword";
3163 0 : v.data = auth_info->AuthInfo.clear.password;
3164 0 : v.length = auth_info->AuthInfo.clear.size;
3165 0 : break;
3166 :
3167 0 : default:
3168 0 : continue;
3169 : }
3170 :
3171 0 : ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3172 0 : if (ret != LDB_SUCCESS) {
3173 0 : return NT_STATUS_NO_MEMORY;
3174 : }
3175 : }
3176 :
3177 : /* create the trusted_domain user account */
3178 0 : ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3179 : ldb_op_default_callback, NULL);
3180 0 : if (ret != LDB_SUCCESS) {
3181 0 : return NT_STATUS_NO_MEMORY;
3182 : }
3183 :
3184 0 : ret = ldb_request_add_control(
3185 : req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3186 : false, NULL);
3187 0 : if (ret != LDB_SUCCESS) {
3188 0 : return NT_STATUS_NO_MEMORY;
3189 : }
3190 :
3191 0 : ret = dsdb_autotransaction_request(sam_ldb, req);
3192 0 : if (ret != LDB_SUCCESS) {
3193 0 : DEBUG(0,("Failed to create user record %s: %s\n",
3194 : ldb_dn_get_linearized(msg->dn),
3195 : ldb_errstring(sam_ldb)));
3196 :
3197 0 : switch (ret) {
3198 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
3199 0 : return NT_STATUS_DOMAIN_EXISTS;
3200 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3201 0 : return NT_STATUS_ACCESS_DENIED;
3202 0 : default:
3203 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3204 : }
3205 : }
3206 :
3207 0 : return NT_STATUS_OK;
3208 : }
3209 :
3210 1 : static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3211 : const char* domain,
3212 : const struct pdb_trusted_domain *td)
3213 : {
3214 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3215 : methods->private_data, struct pdb_samba_dsdb_state);
3216 1 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3217 1 : bool in_txn = false;
3218 1 : struct ldb_dn *base_dn = NULL;
3219 1 : struct ldb_message *msg = NULL;
3220 1 : const char *attrs[] = {
3221 : NULL
3222 : };
3223 1 : char *netbios_encoded = NULL;
3224 1 : char *dns_encoded = NULL;
3225 1 : char *sid_encoded = NULL;
3226 : int ret;
3227 : struct trustAuthInOutBlob taiob;
3228 : enum ndr_err_code ndr_err;
3229 : NTSTATUS status;
3230 : bool ok;
3231 :
3232 1 : base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3233 1 : if (base_dn == NULL) {
3234 0 : TALLOC_FREE(tmp_ctx);
3235 0 : status = NT_STATUS_NO_MEMORY;
3236 0 : goto out;
3237 : }
3238 : /*
3239 : * We expect S-1-5-21-A-B-C, but we don't
3240 : * allow S-1-5-21-0-0-0 as this is used
3241 : * for claims and compound identities.
3242 : */
3243 1 : ok = dom_sid_is_valid_account_domain(&td->security_identifier);
3244 1 : if (!ok) {
3245 0 : status = NT_STATUS_INVALID_PARAMETER;
3246 0 : goto out;
3247 : }
3248 :
3249 1 : if (strequal(td->netbios_name, "BUILTIN")) {
3250 0 : status = NT_STATUS_INVALID_PARAMETER;
3251 0 : goto out;
3252 : }
3253 1 : if (strequal(td->domain_name, "BUILTIN")) {
3254 0 : status = NT_STATUS_INVALID_PARAMETER;
3255 0 : goto out;
3256 : }
3257 :
3258 1 : dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3259 1 : if (dns_encoded == NULL) {
3260 0 : status = NT_STATUS_NO_MEMORY;
3261 0 : goto out;
3262 : }
3263 1 : netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3264 1 : if (netbios_encoded == NULL) {
3265 0 : status =NT_STATUS_NO_MEMORY;
3266 0 : goto out;
3267 : }
3268 1 : sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3269 1 : if (sid_encoded == NULL) {
3270 0 : status = NT_STATUS_NO_MEMORY;
3271 0 : goto out;
3272 : }
3273 :
3274 1 : ok = samdb_is_pdc(state->ldb);
3275 1 : if (!ok) {
3276 0 : DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3277 0 : TALLOC_FREE(tmp_ctx);
3278 0 : status = NT_STATUS_INVALID_DOMAIN_ROLE;
3279 0 : goto out;
3280 : }
3281 :
3282 1 : status = dsdb_trust_search_tdo(state->ldb,
3283 1 : td->netbios_name,
3284 1 : td->domain_name,
3285 : attrs,
3286 : tmp_ctx,
3287 : &msg);
3288 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3289 0 : DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3290 : nt_errstr(status));
3291 0 : status = NT_STATUS_INVALID_DOMAIN_STATE;
3292 0 : goto out;
3293 : }
3294 :
3295 1 : ret = ldb_transaction_start(state->ldb);
3296 1 : if (ret != LDB_SUCCESS) {
3297 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3298 0 : goto out;
3299 : }
3300 1 : in_txn = true;
3301 :
3302 1 : msg = ldb_msg_new(tmp_ctx);
3303 1 : if (msg == NULL) {
3304 0 : status = NT_STATUS_NO_MEMORY;
3305 0 : goto out;
3306 : }
3307 :
3308 1 : msg->dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3309 1 : if (msg->dn == NULL) {
3310 0 : status = NT_STATUS_NO_MEMORY;
3311 0 : goto out;
3312 : }
3313 :
3314 1 : ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s", td->domain_name);
3315 1 : if (!ok) {
3316 0 : status = NT_STATUS_NO_MEMORY;
3317 0 : goto out;
3318 : }
3319 :
3320 1 : ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3321 1 : if (ret != LDB_SUCCESS) {
3322 0 : status = NT_STATUS_NO_MEMORY;
3323 0 : goto out;
3324 : }
3325 :
3326 1 : ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3327 1 : if (ret != LDB_SUCCESS) {
3328 0 : status = NT_STATUS_NO_MEMORY;
3329 0 : goto out;
3330 : }
3331 :
3332 1 : ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3333 1 : if (ret != LDB_SUCCESS) {
3334 0 : status = NT_STATUS_NO_MEMORY;
3335 0 : goto out;
3336 : }
3337 :
3338 1 : ret = samdb_msg_add_dom_sid(state->ldb,
3339 : tmp_ctx,
3340 : msg,
3341 : "securityIdentifier",
3342 : &td->security_identifier);
3343 1 : if (ret != LDB_SUCCESS) {
3344 0 : status = NT_STATUS_NO_MEMORY;
3345 0 : goto out;
3346 : }
3347 :
3348 1 : ret = samdb_msg_add_int(state->ldb,
3349 : tmp_ctx,
3350 : msg,
3351 : "trustType",
3352 1 : td->trust_type);
3353 1 : if (ret != LDB_SUCCESS) {
3354 0 : status = NT_STATUS_NO_MEMORY;
3355 0 : goto out;
3356 : }
3357 :
3358 1 : ret = samdb_msg_add_int(state->ldb,
3359 : tmp_ctx,
3360 : msg,
3361 : "trustAttributes",
3362 1 : td->trust_attributes);
3363 1 : if (ret != LDB_SUCCESS) {
3364 0 : status =NT_STATUS_NO_MEMORY;
3365 0 : goto out;
3366 : }
3367 :
3368 1 : ret = samdb_msg_add_int(state->ldb,
3369 : tmp_ctx,
3370 : msg,
3371 : "trustDirection",
3372 1 : td->trust_direction);
3373 1 : if (ret != LDB_SUCCESS) {
3374 0 : status = NT_STATUS_NO_MEMORY;
3375 0 : goto out;
3376 : }
3377 :
3378 1 : if (td->trust_auth_incoming.data != NULL) {
3379 0 : ret = ldb_msg_add_value(msg,
3380 : "trustAuthIncoming",
3381 0 : &td->trust_auth_incoming,
3382 : NULL);
3383 0 : if (ret != LDB_SUCCESS) {
3384 0 : status = NT_STATUS_NO_MEMORY;
3385 0 : goto out;
3386 : }
3387 : }
3388 1 : if (td->trust_auth_outgoing.data != NULL) {
3389 1 : ret = ldb_msg_add_value(msg,
3390 : "trustAuthOutgoing",
3391 1 : &td->trust_auth_outgoing,
3392 : NULL);
3393 1 : if (ret != LDB_SUCCESS) {
3394 0 : status = NT_STATUS_NO_MEMORY;
3395 0 : goto out;
3396 : }
3397 : }
3398 :
3399 : /* create the trusted_domain */
3400 1 : ret = ldb_add(state->ldb, msg);
3401 1 : switch (ret) {
3402 1 : case LDB_SUCCESS:
3403 1 : break;
3404 :
3405 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
3406 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3407 : ldb_dn_get_linearized(msg->dn),
3408 : ldb_errstring(state->ldb));
3409 0 : status = NT_STATUS_DOMAIN_EXISTS;
3410 0 : goto out;
3411 :
3412 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3413 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3414 : ldb_dn_get_linearized(msg->dn),
3415 : ldb_errstring(state->ldb));
3416 0 : status = NT_STATUS_ACCESS_DENIED;
3417 0 : goto out;
3418 :
3419 0 : default:
3420 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3421 : ldb_dn_get_linearized(msg->dn),
3422 : ldb_errstring(state->ldb));
3423 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3424 0 : goto out;
3425 : }
3426 :
3427 1 : ndr_err = ndr_pull_struct_blob(
3428 : &td->trust_auth_outgoing,
3429 : tmp_ctx,
3430 : &taiob,
3431 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3432 1 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3433 0 : status = ndr_map_error2ntstatus(ndr_err);
3434 0 : goto out;
3435 : }
3436 :
3437 1 : if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3438 0 : status = add_trust_user(tmp_ctx,
3439 : state->ldb,
3440 : base_dn,
3441 0 : td->netbios_name,
3442 : &taiob);
3443 0 : if (!NT_STATUS_IS_OK(status)) {
3444 0 : goto out;
3445 : }
3446 : }
3447 :
3448 1 : ret = ldb_transaction_commit(state->ldb);
3449 1 : if (ret != LDB_SUCCESS) {
3450 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3451 : }
3452 1 : in_txn = false;
3453 :
3454 : /*
3455 : * TODO: Notify winbindd that we have a new trust
3456 : */
3457 :
3458 1 : status = NT_STATUS_OK;
3459 :
3460 1 : out:
3461 1 : if (in_txn) {
3462 0 : ldb_transaction_cancel(state->ldb);
3463 : }
3464 1 : TALLOC_FREE(tmp_ctx);
3465 1 : return status;
3466 : }
3467 :
3468 0 : static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3469 : struct pdb_samba_dsdb_state *state,
3470 : const char *trust_user)
3471 : {
3472 0 : const char *attrs[] = { "userAccountControl", NULL };
3473 : struct ldb_message **msgs;
3474 : uint32_t uac;
3475 : int ret;
3476 :
3477 0 : ret = gendb_search(state->ldb,
3478 : mem_ctx,
3479 : ldb_get_default_basedn(state->ldb),
3480 : &msgs,
3481 : attrs,
3482 : "samAccountName=%s$",
3483 : trust_user);
3484 0 : if (ret > 1) {
3485 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3486 : }
3487 :
3488 0 : if (ret == 0) {
3489 0 : return NT_STATUS_OK;
3490 : }
3491 :
3492 0 : uac = ldb_msg_find_attr_as_uint(msgs[0],
3493 : "userAccountControl",
3494 : 0);
3495 0 : if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3496 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
3497 : }
3498 :
3499 0 : ret = ldb_delete(state->ldb, msgs[0]->dn);
3500 0 : switch (ret) {
3501 0 : case LDB_SUCCESS:
3502 0 : break;
3503 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3504 0 : return NT_STATUS_ACCESS_DENIED;
3505 0 : default:
3506 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3507 : }
3508 :
3509 0 : return NT_STATUS_OK;
3510 : }
3511 :
3512 1 : static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3513 : const char *domain)
3514 : {
3515 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3516 : methods->private_data, struct pdb_samba_dsdb_state);
3517 1 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3518 1 : struct pdb_trusted_domain *td = NULL;
3519 1 : struct ldb_dn *tdo_dn = NULL;
3520 1 : bool in_txn = false;
3521 : NTSTATUS status;
3522 : int ret;
3523 : bool ok;
3524 :
3525 1 : status = pdb_samba_dsdb_get_trusted_domain(methods,
3526 : tmp_ctx,
3527 : domain,
3528 : &td);
3529 1 : if (!NT_STATUS_IS_OK(status)) {
3530 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3531 0 : DBG_ERR("Searching TDO for %s returned %s\n",
3532 : domain, nt_errstr(status));
3533 0 : return status;
3534 : }
3535 0 : DBG_NOTICE("No TDO object for %s\n", domain);
3536 0 : return NT_STATUS_OK;
3537 : }
3538 :
3539 1 : tdo_dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3540 1 : if (tdo_dn == NULL) {
3541 0 : status = NT_STATUS_NO_MEMORY;
3542 0 : goto out;
3543 : }
3544 :
3545 1 : ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s", domain);
3546 1 : if (!ok) {
3547 0 : TALLOC_FREE(tmp_ctx);
3548 0 : status = NT_STATUS_NO_MEMORY;
3549 0 : goto out;
3550 : }
3551 :
3552 1 : ret = ldb_transaction_start(state->ldb);
3553 1 : if (ret != LDB_SUCCESS) {
3554 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3555 0 : goto out;
3556 : }
3557 1 : in_txn = true;
3558 :
3559 1 : ret = ldb_delete(state->ldb, tdo_dn);
3560 1 : if (ret != LDB_SUCCESS) {
3561 0 : status = NT_STATUS_INVALID_HANDLE;
3562 0 : goto out;
3563 : }
3564 :
3565 1 : if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3566 0 : status = delete_trust_user(tmp_ctx, state, domain);
3567 0 : if (!NT_STATUS_IS_OK(status)) {
3568 0 : goto out;
3569 : }
3570 : }
3571 :
3572 1 : ret = ldb_transaction_commit(state->ldb);
3573 1 : if (ret != LDB_SUCCESS) {
3574 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3575 0 : goto out;
3576 : }
3577 1 : in_txn = false;
3578 :
3579 1 : status = NT_STATUS_OK;
3580 :
3581 1 : out:
3582 1 : if (in_txn) {
3583 0 : ldb_transaction_cancel(state->ldb);
3584 : }
3585 1 : TALLOC_FREE(tmp_ctx);
3586 :
3587 1 : return status;
3588 : }
3589 :
3590 198 : static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3591 : TALLOC_CTX *mem_ctx,
3592 : uint32_t *_num_domains,
3593 : struct pdb_trusted_domain ***_domains)
3594 : {
3595 198 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3596 : m->private_data, struct pdb_samba_dsdb_state);
3597 198 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3598 198 : const char * const attrs[] = {
3599 : "securityIdentifier",
3600 : "flatName",
3601 : "trustPartner",
3602 : "trustAuthOutgoing",
3603 : "trustAuthIncoming",
3604 : "trustAttributes",
3605 : "trustDirection",
3606 : "trustType",
3607 : "trustPosixOffset",
3608 : "msDS-SupportedEncryptionTypes",
3609 : "msDS-TrustForestTrustInfo",
3610 : NULL
3611 : };
3612 198 : struct ldb_result *res = NULL;
3613 : unsigned int i;
3614 198 : struct pdb_trusted_domain **domains = NULL;
3615 : NTSTATUS status;
3616 198 : uint32_t di = 0;
3617 :
3618 198 : *_num_domains = 0;
3619 198 : *_domains = NULL;
3620 :
3621 198 : status = dsdb_trust_search_tdos(state->ldb, NULL,
3622 : attrs, tmp_ctx, &res);
3623 198 : if (!NT_STATUS_IS_OK(status)) {
3624 0 : DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
3625 0 : TALLOC_FREE(tmp_ctx);
3626 0 : return status;
3627 : }
3628 :
3629 198 : if (res->count == 0) {
3630 35 : TALLOC_FREE(tmp_ctx);
3631 35 : return NT_STATUS_OK;
3632 : }
3633 :
3634 163 : domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3635 : res->count);
3636 163 : if (domains == NULL) {
3637 0 : TALLOC_FREE(tmp_ctx);
3638 0 : return NT_STATUS_NO_MEMORY;
3639 : }
3640 :
3641 922 : for (i = 0; i < res->count; i++) {
3642 759 : struct ldb_message *msg = res->msgs[i];
3643 759 : struct pdb_trusted_domain *d = NULL;
3644 :
3645 759 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3646 759 : if (!NT_STATUS_IS_OK(status)) {
3647 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s ",
3648 : nt_errstr(status));
3649 0 : TALLOC_FREE(tmp_ctx);
3650 0 : return status;
3651 : }
3652 :
3653 759 : domains[di++] = d;
3654 : }
3655 :
3656 163 : domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3657 : di);
3658 163 : *_domains = talloc_move(mem_ctx, &domains);
3659 163 : *_num_domains = di;
3660 163 : TALLOC_FREE(tmp_ctx);
3661 163 : return NT_STATUS_OK;
3662 : }
3663 :
3664 170 : static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3665 : {
3666 170 : return true;
3667 : }
3668 :
3669 0 : static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3670 : {
3671 0 : return true;
3672 : }
3673 :
3674 3923 : static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3675 : {
3676 3923 : m->name = "samba_dsdb";
3677 3923 : m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3678 3923 : m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3679 3923 : m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3680 3923 : m->create_user = pdb_samba_dsdb_create_user;
3681 3923 : m->delete_user = pdb_samba_dsdb_delete_user;
3682 3923 : m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3683 3923 : m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3684 3923 : m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3685 3923 : m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3686 3923 : m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3687 3923 : m->getgrsid = pdb_samba_dsdb_getgrsid;
3688 3923 : m->getgrgid = pdb_samba_dsdb_getgrgid;
3689 3923 : m->getgrnam = pdb_samba_dsdb_getgrnam;
3690 3923 : m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3691 3923 : m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3692 3923 : m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3693 3923 : m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3694 3923 : m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3695 3923 : m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3696 3923 : m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3697 3923 : m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3698 3923 : m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3699 3923 : m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3700 3923 : m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3701 3923 : m->create_alias = pdb_samba_dsdb_create_alias;
3702 3923 : m->delete_alias = pdb_samba_dsdb_delete_alias;
3703 3923 : m->get_aliasinfo = pdb_default_get_aliasinfo;
3704 3923 : m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3705 3923 : m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3706 3923 : m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3707 3923 : m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3708 3923 : m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3709 3923 : m->lookup_names = pdb_samba_dsdb_lookup_names;
3710 3923 : m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3711 3923 : m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3712 3923 : m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3713 3923 : m->search_users = pdb_samba_dsdb_search_users;
3714 3923 : m->search_groups = pdb_samba_dsdb_search_groups;
3715 3923 : m->search_aliases = pdb_samba_dsdb_search_aliases;
3716 3923 : m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3717 3923 : m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3718 3923 : m->capabilities = pdb_samba_dsdb_capabilities;
3719 3923 : m->new_rid = pdb_samba_dsdb_new_rid;
3720 3923 : m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3721 3923 : m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3722 3923 : m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3723 3923 : m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3724 3923 : m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3725 3923 : m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3726 3923 : m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3727 3923 : m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3728 3923 : m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3729 3923 : m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3730 3923 : m->is_responsible_for_wellknown =
3731 : pdb_samba_dsdb_is_responsible_for_wellknown;
3732 3923 : m->is_responsible_for_everything_else =
3733 : pdb_samba_dsdb_is_responsible_for_everything_else;
3734 3923 : }
3735 :
3736 3738 : static void free_private_data(void **vp)
3737 : {
3738 3738 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3739 : *vp, struct pdb_samba_dsdb_state);
3740 3738 : talloc_unlink(state, state->ldb);
3741 3738 : return;
3742 : }
3743 :
3744 3923 : static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3745 : {
3746 : struct pdb_domain_info *dom_info;
3747 : struct dom_sid stored_sid;
3748 : struct GUID stored_guid;
3749 3923 : bool sid_exists_and_matches = false;
3750 3923 : bool guid_exists_and_matches = false;
3751 : bool ret;
3752 :
3753 3923 : dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3754 3923 : if (!dom_info) {
3755 0 : return NT_STATUS_UNSUCCESSFUL;
3756 : }
3757 :
3758 3923 : ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3759 3923 : if (ret) {
3760 3890 : if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3761 3890 : sid_exists_and_matches = true;
3762 : }
3763 : }
3764 :
3765 3923 : if (sid_exists_and_matches == false) {
3766 33 : secrets_clear_domain_protection(dom_info->name);
3767 33 : ret = secrets_store_domain_sid(dom_info->name,
3768 33 : &dom_info->sid);
3769 33 : ret &= secrets_mark_domain_protected(dom_info->name);
3770 33 : if (!ret) {
3771 0 : goto done;
3772 : }
3773 : }
3774 :
3775 3923 : ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3776 3923 : if (ret) {
3777 3858 : if (GUID_equal(&stored_guid, &dom_info->guid)) {
3778 3858 : guid_exists_and_matches = true;
3779 : }
3780 : }
3781 :
3782 3923 : if (guid_exists_and_matches == false) {
3783 65 : secrets_clear_domain_protection(dom_info->name);
3784 65 : ret = secrets_store_domain_guid(dom_info->name,
3785 65 : &dom_info->guid);
3786 65 : ret &= secrets_mark_domain_protected(dom_info->name);
3787 65 : if (!ret) {
3788 0 : goto done;
3789 : }
3790 : }
3791 :
3792 6909 : done:
3793 3923 : TALLOC_FREE(dom_info);
3794 3923 : if (!ret) {
3795 0 : return NT_STATUS_UNSUCCESSFUL;
3796 : }
3797 3923 : return NT_STATUS_OK;
3798 : }
3799 :
3800 3923 : static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3801 : const char *location)
3802 : {
3803 : struct pdb_methods *m;
3804 : struct pdb_samba_dsdb_state *state;
3805 : NTSTATUS status;
3806 3923 : char *errstring = NULL;
3807 : int ret;
3808 :
3809 3923 : if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3810 0 : return status;
3811 : }
3812 :
3813 3923 : state = talloc_zero(m, struct pdb_samba_dsdb_state);
3814 3923 : if (state == NULL) {
3815 0 : goto nomem;
3816 : }
3817 3923 : m->private_data = state;
3818 3923 : m->free_private_data = free_private_data;
3819 3923 : pdb_samba_dsdb_init_methods(m);
3820 :
3821 3923 : state->ev = s4_event_context_init(state);
3822 3923 : if (!state->ev) {
3823 0 : DEBUG(0, ("s4_event_context_init failed\n"));
3824 0 : goto nomem;
3825 : }
3826 :
3827 3923 : state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3828 3923 : if (state->lp_ctx == NULL) {
3829 0 : DEBUG(0, ("loadparm_init_s3 failed\n"));
3830 0 : goto nomem;
3831 : }
3832 :
3833 3923 : if (location == NULL) {
3834 3865 : location = "sam.ldb";
3835 : }
3836 :
3837 3923 : ret = samdb_connect_url(state,
3838 : state->ev,
3839 : state->lp_ctx,
3840 : system_session(state->lp_ctx),
3841 : 0,
3842 : location,
3843 : NULL,
3844 : &state->ldb,
3845 : &errstring);
3846 :
3847 3923 : if (!state->ldb) {
3848 0 : DEBUG(0, ("samdb_connect failed: %s: %s\n",
3849 : errstring, ldb_strerror(ret)));
3850 0 : status = NT_STATUS_INTERNAL_ERROR;
3851 0 : goto fail;
3852 : }
3853 :
3854 3923 : state->idmap_ctx = idmap_init(state, state->ev,
3855 : state->lp_ctx);
3856 3923 : if (!state->idmap_ctx) {
3857 0 : DEBUG(0, ("idmap failed\n"));
3858 0 : status = NT_STATUS_INTERNAL_ERROR;
3859 0 : goto fail;
3860 : }
3861 :
3862 3923 : status = pdb_samba_dsdb_init_secrets(m);
3863 3923 : if (!NT_STATUS_IS_OK(status)) {
3864 0 : DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3865 0 : goto fail;
3866 : }
3867 :
3868 3923 : *pdb_method = m;
3869 3923 : return NT_STATUS_OK;
3870 0 : nomem:
3871 0 : status = NT_STATUS_NO_MEMORY;
3872 0 : fail:
3873 0 : TALLOC_FREE(m);
3874 0 : return status;
3875 : }
3876 :
3877 : NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3878 757 : NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3879 : {
3880 757 : NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3881 : pdb_init_samba_dsdb);
3882 757 : if (!NT_STATUS_IS_OK(status)) {
3883 0 : return status;
3884 : }
3885 757 : return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3886 : pdb_init_samba_dsdb);
3887 : }
|