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 3880 : static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
76 : struct pdb_methods *m, TALLOC_CTX *mem_ctx)
77 : {
78 3880 : 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 3880 : struct ldb_result *dom_res = NULL;
84 3880 : const char *dom_attrs[] = {
85 : "objectSid",
86 : "objectGUID",
87 : "fSMORoleOwner",
88 : NULL
89 : };
90 : char *p;
91 : int ret;
92 :
93 3880 : info = talloc(mem_ctx, struct pdb_domain_info);
94 3880 : if (info == NULL) {
95 0 : return NULL;
96 : }
97 :
98 3880 : domain_dn = ldb_get_default_basedn(state->ldb);
99 :
100 3880 : ret = ldb_search(state->ldb, info, &dom_res,
101 : domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
102 3880 : if (ret != LDB_SUCCESS) {
103 0 : goto fail;
104 : }
105 3880 : if (dom_res->count != 1) {
106 0 : goto fail;
107 : }
108 :
109 3880 : info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
110 :
111 3880 : domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
112 3880 : if (!domain_sid) {
113 0 : goto fail;
114 : }
115 3880 : info->sid = *domain_sid;
116 :
117 3880 : TALLOC_FREE(dom_res);
118 :
119 3880 : info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
120 3880 : info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
121 :
122 3880 : if (!info->dns_domain) {
123 0 : goto fail;
124 : }
125 3880 : p = strchr(info->dns_domain, '/');
126 3880 : if (p) {
127 3880 : *p = '\0';
128 : }
129 :
130 3880 : forest_dn = ldb_get_root_basedn(state->ldb);
131 3880 : if (!forest_dn) {
132 0 : goto fail;
133 : }
134 :
135 3880 : info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
136 3880 : if (!info->dns_forest) {
137 0 : goto fail;
138 : }
139 3880 : p = strchr(info->dns_forest, '/');
140 3880 : if (p) {
141 3880 : *p = '\0';
142 : }
143 :
144 3880 : 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 1929 : static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
900 : const char *exp_fmt, ...)
901 : {
902 1929 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
903 : m->private_data, struct pdb_samba_dsdb_state);
904 1929 : const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
905 : NULL };
906 : struct ldb_message *msg;
907 : va_list ap;
908 1929 : 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 1929 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
915 1929 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
916 :
917 1929 : va_start(ap, exp_fmt);
918 1929 : expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
919 1929 : va_end(ap);
920 :
921 1929 : if (!expression) {
922 0 : talloc_free(tmp_ctx);
923 0 : return NT_STATUS_NO_MEMORY;
924 : }
925 :
926 1929 : rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
927 1929 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
928 0 : talloc_free(tmp_ctx);
929 0 : return NT_STATUS_NO_SUCH_GROUP;
930 1929 : } 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 1929 : sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
938 1929 : 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 1929 : map->sid = *sid;
945 :
946 1929 : if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
947 : NTSTATUS status;
948 1929 : uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
949 1929 : switch (grouptype) {
950 1929 : case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
951 : case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
952 1929 : map->sid_name_use = SID_NAME_ALIAS;
953 1929 : 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 1929 : ZERO_STRUCT(id_map);
964 1929 : id_map.sid = sid;
965 1929 : id_maps[0] = &id_map;
966 1929 : id_maps[1] = NULL;
967 :
968 1929 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
969 :
970 1929 : if (!NT_STATUS_IS_OK(status)) {
971 0 : talloc_free(tmp_ctx);
972 0 : return status;
973 : }
974 1929 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
975 1929 : 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 1929 : str = ldb_msg_find_attr_as_string(msg, "samAccountName",
988 : NULL);
989 1929 : if (str == NULL) {
990 0 : talloc_free(tmp_ctx);
991 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
992 : }
993 1929 : map->nt_name = talloc_strdup(map, str);
994 1929 : if (!map->nt_name) {
995 0 : talloc_free(tmp_ctx);
996 0 : return NT_STATUS_NO_MEMORY;
997 : }
998 :
999 1929 : str = ldb_msg_find_attr_as_string(msg, "description",
1000 : NULL);
1001 1929 : if (str != NULL) {
1002 1929 : map->comment = talloc_strdup(map, str);
1003 : } else {
1004 0 : map->comment = talloc_strdup(map, "");
1005 : }
1006 1929 : if (!map->comment) {
1007 0 : talloc_free(tmp_ctx);
1008 0 : return NT_STATUS_NO_MEMORY;
1009 : }
1010 :
1011 1929 : talloc_free(tmp_ctx);
1012 1929 : return NT_STATUS_OK;
1013 : }
1014 :
1015 1929 : 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 1929 : filter = talloc_asprintf(talloc_tos(),
1023 : "(&(objectsid=%s)(objectclass=group))",
1024 : dom_sid_str_buf(&sid, &buf));
1025 1929 : if (filter == NULL) {
1026 0 : return NT_STATUS_NO_MEMORY;
1027 : }
1028 :
1029 1929 : status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1030 1929 : TALLOC_FREE(filter);
1031 1929 : 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 0 : } else if (rc != LDB_SUCCESS) {
1138 0 : talloc_free(tmp_ctx);
1139 0 : DEBUG(10, ("dsdb_search_one failed %s\n",
1140 : ldb_errstring(state->ldb)));
1141 0 : ldb_transaction_cancel(state->ldb);
1142 0 : return NT_STATUS_LDAP(rc);
1143 : }
1144 0 : rc = ldb_delete(state->ldb, dn);
1145 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1146 0 : talloc_free(tmp_ctx);
1147 0 : ldb_transaction_cancel(state->ldb);
1148 0 : return NT_STATUS_NO_SUCH_GROUP;
1149 0 : } else if (rc != LDB_SUCCESS) {
1150 0 : DEBUG(10, ("ldb_delete failed %s\n",
1151 : ldb_errstring(state->ldb)));
1152 0 : ldb_transaction_cancel(state->ldb);
1153 0 : return NT_STATUS_LDAP(rc);
1154 : }
1155 :
1156 0 : if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1157 0 : DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1158 0 : return NT_STATUS_INTERNAL_ERROR;
1159 : }
1160 0 : return NT_STATUS_OK;
1161 : }
1162 :
1163 0 : static NTSTATUS pdb_samba_dsdb_add_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_update_group_mapping_entry(struct pdb_methods *m,
1170 : GROUP_MAP *map)
1171 : {
1172 0 : return NT_STATUS_NOT_IMPLEMENTED;
1173 : }
1174 :
1175 0 : static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1176 : struct dom_sid sid)
1177 : {
1178 0 : return NT_STATUS_NOT_IMPLEMENTED;
1179 : }
1180 :
1181 0 : static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1182 : const struct dom_sid *sid,
1183 : enum lsa_SidType sid_name_use,
1184 : GROUP_MAP ***pp_rmap,
1185 : size_t *p_num_entries,
1186 : bool unix_only)
1187 : {
1188 0 : return NT_STATUS_NOT_IMPLEMENTED;
1189 : }
1190 :
1191 0 : static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1192 : TALLOC_CTX *mem_ctx,
1193 : const struct dom_sid *group,
1194 : uint32_t **pmembers,
1195 : size_t *pnum_members)
1196 : {
1197 : unsigned int i, num_sids, num_members;
1198 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1199 : m->private_data, struct pdb_samba_dsdb_state);
1200 : struct dom_sid *members_as_sids;
1201 : struct dom_sid *dom_sid;
1202 : uint32_t *members;
1203 : struct ldb_dn *dn;
1204 : NTSTATUS status;
1205 : struct dom_sid_buf buf;
1206 :
1207 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1208 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1209 :
1210 0 : dn = ldb_dn_new_fmt(
1211 : tmp_ctx,
1212 : state->ldb,
1213 : "<SID=%s>",
1214 : dom_sid_str_buf(group, &buf));
1215 0 : if (!dn || !ldb_dn_validate(dn)) {
1216 0 : return NT_STATUS_NO_MEMORY;
1217 : }
1218 :
1219 0 : status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1220 0 : if (!NT_STATUS_IS_OK(status)) {
1221 0 : talloc_free(tmp_ctx);
1222 0 : return status;
1223 : }
1224 0 : status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1225 0 : if (!NT_STATUS_IS_OK(status)) {
1226 0 : talloc_free(tmp_ctx);
1227 0 : return status;
1228 : }
1229 :
1230 0 : *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1231 0 : if (*pmembers == NULL) {
1232 0 : TALLOC_FREE(tmp_ctx);
1233 0 : return NT_STATUS_NO_MEMORY;
1234 : }
1235 0 : num_members = 0;
1236 :
1237 0 : for (i = 0; i < num_sids; i++) {
1238 0 : if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1239 0 : continue;
1240 : }
1241 0 : status = dom_sid_split_rid(NULL, &members_as_sids[i],
1242 0 : NULL, &members[num_members]);
1243 0 : if (!NT_STATUS_IS_OK(status)) {
1244 0 : talloc_free(tmp_ctx);
1245 0 : return status;
1246 : }
1247 0 : num_members++;
1248 : }
1249 0 : *pnum_members = num_members;
1250 0 : return NT_STATUS_OK;
1251 : }
1252 :
1253 : /* Just convert the primary group SID into a group */
1254 0 : static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1255 : TALLOC_CTX *mem_ctx,
1256 : struct samu *user,
1257 : struct dom_sid **pp_sids,
1258 : gid_t **pp_gids,
1259 : uint32_t *p_num_groups)
1260 : {
1261 : NTSTATUS status;
1262 0 : size_t num_groups = 0;
1263 0 : struct dom_sid *group_sids = NULL;
1264 0 : gid_t *gids = NULL;
1265 : TALLOC_CTX *tmp_ctx;
1266 :
1267 0 : tmp_ctx = talloc_new(mem_ctx);
1268 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1269 :
1270 0 : if (user->group_sid) {
1271 : struct id_map *id_maps[2];
1272 : struct id_map id_map;
1273 :
1274 0 : num_groups = 1;
1275 :
1276 0 : group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1277 0 : if (group_sids == NULL) {
1278 0 : talloc_free(tmp_ctx);
1279 0 : return NT_STATUS_NO_MEMORY;
1280 : }
1281 0 : gids = talloc_array(tmp_ctx, gid_t, num_groups);
1282 0 : if (gids == NULL) {
1283 0 : talloc_free(tmp_ctx);
1284 0 : return NT_STATUS_NO_MEMORY;
1285 : }
1286 :
1287 0 : group_sids[0] = *user->group_sid;
1288 :
1289 0 : ZERO_STRUCT(id_map);
1290 0 : id_map.sid = &group_sids[0];
1291 0 : id_maps[0] = &id_map;
1292 0 : id_maps[1] = NULL;
1293 :
1294 0 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1295 0 : if (!NT_STATUS_IS_OK(status)) {
1296 0 : talloc_free(tmp_ctx);
1297 0 : return status;
1298 : }
1299 0 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1300 0 : gids[0] = id_map.xid.id;
1301 : } else {
1302 : struct dom_sid_buf buf1, buf2;
1303 0 : DEBUG(1, (__location__
1304 : "Group %s, of which %s is a member, could not be converted to a GID\n",
1305 : dom_sid_str_buf(&group_sids[0], &buf1),
1306 : dom_sid_str_buf(&user->user_sid, &buf2)));
1307 0 : talloc_free(tmp_ctx);
1308 : /* We must error out, otherwise a user might
1309 : * avoid a DENY acl based on a group they
1310 : * missed out on */
1311 0 : return NT_STATUS_NO_SUCH_GROUP;
1312 : }
1313 : }
1314 :
1315 0 : *pp_sids = talloc_steal(mem_ctx, group_sids);
1316 0 : *pp_gids = talloc_steal(mem_ctx, gids);
1317 0 : *p_num_groups = num_groups;
1318 0 : talloc_free(tmp_ctx);
1319 0 : return NT_STATUS_OK;
1320 : }
1321 :
1322 2295 : static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1323 : TALLOC_CTX *mem_ctx,
1324 : struct samu *user,
1325 : struct dom_sid **pp_sids,
1326 : gid_t **pp_gids,
1327 : uint32_t *p_num_groups)
1328 : {
1329 2295 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1330 : m->private_data, struct pdb_samba_dsdb_state);
1331 2295 : struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1332 : m, user);
1333 2295 : const char *attrs[] = { "tokenGroups", NULL};
1334 : struct ldb_message *tokengroups_msg;
1335 : struct ldb_message_element *tokengroups;
1336 : int i, rc;
1337 : NTSTATUS status;
1338 2295 : unsigned int count = 0;
1339 : size_t num_groups;
1340 : struct dom_sid *group_sids;
1341 : gid_t *gids;
1342 : TALLOC_CTX *tmp_ctx;
1343 :
1344 2295 : if (msg == NULL) {
1345 : /* Fake up some things here */
1346 0 : return fake_enum_group_memberships(state,
1347 : mem_ctx,
1348 : user, pp_sids,
1349 : pp_gids, p_num_groups);
1350 : }
1351 :
1352 2295 : tmp_ctx = talloc_new(mem_ctx);
1353 2295 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1354 :
1355 2295 : rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1356 :
1357 2295 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1358 0 : talloc_free(tmp_ctx);
1359 0 : return NT_STATUS_NO_SUCH_USER;
1360 2295 : } else if (rc != LDB_SUCCESS) {
1361 0 : DEBUG(10, ("dsdb_search_one failed %s\n",
1362 : ldb_errstring(state->ldb)));
1363 0 : talloc_free(tmp_ctx);
1364 0 : return NT_STATUS_LDAP(rc);
1365 : }
1366 :
1367 2295 : tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1368 :
1369 2295 : if (tokengroups) {
1370 2295 : count = tokengroups->num_values;
1371 : }
1372 :
1373 2295 : group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1374 2295 : if (group_sids == NULL) {
1375 0 : talloc_free(tmp_ctx);
1376 0 : return NT_STATUS_NO_MEMORY;
1377 : }
1378 2295 : gids = talloc_array(tmp_ctx, gid_t, count);
1379 2295 : if (gids == NULL) {
1380 0 : talloc_free(tmp_ctx);
1381 0 : return NT_STATUS_NO_MEMORY;
1382 : }
1383 2295 : num_groups = 0;
1384 :
1385 18354 : for (i=0; i<count; i++) {
1386 : struct id_map *id_maps[2];
1387 : struct id_map id_map;
1388 18354 : struct ldb_val *v = &tokengroups->values[i];
1389 : enum ndr_err_code ndr_err
1390 18354 : = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1391 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1392 18354 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1393 0 : talloc_free(tmp_ctx);
1394 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1395 : }
1396 :
1397 18354 : ZERO_STRUCT(id_map);
1398 18354 : id_map.sid = &group_sids[num_groups];
1399 18354 : id_maps[0] = &id_map;
1400 18354 : id_maps[1] = NULL;
1401 :
1402 18354 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1403 18354 : if (!NT_STATUS_IS_OK(status)) {
1404 0 : talloc_free(tmp_ctx);
1405 0 : return status;
1406 : }
1407 18354 : if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1408 18354 : gids[num_groups] = id_map.xid.id;
1409 : } else {
1410 : struct dom_sid_buf buf;
1411 0 : DEBUG(1, (__location__
1412 : "Group %s, of which %s is a member, could not be converted to a GID\n",
1413 : dom_sid_str_buf(&group_sids[num_groups],
1414 : &buf),
1415 : ldb_dn_get_linearized(msg->dn)));
1416 0 : talloc_free(tmp_ctx);
1417 : /* We must error out, otherwise a user might
1418 : * avoid a DENY acl based on a group they
1419 : * missed out on */
1420 0 : return NT_STATUS_NO_SUCH_GROUP;
1421 : }
1422 :
1423 18354 : num_groups += 1;
1424 18354 : if (num_groups == count) {
1425 2295 : break;
1426 : }
1427 : }
1428 :
1429 2295 : *pp_sids = talloc_steal(mem_ctx, group_sids);
1430 2295 : *pp_gids = talloc_steal(mem_ctx, gids);
1431 2295 : *p_num_groups = num_groups;
1432 2295 : talloc_free(tmp_ctx);
1433 2295 : return NT_STATUS_OK;
1434 : }
1435 :
1436 0 : static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1437 : TALLOC_CTX *mem_ctx,
1438 : struct samu *user)
1439 : {
1440 0 : return NT_STATUS_NOT_IMPLEMENTED;
1441 : }
1442 :
1443 0 : static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1444 : TALLOC_CTX *mem_ctx,
1445 : const struct dom_sid *groupsid,
1446 : const struct dom_sid *membersid,
1447 : int mod_op)
1448 : {
1449 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1450 : m->private_data, struct pdb_samba_dsdb_state);
1451 : struct ldb_message *msg;
1452 : int ret;
1453 : struct ldb_message_element *el;
1454 : struct dom_sid_buf buf;
1455 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1456 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1457 0 : msg = ldb_msg_new(tmp_ctx);
1458 0 : if (msg == NULL) {
1459 0 : TALLOC_FREE(tmp_ctx);
1460 0 : return NT_STATUS_NO_MEMORY;
1461 : }
1462 :
1463 0 : msg->dn = ldb_dn_new_fmt(
1464 : msg,
1465 : state->ldb,
1466 : "<SID=%s>",
1467 : dom_sid_str_buf(groupsid, &buf));
1468 0 : if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1469 0 : talloc_free(tmp_ctx);
1470 0 : return NT_STATUS_NO_MEMORY;
1471 : }
1472 0 : ret = ldb_msg_add_fmt(
1473 : msg,
1474 : "member",
1475 : "<SID=%s>",
1476 : dom_sid_str_buf(membersid, &buf));
1477 0 : if (ret != LDB_SUCCESS) {
1478 0 : talloc_free(tmp_ctx);
1479 0 : return NT_STATUS_NO_MEMORY;
1480 : }
1481 0 : el = ldb_msg_find_element(msg, "member");
1482 0 : el->flags = mod_op;
1483 :
1484 : /* No need for transactions here, the ldb auto-transaction
1485 : * code will handle things for the single operation */
1486 0 : ret = ldb_modify(state->ldb, msg);
1487 0 : talloc_free(tmp_ctx);
1488 0 : if (ret != LDB_SUCCESS) {
1489 0 : DEBUG(10, ("ldb_modify failed: %s\n",
1490 : ldb_errstring(state->ldb)));
1491 0 : if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1492 0 : return NT_STATUS_MEMBER_IN_GROUP;
1493 : }
1494 0 : if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1495 0 : return NT_STATUS_MEMBER_NOT_IN_GROUP;
1496 : }
1497 0 : return NT_STATUS_LDAP(ret);
1498 : }
1499 :
1500 0 : return NT_STATUS_OK;
1501 : }
1502 :
1503 0 : static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1504 : TALLOC_CTX *mem_ctx,
1505 : uint32_t grouprid, uint32_t memberrid,
1506 : int mod_op)
1507 : {
1508 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1509 : m->private_data, struct pdb_samba_dsdb_state);
1510 : const struct dom_sid *dom_sid, *groupsid, *membersid;
1511 : NTSTATUS status;
1512 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1513 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1514 :
1515 0 : dom_sid = samdb_domain_sid(state->ldb);
1516 :
1517 0 : groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1518 0 : if (groupsid == NULL) {
1519 0 : TALLOC_FREE(tmp_ctx);
1520 0 : return NT_STATUS_NO_MEMORY;
1521 : }
1522 0 : membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1523 0 : if (membersid == NULL) {
1524 0 : TALLOC_FREE(tmp_ctx);
1525 0 : return NT_STATUS_NO_MEMORY;
1526 : }
1527 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1528 0 : talloc_free(tmp_ctx);
1529 0 : return status;
1530 : }
1531 :
1532 0 : static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1533 : TALLOC_CTX *mem_ctx,
1534 : uint32_t group_rid, uint32_t member_rid)
1535 : {
1536 0 : return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1537 : LDB_FLAG_MOD_ADD);
1538 : }
1539 :
1540 0 : static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1541 : TALLOC_CTX *mem_ctx,
1542 : uint32_t group_rid, uint32_t member_rid)
1543 : {
1544 0 : return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1545 : LDB_FLAG_MOD_DELETE);
1546 : }
1547 :
1548 0 : static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1549 : const char *name, uint32_t *rid)
1550 : {
1551 0 : TALLOC_CTX *frame = talloc_stackframe();
1552 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1553 : m->private_data, struct pdb_samba_dsdb_state);
1554 : struct dom_sid *sid;
1555 :
1556 : struct ldb_dn *dn;
1557 : NTSTATUS status;
1558 :
1559 : /* Internally this uses transactions to ensure all the steps
1560 : * happen or fail as one */
1561 0 : status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1562 0 : if (!NT_STATUS_IS_OK(status)) {
1563 0 : TALLOC_FREE(frame);
1564 : }
1565 :
1566 0 : sid_peek_rid(sid, rid);
1567 0 : TALLOC_FREE(frame);
1568 0 : return NT_STATUS_OK;
1569 : }
1570 :
1571 0 : static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1572 : const struct dom_sid *sid)
1573 : {
1574 0 : const char *attrs[] = { NULL };
1575 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1576 : m->private_data, struct pdb_samba_dsdb_state);
1577 : struct ldb_message *msg;
1578 : struct ldb_dn *dn;
1579 : int rc;
1580 : struct dom_sid_buf buf;
1581 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1582 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1583 :
1584 0 : dn = ldb_dn_new_fmt(
1585 : tmp_ctx,
1586 : state->ldb,
1587 : "<SID=%s>",
1588 : dom_sid_str_buf(sid, &buf));
1589 0 : if (!dn || !ldb_dn_validate(dn)) {
1590 0 : talloc_free(tmp_ctx);
1591 0 : return NT_STATUS_NO_MEMORY;
1592 : }
1593 :
1594 0 : if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1595 0 : DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1596 0 : talloc_free(tmp_ctx);
1597 0 : return NT_STATUS_INTERNAL_ERROR;
1598 : }
1599 :
1600 0 : rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1601 : "(|(grouptype=%d)(grouptype=%d)))",
1602 : GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1603 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
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 : talloc_free(tmp_ctx);
1610 0 : DEBUG(10, ("dsdb_search_one failed %s\n",
1611 : ldb_errstring(state->ldb)));
1612 0 : ldb_transaction_cancel(state->ldb);
1613 0 : return NT_STATUS_LDAP(rc);
1614 : }
1615 0 : rc = ldb_delete(state->ldb, dn);
1616 0 : if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1617 0 : talloc_free(tmp_ctx);
1618 0 : ldb_transaction_cancel(state->ldb);
1619 0 : return NT_STATUS_NO_SUCH_ALIAS;
1620 0 : } else if (rc != LDB_SUCCESS) {
1621 0 : DEBUG(10, ("ldb_delete failed %s\n",
1622 : ldb_errstring(state->ldb)));
1623 0 : ldb_transaction_cancel(state->ldb);
1624 0 : talloc_free(tmp_ctx);
1625 0 : return NT_STATUS_LDAP(rc);
1626 : }
1627 :
1628 0 : if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1629 0 : DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1630 : ldb_errstring(state->ldb)));
1631 0 : talloc_free(tmp_ctx);
1632 0 : return NT_STATUS_INTERNAL_ERROR;
1633 : }
1634 :
1635 0 : talloc_free(tmp_ctx);
1636 0 : return NT_STATUS_OK;
1637 : }
1638 :
1639 0 : static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1640 : const struct dom_sid *alias,
1641 : const struct dom_sid *member)
1642 : {
1643 : NTSTATUS status;
1644 0 : TALLOC_CTX *frame = talloc_stackframe();
1645 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1646 0 : talloc_free(frame);
1647 0 : return status;
1648 : }
1649 :
1650 0 : static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1651 : const struct dom_sid *alias,
1652 : const struct dom_sid *member)
1653 : {
1654 : NTSTATUS status;
1655 0 : TALLOC_CTX *frame = talloc_stackframe();
1656 0 : status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1657 0 : talloc_free(frame);
1658 0 : return status;
1659 : }
1660 :
1661 0 : static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1662 : const struct dom_sid *alias,
1663 : TALLOC_CTX *mem_ctx,
1664 : struct dom_sid **pmembers,
1665 : size_t *pnum_members)
1666 : {
1667 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1668 : m->private_data, struct pdb_samba_dsdb_state);
1669 : struct ldb_dn *dn;
1670 : unsigned int num_members;
1671 : NTSTATUS status;
1672 : struct dom_sid_buf buf;
1673 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1674 0 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1675 :
1676 0 : dn = ldb_dn_new_fmt(
1677 : tmp_ctx,
1678 : state->ldb,
1679 : "<SID=%s>",
1680 : dom_sid_str_buf(alias, &buf));
1681 0 : if (!dn || !ldb_dn_validate(dn)) {
1682 0 : return NT_STATUS_NO_MEMORY;
1683 : }
1684 :
1685 0 : status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1686 0 : if (NT_STATUS_IS_OK(status)) {
1687 0 : *pnum_members = num_members;
1688 : }
1689 0 : talloc_free(tmp_ctx);
1690 0 : return status;
1691 : }
1692 :
1693 1286 : static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1694 : TALLOC_CTX *mem_ctx,
1695 : const struct dom_sid *domain_sid,
1696 : const struct dom_sid *members,
1697 : size_t num_members,
1698 : uint32_t **palias_rids,
1699 : size_t *pnum_alias_rids)
1700 : {
1701 1286 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1702 : m->private_data, struct pdb_samba_dsdb_state);
1703 1286 : uint32_t *alias_rids = NULL;
1704 1286 : size_t num_alias_rids = 0;
1705 : int i;
1706 1286 : struct dom_sid *groupSIDs = NULL;
1707 1286 : unsigned int num_groupSIDs = 0;
1708 : char *filter;
1709 : NTSTATUS status;
1710 : const char *sid_dn;
1711 : DATA_BLOB sid_blob;
1712 :
1713 1286 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1714 1286 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1715 : /*
1716 : * TODO: Get the filter right so that we only get the aliases from
1717 : * either the SAM or BUILTIN
1718 : */
1719 :
1720 1286 : filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1721 : GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1722 1286 : if (filter == NULL) {
1723 0 : return NT_STATUS_NO_MEMORY;
1724 : }
1725 :
1726 27098 : for (i = 0; i < num_members; i++) {
1727 : struct dom_sid_buf buf;
1728 :
1729 25812 : sid_dn = talloc_asprintf(
1730 : tmp_ctx,
1731 : "<SID=%s>",
1732 25812 : dom_sid_str_buf(&members[i], &buf));
1733 25812 : if (sid_dn == NULL) {
1734 0 : TALLOC_FREE(tmp_ctx);
1735 0 : return NT_STATUS_NO_MEMORY;
1736 : }
1737 :
1738 25812 : sid_blob = data_blob_string_const(sid_dn);
1739 :
1740 25812 : status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1741 : tmp_ctx, &groupSIDs, &num_groupSIDs);
1742 25812 : if (!NT_STATUS_IS_OK(status)) {
1743 0 : talloc_free(tmp_ctx);
1744 0 : return status;
1745 : }
1746 : }
1747 :
1748 1286 : alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1749 1286 : if (alias_rids == NULL) {
1750 0 : talloc_free(tmp_ctx);
1751 0 : return NT_STATUS_NO_MEMORY;
1752 : }
1753 :
1754 5068 : for (i=0; i<num_groupSIDs; i++) {
1755 3782 : if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1756 3782 : &alias_rids[num_alias_rids])) {
1757 1891 : num_alias_rids++;;
1758 : }
1759 : }
1760 :
1761 1286 : *palias_rids = alias_rids;
1762 1286 : *pnum_alias_rids = num_alias_rids;
1763 1286 : return NT_STATUS_OK;
1764 : }
1765 :
1766 2294 : static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1767 : const struct dom_sid *domain_sid,
1768 : int num_rids,
1769 : uint32_t *rids,
1770 : const char **names,
1771 : enum lsa_SidType *lsa_attrs)
1772 : {
1773 2294 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1774 : m->private_data, struct pdb_samba_dsdb_state);
1775 : NTSTATUS status;
1776 :
1777 : TALLOC_CTX *tmp_ctx;
1778 :
1779 2294 : if (num_rids == 0) {
1780 0 : return NT_STATUS_NONE_MAPPED;
1781 : }
1782 :
1783 2294 : tmp_ctx = talloc_stackframe();
1784 2294 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1785 :
1786 2294 : status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1787 2294 : talloc_free(tmp_ctx);
1788 2294 : return status;
1789 : }
1790 :
1791 0 : static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1792 : const struct dom_sid *domain_sid,
1793 : int num_names,
1794 : const char **pp_names,
1795 : uint32_t *rids,
1796 : enum lsa_SidType *attrs)
1797 : {
1798 0 : return NT_STATUS_NOT_IMPLEMENTED;
1799 : }
1800 :
1801 62 : static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1802 : enum pdb_policy_type type,
1803 : uint32_t *value)
1804 : {
1805 62 : return account_policy_get(type, value)
1806 62 : ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1807 : }
1808 :
1809 0 : static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1810 : enum pdb_policy_type type,
1811 : uint32_t value)
1812 : {
1813 0 : return account_policy_set(type, value)
1814 0 : ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1815 : }
1816 :
1817 0 : static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1818 : time_t *seq_num_out)
1819 : {
1820 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1821 : m->private_data, struct pdb_samba_dsdb_state);
1822 : uint64_t seq_num;
1823 0 : int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1824 0 : if (ret == LDB_SUCCESS) {
1825 0 : *seq_num_out = seq_num;
1826 0 : return NT_STATUS_OK;
1827 : } else {
1828 0 : return NT_STATUS_UNSUCCESSFUL;
1829 : }
1830 : }
1831 :
1832 : struct pdb_samba_dsdb_search_state {
1833 : uint32_t acct_flags;
1834 : struct samr_displayentry *entries;
1835 : uint32_t num_entries;
1836 : ssize_t array_size;
1837 : uint32_t current;
1838 : };
1839 :
1840 0 : static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1841 : struct samr_displayentry *entry)
1842 : {
1843 0 : struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1844 : search->private_data, struct pdb_samba_dsdb_search_state);
1845 :
1846 0 : if (state->current == state->num_entries) {
1847 0 : return false;
1848 : }
1849 :
1850 0 : entry->idx = state->entries[state->current].idx;
1851 0 : entry->rid = state->entries[state->current].rid;
1852 0 : entry->acct_flags = state->entries[state->current].acct_flags;
1853 :
1854 0 : entry->account_name = talloc_strdup(
1855 0 : search, state->entries[state->current].account_name);
1856 0 : entry->fullname = talloc_strdup(
1857 0 : search, state->entries[state->current].fullname);
1858 0 : entry->description = talloc_strdup(
1859 0 : search, state->entries[state->current].description);
1860 :
1861 0 : state->current += 1;
1862 0 : return true;
1863 : }
1864 :
1865 0 : static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1866 : {
1867 0 : struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1868 : search->private_data, struct pdb_samba_dsdb_search_state);
1869 0 : talloc_free(state);
1870 0 : }
1871 :
1872 : static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1873 : struct pdb_search *search,
1874 : struct pdb_samba_dsdb_search_state **pstate,
1875 : const char *exp_fmt, ...)
1876 : PRINTF_ATTRIBUTE(4, 5);
1877 :
1878 0 : static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1879 : struct pdb_search *search,
1880 : struct pdb_samba_dsdb_search_state **pstate,
1881 : const char *exp_fmt, ...)
1882 : {
1883 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1884 : m->private_data, struct pdb_samba_dsdb_state);
1885 : struct pdb_samba_dsdb_search_state *sstate;
1886 0 : const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1887 : "userAccountControl", "description", NULL };
1888 : struct ldb_result *res;
1889 : int i, rc, num_users;
1890 :
1891 : va_list ap;
1892 0 : char *expression = NULL;
1893 :
1894 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1895 0 : if (!tmp_ctx) {
1896 0 : return false;
1897 : }
1898 :
1899 0 : va_start(ap, exp_fmt);
1900 0 : expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1901 0 : va_end(ap);
1902 :
1903 0 : if (!expression) {
1904 0 : talloc_free(tmp_ctx);
1905 0 : return LDB_ERR_OPERATIONS_ERROR;
1906 : }
1907 :
1908 0 : sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1909 0 : if (sstate == NULL) {
1910 0 : talloc_free(tmp_ctx);
1911 0 : return false;
1912 : }
1913 :
1914 0 : rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1915 0 : if (rc != LDB_SUCCESS) {
1916 0 : talloc_free(tmp_ctx);
1917 0 : DEBUG(10, ("dsdb_search failed: %s\n",
1918 : ldb_errstring(state->ldb)));
1919 0 : return false;
1920 : }
1921 :
1922 0 : num_users = res->count;
1923 :
1924 0 : sstate->entries = talloc_array(sstate, struct samr_displayentry,
1925 : num_users);
1926 0 : if (sstate->entries == NULL) {
1927 0 : talloc_free(tmp_ctx);
1928 0 : DEBUG(10, ("talloc failed\n"));
1929 0 : return false;
1930 : }
1931 :
1932 0 : sstate->num_entries = 0;
1933 :
1934 0 : for (i=0; i<num_users; i++) {
1935 : struct samr_displayentry *e;
1936 : struct dom_sid *sid;
1937 :
1938 0 : e = &sstate->entries[sstate->num_entries];
1939 :
1940 0 : e->idx = sstate->num_entries;
1941 0 : sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1942 0 : if (!sid) {
1943 0 : talloc_free(tmp_ctx);
1944 0 : DEBUG(10, ("Could not pull SID\n"));
1945 0 : return false;
1946 : }
1947 0 : sid_peek_rid(sid, &e->rid);
1948 :
1949 0 : e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1950 0 : e->account_name = ldb_msg_find_attr_as_string(
1951 0 : res->msgs[i], "samAccountName", NULL);
1952 0 : if (e->account_name == NULL) {
1953 0 : talloc_free(tmp_ctx);
1954 0 : return false;
1955 : }
1956 0 : e->fullname = ldb_msg_find_attr_as_string(
1957 0 : res->msgs[i], "displayName", "");
1958 0 : e->description = ldb_msg_find_attr_as_string(
1959 0 : res->msgs[i], "description", "");
1960 :
1961 0 : sstate->num_entries += 1;
1962 0 : if (sstate->num_entries >= num_users) {
1963 0 : break;
1964 : }
1965 : }
1966 0 : talloc_steal(sstate->entries, res->msgs);
1967 0 : search->private_data = talloc_steal(search, sstate);
1968 0 : search->next_entry = pdb_samba_dsdb_next_entry;
1969 0 : search->search_end = pdb_samba_dsdb_search_end;
1970 0 : *pstate = sstate;
1971 0 : talloc_free(tmp_ctx);
1972 0 : return true;
1973 : }
1974 :
1975 0 : static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1976 : struct pdb_search *search,
1977 : uint32_t acct_flags)
1978 : {
1979 : struct pdb_samba_dsdb_search_state *sstate;
1980 : bool ret;
1981 :
1982 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
1983 0 : if (!ret) {
1984 0 : return false;
1985 : }
1986 0 : sstate->acct_flags = acct_flags;
1987 0 : return true;
1988 : }
1989 :
1990 0 : static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
1991 : struct pdb_search *search)
1992 : {
1993 : struct pdb_samba_dsdb_search_state *sstate;
1994 : bool ret;
1995 :
1996 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
1997 : "(&(grouptype=%d)(objectclass=group))",
1998 : GTYPE_SECURITY_GLOBAL_GROUP);
1999 0 : if (!ret) {
2000 0 : return false;
2001 : }
2002 0 : sstate->acct_flags = 0;
2003 0 : return true;
2004 : }
2005 :
2006 0 : static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2007 : struct pdb_search *search,
2008 : const struct dom_sid *sid)
2009 : {
2010 : struct pdb_samba_dsdb_search_state *sstate;
2011 : bool ret;
2012 :
2013 0 : ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2014 : "(&(grouptype=%d)(objectclass=group))",
2015 0 : sid_check_is_builtin(sid)
2016 : ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2017 : : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2018 0 : if (!ret) {
2019 0 : return false;
2020 : }
2021 0 : sstate->acct_flags = 0;
2022 0 : return true;
2023 : }
2024 :
2025 : /*
2026 : * Instead of taking a gid or uid, this function takes a pointer to a
2027 : * unixid.
2028 : *
2029 : * This acts as an in-out variable so that the idmap functions can correctly
2030 : * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2031 : * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID.
2032 : */
2033 70 : static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2034 : struct dom_sid *sid)
2035 : {
2036 70 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2037 : m->private_data, struct pdb_samba_dsdb_state);
2038 : NTSTATUS status;
2039 : struct id_map id_map;
2040 : struct id_map *id_maps[2];
2041 70 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2042 70 : if (!tmp_ctx) {
2043 0 : return false;
2044 : }
2045 :
2046 70 : id_map.xid = *id;
2047 70 : id_maps[0] = &id_map;
2048 70 : id_maps[1] = NULL;
2049 :
2050 70 : status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2051 70 : if (!NT_STATUS_IS_OK(status)) {
2052 0 : talloc_free(tmp_ctx);
2053 0 : return false;
2054 : }
2055 :
2056 70 : if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2057 70 : id->type = id_map.xid.type;
2058 : }
2059 70 : *sid = *id_map.sid;
2060 70 : talloc_free(tmp_ctx);
2061 70 : return true;
2062 : }
2063 :
2064 824 : static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2065 : struct unixid *id)
2066 : {
2067 824 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2068 : m->private_data, struct pdb_samba_dsdb_state);
2069 : struct id_map id_map;
2070 : struct id_map *id_maps[2];
2071 : NTSTATUS status;
2072 824 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2073 824 : if (!tmp_ctx) {
2074 0 : return false;
2075 : }
2076 :
2077 824 : ZERO_STRUCT(id_map);
2078 824 : id_map.sid = discard_const_p(struct dom_sid, sid);
2079 824 : id_maps[0] = &id_map;
2080 824 : id_maps[1] = NULL;
2081 :
2082 824 : status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2083 824 : talloc_free(tmp_ctx);
2084 824 : if (!NT_STATUS_IS_OK(status)) {
2085 0 : return false;
2086 : }
2087 824 : if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2088 824 : *id = id_map.xid;
2089 824 : return true;
2090 : }
2091 0 : return false;
2092 : }
2093 :
2094 5 : static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2095 : {
2096 5 : return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2097 : }
2098 :
2099 0 : static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2100 : {
2101 0 : return false;
2102 : }
2103 :
2104 0 : static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2105 : const char *domain, char** pwd,
2106 : struct dom_sid *sid,
2107 : time_t *pass_last_set_time)
2108 : {
2109 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2110 : m->private_data, struct pdb_samba_dsdb_state);
2111 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2112 0 : const char * const attrs[] = {
2113 : "securityIdentifier",
2114 : "flatName",
2115 : "trustPartner",
2116 : "trustAuthOutgoing",
2117 : "whenCreated",
2118 : "msDS-SupportedEncryptionTypes",
2119 : "trustAttributes",
2120 : "trustDirection",
2121 : "trustType",
2122 : NULL
2123 : };
2124 : struct ldb_message *msg;
2125 : const struct ldb_val *password_val;
2126 : int trust_direction_flags;
2127 : int trust_type;
2128 : int i;
2129 : DATA_BLOB password_utf16;
2130 : struct trustAuthInOutBlob password_blob;
2131 : struct AuthenticationInformationArray *auth_array;
2132 : char *password_talloc;
2133 : size_t password_len;
2134 : enum ndr_err_code ndr_err;
2135 : NTSTATUS status;
2136 0 : const char *netbios_domain = NULL;
2137 0 : const struct dom_sid *domain_sid = NULL;
2138 :
2139 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2140 : attrs, tmp_ctx, &msg);
2141 0 : if (!NT_STATUS_IS_OK(status)) {
2142 : /*
2143 : * This can be called to work out of a domain is
2144 : * trusted, rather than just to get the password
2145 : */
2146 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2147 : "It may not be a trusted domain.\n", domain,
2148 : nt_errstr(status)));
2149 0 : TALLOC_FREE(tmp_ctx);
2150 0 : return false;
2151 : }
2152 :
2153 0 : netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2154 0 : if (netbios_domain == NULL) {
2155 0 : DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2156 : domain));
2157 0 : TALLOC_FREE(tmp_ctx);
2158 0 : return false;
2159 : }
2160 :
2161 0 : domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2162 0 : if (domain_sid == NULL) {
2163 0 : DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2164 : domain));
2165 0 : TALLOC_FREE(tmp_ctx);
2166 0 : return false;
2167 : }
2168 :
2169 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2170 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2171 0 : DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2172 : domain);
2173 0 : TALLOC_FREE(tmp_ctx);
2174 0 : return false;
2175 : }
2176 :
2177 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2178 0 : if (trust_type == LSA_TRUST_TYPE_MIT) {
2179 0 : DBG_WARNING("Trusted domain %s is not an AD trust "
2180 : "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2181 0 : TALLOC_FREE(tmp_ctx);
2182 0 : return false;
2183 : }
2184 :
2185 0 : password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2186 0 : if (password_val == NULL) {
2187 0 : DEBUG(2, ("Failed to get trusted domain password for %s, "
2188 : "attribute trustAuthOutgoing not returned.\n", domain));
2189 0 : TALLOC_FREE(tmp_ctx);
2190 0 : return false;
2191 : }
2192 :
2193 0 : ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2194 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2195 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2196 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2197 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2198 : domain,
2199 : ndr_map_error2string(ndr_err)));
2200 0 : TALLOC_FREE(tmp_ctx);
2201 0 : return false;
2202 : }
2203 :
2204 0 : auth_array = &password_blob.current;
2205 :
2206 0 : for (i=0; i < auth_array->count; i++) {
2207 0 : if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2208 0 : break;
2209 : }
2210 : }
2211 :
2212 0 : if (i == auth_array->count) {
2213 0 : DEBUG(0, ("Trusted domain %s does not have a "
2214 : "clear-text password stored\n",
2215 : domain));
2216 0 : TALLOC_FREE(tmp_ctx);
2217 0 : return false;
2218 : }
2219 :
2220 0 : password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2221 0 : auth_array->array[i].AuthInfo.clear.size);
2222 :
2223 : /*
2224 : * In the future, make this function return a
2225 : * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2226 : * but for now convert to UTF8 and fail if the string can not be converted.
2227 : *
2228 : * We can't safely convert the random strings windows uses into
2229 : * utf8.
2230 : */
2231 0 : if (!convert_string_talloc(tmp_ctx,
2232 : CH_UTF16MUNGED, CH_UTF8,
2233 0 : password_utf16.data, password_utf16.length,
2234 : (void *)&password_talloc,
2235 : &password_len)) {
2236 0 : DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2237 : " to UTF8. This may be a password set from Windows.\n",
2238 : domain));
2239 0 : TALLOC_FREE(tmp_ctx);
2240 0 : return false;
2241 : }
2242 0 : *pwd = SMB_STRNDUP(password_talloc, password_len);
2243 0 : if (pass_last_set_time) {
2244 0 : *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2245 : }
2246 :
2247 0 : if (sid != NULL) {
2248 0 : sid_copy(sid, domain_sid);
2249 : }
2250 :
2251 0 : TALLOC_FREE(tmp_ctx);
2252 0 : return true;
2253 : }
2254 :
2255 0 : static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2256 : const char *domain,
2257 : TALLOC_CTX *mem_ctx,
2258 : struct cli_credentials **_creds)
2259 : {
2260 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2261 : m->private_data, struct pdb_samba_dsdb_state);
2262 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2263 0 : const char * const attrs[] = {
2264 : "securityIdentifier",
2265 : "flatName",
2266 : "trustPartner",
2267 : "trustAuthOutgoing",
2268 : "whenCreated",
2269 : "msDS-SupportedEncryptionTypes",
2270 : "trustAttributes",
2271 : "trustDirection",
2272 : "trustType",
2273 : NULL
2274 : };
2275 : struct ldb_message *msg;
2276 : const struct ldb_val *password_val;
2277 : int trust_direction_flags;
2278 : int trust_type;
2279 : int i;
2280 0 : DATA_BLOB password_utf16 = {};
2281 0 : struct samr_Password *password_nt = NULL;
2282 0 : uint32_t password_version = 0;
2283 0 : DATA_BLOB old_password_utf16 = {};
2284 0 : struct samr_Password *old_password_nt = NULL;
2285 : struct trustAuthInOutBlob password_blob;
2286 : enum ndr_err_code ndr_err;
2287 : NTSTATUS status;
2288 0 : time_t last_set_time = 0;
2289 0 : struct cli_credentials *creds = NULL;
2290 : bool ok;
2291 0 : const char *my_netbios_name = NULL;
2292 0 : const char *my_netbios_domain = NULL;
2293 0 : const char *my_dns_domain = NULL;
2294 0 : const char *netbios_domain = NULL;
2295 0 : char *account_name = NULL;
2296 0 : char *principal_name = NULL;
2297 0 : const char *dns_domain = NULL;
2298 :
2299 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2300 : attrs, tmp_ctx, &msg);
2301 0 : if (!NT_STATUS_IS_OK(status)) {
2302 : /*
2303 : * This can be called to work out of a domain is
2304 : * trusted, rather than just to get the password
2305 : */
2306 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2307 : "It may not be a trusted domain.\n", domain,
2308 : nt_errstr(status)));
2309 0 : TALLOC_FREE(tmp_ctx);
2310 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2311 : }
2312 :
2313 0 : netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2314 0 : if (netbios_domain == NULL) {
2315 0 : DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2316 : domain));
2317 0 : TALLOC_FREE(tmp_ctx);
2318 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2319 : }
2320 :
2321 0 : dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2322 :
2323 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2324 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2325 0 : DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2326 : domain);
2327 0 : TALLOC_FREE(tmp_ctx);
2328 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2329 : }
2330 :
2331 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2332 0 : if (trust_type == LSA_TRUST_TYPE_MIT) {
2333 0 : DBG_WARNING("Trusted domain %s is not an AD trust "
2334 : "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2335 0 : TALLOC_FREE(tmp_ctx);
2336 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2337 : }
2338 :
2339 0 : password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2340 0 : if (password_val == NULL) {
2341 0 : DEBUG(2, ("Failed to get trusted domain password for %s, "
2342 : "attribute trustAuthOutgoing not returned.\n", domain));
2343 0 : TALLOC_FREE(tmp_ctx);
2344 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2345 : }
2346 :
2347 0 : ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2348 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2349 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2350 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2351 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2352 : domain,
2353 : ndr_map_error2string(ndr_err)));
2354 0 : TALLOC_FREE(tmp_ctx);
2355 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2356 : }
2357 :
2358 0 : for (i=0; i < password_blob.current.count; i++) {
2359 0 : struct AuthenticationInformation *a =
2360 0 : &password_blob.current.array[i];
2361 :
2362 0 : switch (a->AuthType) {
2363 0 : case TRUST_AUTH_TYPE_NONE:
2364 0 : break;
2365 :
2366 0 : case TRUST_AUTH_TYPE_VERSION:
2367 0 : password_version = a->AuthInfo.version.version;
2368 0 : break;
2369 :
2370 0 : case TRUST_AUTH_TYPE_CLEAR:
2371 0 : last_set_time = nt_time_to_unix(a->LastUpdateTime);
2372 :
2373 0 : password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2374 0 : a->AuthInfo.clear.size);
2375 0 : password_nt = NULL;
2376 0 : break;
2377 :
2378 0 : case TRUST_AUTH_TYPE_NT4OWF:
2379 0 : if (password_utf16.length != 0) {
2380 0 : break;
2381 : }
2382 :
2383 0 : last_set_time = nt_time_to_unix(a->LastUpdateTime);
2384 :
2385 0 : password_nt = &a->AuthInfo.nt4owf.password;
2386 0 : break;
2387 : }
2388 : }
2389 :
2390 0 : for (i=0; i < password_blob.previous.count; i++) {
2391 0 : struct AuthenticationInformation *a = &password_blob.previous.array[i];
2392 :
2393 0 : switch (a->AuthType) {
2394 0 : case TRUST_AUTH_TYPE_NONE:
2395 0 : break;
2396 :
2397 0 : case TRUST_AUTH_TYPE_VERSION:
2398 0 : break;
2399 :
2400 0 : case TRUST_AUTH_TYPE_CLEAR:
2401 0 : old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2402 0 : a->AuthInfo.clear.size);
2403 0 : old_password_nt = NULL;
2404 0 : break;
2405 :
2406 0 : case TRUST_AUTH_TYPE_NT4OWF:
2407 0 : if (old_password_utf16.length != 0) {
2408 0 : break;
2409 : }
2410 :
2411 0 : old_password_nt = &a->AuthInfo.nt4owf.password;
2412 0 : break;
2413 : }
2414 : }
2415 :
2416 0 : if (password_utf16.length == 0 && password_nt == NULL) {
2417 0 : DEBUG(0, ("Trusted domain %s does not have a "
2418 : "clear-text nor nt password stored\n",
2419 : domain));
2420 0 : TALLOC_FREE(tmp_ctx);
2421 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2422 : }
2423 :
2424 0 : my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2425 0 : my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2426 0 : my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2427 :
2428 0 : creds = cli_credentials_init(tmp_ctx);
2429 0 : if (creds == NULL) {
2430 0 : TALLOC_FREE(tmp_ctx);
2431 0 : return NT_STATUS_NO_MEMORY;
2432 : }
2433 :
2434 0 : ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2435 0 : if (!ok) {
2436 0 : TALLOC_FREE(tmp_ctx);
2437 0 : return NT_STATUS_NO_MEMORY;
2438 : }
2439 :
2440 0 : ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2441 0 : if (!ok) {
2442 0 : TALLOC_FREE(tmp_ctx);
2443 0 : return NT_STATUS_NO_MEMORY;
2444 : }
2445 0 : ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2446 0 : if (!ok) {
2447 0 : TALLOC_FREE(tmp_ctx);
2448 0 : return NT_STATUS_NO_MEMORY;
2449 : }
2450 :
2451 0 : if (my_dns_domain != NULL && dns_domain != NULL) {
2452 0 : cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2453 0 : account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2454 0 : if (account_name == NULL) {
2455 0 : TALLOC_FREE(tmp_ctx);
2456 0 : return NT_STATUS_NO_MEMORY;
2457 : }
2458 0 : principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2459 : cli_credentials_get_realm(creds));
2460 0 : if (principal_name == NULL) {
2461 0 : TALLOC_FREE(tmp_ctx);
2462 0 : return NT_STATUS_NO_MEMORY;
2463 : }
2464 : } else {
2465 0 : cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2466 0 : account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2467 0 : if (account_name == NULL) {
2468 0 : TALLOC_FREE(tmp_ctx);
2469 0 : return NT_STATUS_NO_MEMORY;
2470 : }
2471 0 : principal_name = NULL;
2472 : }
2473 :
2474 0 : ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2475 0 : if (!ok) {
2476 0 : TALLOC_FREE(tmp_ctx);
2477 0 : return NT_STATUS_NO_MEMORY;
2478 : }
2479 :
2480 0 : if (principal_name != NULL) {
2481 0 : ok = cli_credentials_set_principal(creds, principal_name,
2482 : CRED_SPECIFIED);
2483 0 : if (!ok) {
2484 0 : TALLOC_FREE(tmp_ctx);
2485 0 : return NT_STATUS_NO_MEMORY;
2486 : }
2487 : }
2488 :
2489 0 : if (old_password_nt != NULL) {
2490 0 : ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2491 0 : if (!ok) {
2492 0 : TALLOC_FREE(tmp_ctx);
2493 0 : return NT_STATUS_NO_MEMORY;
2494 : }
2495 : }
2496 :
2497 0 : if (old_password_utf16.length > 0) {
2498 0 : ok = cli_credentials_set_old_utf16_password(creds,
2499 : &old_password_utf16);
2500 0 : if (!ok) {
2501 0 : TALLOC_FREE(tmp_ctx);
2502 0 : return NT_STATUS_NO_MEMORY;
2503 : }
2504 : }
2505 :
2506 0 : if (password_nt != NULL) {
2507 0 : ok = cli_credentials_set_nt_hash(creds, password_nt,
2508 : CRED_SPECIFIED);
2509 0 : if (!ok) {
2510 0 : TALLOC_FREE(tmp_ctx);
2511 0 : return NT_STATUS_NO_MEMORY;
2512 : }
2513 : }
2514 :
2515 0 : if (password_utf16.length > 0) {
2516 0 : ok = cli_credentials_set_utf16_password(creds,
2517 : &password_utf16,
2518 : CRED_SPECIFIED);
2519 0 : if (!ok) {
2520 0 : TALLOC_FREE(tmp_ctx);
2521 0 : return NT_STATUS_NO_MEMORY;
2522 : }
2523 : }
2524 :
2525 0 : cli_credentials_set_password_last_changed_time(creds, last_set_time);
2526 0 : cli_credentials_set_kvno(creds, password_version);
2527 :
2528 0 : if (password_utf16.length > 0 && dns_domain != NULL) {
2529 : /*
2530 : * Force kerberos if this is an active directory domain
2531 : */
2532 0 : cli_credentials_set_kerberos_state(creds,
2533 : CRED_USE_KERBEROS_REQUIRED,
2534 : CRED_SPECIFIED);
2535 : } else {
2536 : /*
2537 : * TODO: we should allow krb5 with the raw nt hash.
2538 : */
2539 0 : cli_credentials_set_kerberos_state(creds,
2540 : CRED_USE_KERBEROS_DISABLED,
2541 : CRED_SPECIFIED);
2542 : }
2543 :
2544 0 : *_creds = talloc_move(mem_ctx, &creds);
2545 0 : TALLOC_FREE(tmp_ctx);
2546 0 : return NT_STATUS_OK;
2547 : }
2548 :
2549 0 : static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2550 : const char* domain, const char* pwd,
2551 : const struct dom_sid *sid)
2552 : {
2553 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2554 : m->private_data, struct pdb_samba_dsdb_state);
2555 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2556 0 : const char * const attrs[] = {
2557 : "trustAuthOutgoing",
2558 : "trustDirection",
2559 : "trustType",
2560 : NULL
2561 : };
2562 0 : struct ldb_message *msg = NULL;
2563 : int trust_direction_flags;
2564 : int trust_type;
2565 : uint32_t i; /* The same type as old_blob.current.count */
2566 0 : const struct ldb_val *old_val = NULL;
2567 0 : struct trustAuthInOutBlob old_blob = {};
2568 0 : uint32_t old_version = 0;
2569 0 : uint32_t new_version = 0;
2570 0 : DATA_BLOB new_utf16 = {};
2571 0 : struct trustAuthInOutBlob new_blob = {};
2572 0 : struct ldb_val new_val = {};
2573 0 : struct timeval tv = timeval_current();
2574 0 : NTTIME now = timeval_to_nttime(&tv);
2575 : enum ndr_err_code ndr_err;
2576 : NTSTATUS status;
2577 : bool ok;
2578 : int ret;
2579 :
2580 0 : ret = ldb_transaction_start(state->ldb);
2581 0 : if (ret != LDB_SUCCESS) {
2582 0 : DEBUG(2, ("Failed to start transaction.\n"));
2583 0 : TALLOC_FREE(tmp_ctx);
2584 0 : return false;
2585 : }
2586 :
2587 0 : ok = samdb_is_pdc(state->ldb);
2588 0 : if (!ok) {
2589 0 : DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2590 : domain));
2591 0 : TALLOC_FREE(tmp_ctx);
2592 0 : ldb_transaction_cancel(state->ldb);
2593 0 : return false;
2594 : }
2595 :
2596 0 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2597 : attrs, tmp_ctx, &msg);
2598 0 : if (!NT_STATUS_IS_OK(status)) {
2599 : /*
2600 : * This can be called to work out of a domain is
2601 : * trusted, rather than just to get the password
2602 : */
2603 0 : DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2604 : "It may not be a trusted domain.\n", domain,
2605 : nt_errstr(status)));
2606 0 : TALLOC_FREE(tmp_ctx);
2607 0 : ldb_transaction_cancel(state->ldb);
2608 0 : return false;
2609 : }
2610 :
2611 0 : trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2612 0 : if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2613 0 : DBG_WARNING("Trusted domain %s is not an outbound trust, can't set a password.\n",
2614 : domain);
2615 0 : TALLOC_FREE(tmp_ctx);
2616 0 : ldb_transaction_cancel(state->ldb);
2617 0 : return false;
2618 : }
2619 :
2620 0 : trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2621 0 : switch (trust_type) {
2622 0 : case LSA_TRUST_TYPE_DOWNLEVEL:
2623 : case LSA_TRUST_TYPE_UPLEVEL:
2624 0 : break;
2625 0 : default:
2626 0 : DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2627 : "password changes are not supported\n",
2628 : domain, (unsigned)trust_type));
2629 0 : TALLOC_FREE(tmp_ctx);
2630 0 : ldb_transaction_cancel(state->ldb);
2631 0 : return false;
2632 : }
2633 :
2634 0 : old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2635 0 : if (old_val != NULL) {
2636 0 : ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2637 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2638 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2639 0 : DEBUG(0, ("Failed to get trusted domain password for %s, "
2640 : "attribute trustAuthOutgoing could not be parsed %s.\n",
2641 : domain,
2642 : ndr_map_error2string(ndr_err)));
2643 0 : TALLOC_FREE(tmp_ctx);
2644 0 : ldb_transaction_cancel(state->ldb);
2645 0 : return false;
2646 : }
2647 : }
2648 :
2649 0 : for (i=0; i < old_blob.current.count; i++) {
2650 0 : struct AuthenticationInformation *a =
2651 0 : &old_blob.current.array[i];
2652 :
2653 0 : switch (a->AuthType) {
2654 0 : case TRUST_AUTH_TYPE_NONE:
2655 0 : break;
2656 :
2657 0 : case TRUST_AUTH_TYPE_VERSION:
2658 0 : old_version = a->AuthInfo.version.version;
2659 0 : break;
2660 :
2661 0 : case TRUST_AUTH_TYPE_CLEAR:
2662 0 : break;
2663 :
2664 0 : case TRUST_AUTH_TYPE_NT4OWF:
2665 0 : break;
2666 : }
2667 : }
2668 :
2669 0 : new_version = old_version + 1;
2670 0 : ok = convert_string_talloc(tmp_ctx,
2671 : CH_UNIX, CH_UTF16,
2672 : pwd, strlen(pwd),
2673 : (void *)&new_utf16.data,
2674 : &new_utf16.length);
2675 0 : if (!ok) {
2676 0 : DEBUG(0, ("Failed to generate new_utf16 password for domain %s\n",
2677 : domain));
2678 0 : TALLOC_FREE(tmp_ctx);
2679 0 : ldb_transaction_cancel(state->ldb);
2680 0 : return false;
2681 : }
2682 :
2683 0 : if (new_utf16.length < 28) {
2684 0 : DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2685 : new_utf16.length,
2686 : (unsigned)new_version,
2687 : domain));
2688 0 : TALLOC_FREE(tmp_ctx);
2689 0 : ldb_transaction_cancel(state->ldb);
2690 0 : return false;
2691 : }
2692 0 : if (new_utf16.length > 498) {
2693 0 : DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2694 : new_utf16.length,
2695 : (unsigned)new_version,
2696 : domain));
2697 0 : TALLOC_FREE(tmp_ctx);
2698 0 : ldb_transaction_cancel(state->ldb);
2699 0 : return false;
2700 : }
2701 :
2702 0 : new_blob.count = MAX(old_blob.current.count, 2);
2703 0 : new_blob.current.array = talloc_zero_array(tmp_ctx,
2704 : struct AuthenticationInformation,
2705 : new_blob.count);
2706 0 : if (new_blob.current.array == NULL) {
2707 0 : DEBUG(0, ("talloc_zero_array(%u) failed\n",
2708 : (unsigned)new_blob.count));
2709 0 : TALLOC_FREE(tmp_ctx);
2710 0 : ldb_transaction_cancel(state->ldb);
2711 0 : return false;
2712 : }
2713 0 : new_blob.previous.array = talloc_zero_array(tmp_ctx,
2714 : struct AuthenticationInformation,
2715 : new_blob.count);
2716 0 : if (new_blob.current.array == NULL) {
2717 0 : DEBUG(0, ("talloc_zero_array(%u) failed\n",
2718 : (unsigned)new_blob.count));
2719 0 : TALLOC_FREE(tmp_ctx);
2720 0 : ldb_transaction_cancel(state->ldb);
2721 0 : return false;
2722 : }
2723 :
2724 0 : for (i = 0; i < old_blob.current.count; i++) {
2725 0 : struct AuthenticationInformation *o =
2726 0 : &old_blob.current.array[i];
2727 0 : struct AuthenticationInformation *p =
2728 0 : &new_blob.previous.array[i];
2729 :
2730 0 : *p = *o;
2731 0 : new_blob.previous.count++;
2732 : }
2733 0 : for (; i < new_blob.count; i++) {
2734 0 : struct AuthenticationInformation *pi =
2735 0 : &new_blob.previous.array[i];
2736 :
2737 0 : if (i == 0) {
2738 : /*
2739 : * new_blob.previous is still empty so
2740 : * we'll do new_blob.previous = new_blob.current
2741 : * below.
2742 : */
2743 0 : break;
2744 : }
2745 :
2746 0 : pi->LastUpdateTime = now;
2747 0 : pi->AuthType = TRUST_AUTH_TYPE_NONE;
2748 0 : new_blob.previous.count++;
2749 : }
2750 :
2751 0 : for (i = 0; i < new_blob.count; i++) {
2752 0 : struct AuthenticationInformation *ci =
2753 0 : &new_blob.current.array[i];
2754 :
2755 0 : ci->LastUpdateTime = now;
2756 0 : switch (i) {
2757 0 : case 0:
2758 0 : ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2759 0 : ci->AuthInfo.clear.size = new_utf16.length;
2760 0 : ci->AuthInfo.clear.password = new_utf16.data;
2761 0 : break;
2762 0 : case 1:
2763 0 : ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2764 0 : ci->AuthInfo.version.version = new_version;
2765 0 : break;
2766 0 : default:
2767 0 : ci->AuthType = TRUST_AUTH_TYPE_NONE;
2768 0 : break;
2769 : }
2770 :
2771 0 : new_blob.current.count++;
2772 : }
2773 :
2774 0 : if (new_blob.previous.count == 0) {
2775 0 : TALLOC_FREE(new_blob.previous.array);
2776 0 : new_blob.previous = new_blob.current;
2777 : }
2778 :
2779 0 : ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2780 : (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2781 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2782 0 : DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2783 : "trusted domain password for %s: %s.\n",
2784 : domain, ndr_map_error2string(ndr_err)));
2785 0 : TALLOC_FREE(tmp_ctx);
2786 0 : ldb_transaction_cancel(state->ldb);
2787 0 : return false;
2788 : }
2789 :
2790 0 : msg->num_elements = 0;
2791 0 : ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2792 : &new_val, LDB_FLAG_MOD_REPLACE);
2793 0 : if (ret != LDB_SUCCESS) {
2794 0 : DEBUG(0, ("ldb_msg_append_value() failed\n"));
2795 0 : TALLOC_FREE(tmp_ctx);
2796 0 : ldb_transaction_cancel(state->ldb);
2797 0 : return false;
2798 : }
2799 :
2800 0 : ret = ldb_modify(state->ldb, msg);
2801 0 : if (ret != LDB_SUCCESS) {
2802 0 : DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2803 : "trusted domain password for %s: %s - %s\n",
2804 : domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2805 0 : TALLOC_FREE(tmp_ctx);
2806 0 : ldb_transaction_cancel(state->ldb);
2807 0 : return false;
2808 : }
2809 :
2810 0 : ret = ldb_transaction_commit(state->ldb);
2811 0 : if (ret != LDB_SUCCESS) {
2812 0 : DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2813 : "trusted domain password for %s: %s - %s\n",
2814 : domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2815 0 : TALLOC_FREE(tmp_ctx);
2816 0 : return false;
2817 : }
2818 :
2819 0 : DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2820 : "trusted domain password for %s.\n",
2821 : (unsigned)new_version, domain));
2822 0 : TALLOC_FREE(tmp_ctx);
2823 0 : return true;
2824 : }
2825 :
2826 0 : static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2827 : const char *domain)
2828 : {
2829 0 : return false;
2830 : }
2831 :
2832 0 : static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2833 : TALLOC_CTX *mem_ctx,
2834 : uint32_t *_num_domains,
2835 : struct trustdom_info ***_domains)
2836 : {
2837 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2838 : m->private_data, struct pdb_samba_dsdb_state);
2839 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2840 0 : const char * const attrs[] = {
2841 : "securityIdentifier",
2842 : "flatName",
2843 : "trustDirection",
2844 : NULL
2845 : };
2846 0 : struct ldb_result *res = NULL;
2847 : unsigned int i;
2848 0 : struct trustdom_info **domains = NULL;
2849 : NTSTATUS status;
2850 0 : uint32_t di = 0;
2851 :
2852 0 : *_num_domains = 0;
2853 0 : *_domains = NULL;
2854 :
2855 0 : status = dsdb_trust_search_tdos(state->ldb, NULL,
2856 : attrs, tmp_ctx, &res);
2857 0 : if (!NT_STATUS_IS_OK(status)) {
2858 0 : DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
2859 0 : TALLOC_FREE(tmp_ctx);
2860 0 : return status;
2861 : }
2862 :
2863 0 : if (res->count == 0) {
2864 0 : TALLOC_FREE(tmp_ctx);
2865 0 : return NT_STATUS_OK;
2866 : }
2867 :
2868 0 : domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2869 : res->count);
2870 0 : if (domains == NULL) {
2871 0 : TALLOC_FREE(tmp_ctx);
2872 0 : return NT_STATUS_NO_MEMORY;
2873 : }
2874 :
2875 0 : for (i = 0; i < res->count; i++) {
2876 0 : struct ldb_message *msg = res->msgs[i];
2877 0 : struct trustdom_info *d = NULL;
2878 0 : const char *name = NULL;
2879 0 : struct dom_sid *sid = NULL;
2880 : uint32_t direction;
2881 :
2882 0 : d = talloc_zero(domains, struct trustdom_info);
2883 0 : if (d == NULL) {
2884 0 : TALLOC_FREE(tmp_ctx);
2885 0 : return NT_STATUS_NO_MEMORY;
2886 : }
2887 :
2888 0 : name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2889 0 : if (name == NULL) {
2890 0 : TALLOC_FREE(tmp_ctx);
2891 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2892 : }
2893 0 : sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2894 0 : if (sid == NULL) {
2895 0 : continue;
2896 : }
2897 :
2898 0 : direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2899 0 : if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2900 0 : continue;
2901 : }
2902 :
2903 0 : d->name = talloc_strdup(d, name);
2904 0 : if (d->name == NULL) {
2905 0 : TALLOC_FREE(tmp_ctx);
2906 0 : return NT_STATUS_NO_MEMORY;
2907 : }
2908 0 : d->sid = *sid;
2909 :
2910 0 : domains[di++] = d;
2911 : }
2912 :
2913 0 : domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2914 0 : *_domains = talloc_move(mem_ctx, &domains);
2915 0 : *_num_domains = di;
2916 0 : TALLOC_FREE(tmp_ctx);
2917 0 : return NT_STATUS_OK;
2918 : }
2919 :
2920 2 : static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2921 : TALLOC_CTX *mem_ctx,
2922 : struct pdb_trusted_domain **_d)
2923 : {
2924 2 : struct pdb_trusted_domain *d = NULL;
2925 2 : const char *str = NULL;
2926 2 : struct dom_sid *sid = NULL;
2927 2 : const struct ldb_val *val = NULL;
2928 : uint64_t val64;
2929 :
2930 2 : *_d = NULL;
2931 :
2932 2 : d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
2933 2 : if (d == NULL) {
2934 0 : return NT_STATUS_NO_MEMORY;
2935 : }
2936 :
2937 2 : str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2938 2 : if (str == NULL) {
2939 0 : TALLOC_FREE(d);
2940 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2941 : }
2942 2 : d->netbios_name = talloc_strdup(d, str);
2943 2 : if (d->netbios_name == NULL) {
2944 0 : TALLOC_FREE(d);
2945 0 : return NT_STATUS_NO_MEMORY;
2946 : }
2947 :
2948 2 : str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2949 2 : if (str != NULL) {
2950 2 : d->domain_name = talloc_strdup(d, str);
2951 2 : if (d->domain_name == NULL) {
2952 0 : TALLOC_FREE(d);
2953 0 : return NT_STATUS_NO_MEMORY;
2954 : }
2955 : }
2956 :
2957 2 : sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
2958 2 : if (sid != NULL) {
2959 2 : d->security_identifier = *sid;
2960 2 : TALLOC_FREE(sid);
2961 : }
2962 :
2963 2 : val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2964 2 : if (val != NULL) {
2965 2 : d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
2966 2 : if (d->trust_auth_outgoing.data == NULL) {
2967 0 : TALLOC_FREE(d);
2968 0 : return NT_STATUS_NO_MEMORY;
2969 : }
2970 : }
2971 2 : val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2972 2 : if (val != NULL) {
2973 0 : d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
2974 0 : if (d->trust_auth_incoming.data == NULL) {
2975 0 : TALLOC_FREE(d);
2976 0 : return NT_STATUS_NO_MEMORY;
2977 : }
2978 : }
2979 :
2980 2 : d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2981 2 : d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
2982 2 : d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
2983 :
2984 2 : val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
2985 2 : if (val64 != UINT64_MAX) {
2986 0 : d->trust_posix_offset = talloc(d, uint32_t);
2987 0 : if (d->trust_posix_offset == NULL) {
2988 0 : TALLOC_FREE(d);
2989 0 : return NT_STATUS_NO_MEMORY;
2990 : }
2991 0 : *d->trust_posix_offset = (uint32_t)val64;
2992 : }
2993 :
2994 2 : val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
2995 2 : if (val64 != UINT64_MAX) {
2996 0 : d->supported_enc_type = talloc(d, uint32_t);
2997 0 : if (d->supported_enc_type == NULL) {
2998 0 : TALLOC_FREE(d);
2999 0 : return NT_STATUS_NO_MEMORY;
3000 : }
3001 0 : *d->supported_enc_type = (uint32_t)val64;
3002 : }
3003 :
3004 2 : val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3005 2 : if (val != NULL) {
3006 0 : d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3007 0 : if (d->trust_forest_trust_info.data == NULL) {
3008 0 : TALLOC_FREE(d);
3009 0 : return NT_STATUS_NO_MEMORY;
3010 : }
3011 : }
3012 :
3013 2 : *_d = d;
3014 2 : return NT_STATUS_OK;
3015 : }
3016 :
3017 2 : static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3018 : TALLOC_CTX *mem_ctx,
3019 : const char *domain,
3020 : struct pdb_trusted_domain **td)
3021 : {
3022 2 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3023 : m->private_data, struct pdb_samba_dsdb_state);
3024 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3025 2 : const char * const attrs[] = {
3026 : "securityIdentifier",
3027 : "flatName",
3028 : "trustPartner",
3029 : "trustAuthOutgoing",
3030 : "trustAuthIncoming",
3031 : "trustAttributes",
3032 : "trustDirection",
3033 : "trustType",
3034 : "trustPosixOffset",
3035 : "msDS-SupportedEncryptionTypes",
3036 : "msDS-TrustForestTrustInfo",
3037 : NULL
3038 : };
3039 2 : struct ldb_message *msg = NULL;
3040 2 : struct pdb_trusted_domain *d = NULL;
3041 : NTSTATUS status;
3042 :
3043 2 : status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3044 : attrs, tmp_ctx, &msg);
3045 2 : if (!NT_STATUS_IS_OK(status)) {
3046 0 : DBG_ERR("dsdb_trust_search_tdo(%s) - %s ",
3047 : domain, nt_errstr(status));
3048 0 : TALLOC_FREE(tmp_ctx);
3049 0 : return status;
3050 : }
3051 :
3052 2 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3053 2 : if (!NT_STATUS_IS_OK(status)) {
3054 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3055 : domain, nt_errstr(status));
3056 0 : TALLOC_FREE(tmp_ctx);
3057 0 : return status;
3058 : }
3059 :
3060 2 : *td = d;
3061 2 : TALLOC_FREE(tmp_ctx);
3062 2 : return NT_STATUS_OK;
3063 : }
3064 :
3065 0 : static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3066 : TALLOC_CTX *mem_ctx,
3067 : struct dom_sid *sid,
3068 : struct pdb_trusted_domain **td)
3069 : {
3070 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3071 : m->private_data, struct pdb_samba_dsdb_state);
3072 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3073 0 : const char * const attrs[] = {
3074 : "securityIdentifier",
3075 : "flatName",
3076 : "trustPartner",
3077 : "trustAuthOutgoing",
3078 : "trustAuthIncoming",
3079 : "trustAttributes",
3080 : "trustDirection",
3081 : "trustType",
3082 : "trustPosixOffset",
3083 : "msDS-SupportedEncryptionTypes",
3084 : "msDS-TrustForestTrustInfo",
3085 : NULL
3086 : };
3087 0 : struct ldb_message *msg = NULL;
3088 0 : struct pdb_trusted_domain *d = NULL;
3089 : struct dom_sid_buf buf;
3090 : NTSTATUS status;
3091 :
3092 0 : status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3093 : attrs, tmp_ctx, &msg);
3094 0 : if (!NT_STATUS_IS_OK(status)) {
3095 0 : DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s ",
3096 : dom_sid_str_buf(sid, &buf),
3097 : nt_errstr(status));
3098 0 : TALLOC_FREE(tmp_ctx);
3099 0 : return status;
3100 : }
3101 :
3102 0 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3103 0 : if (!NT_STATUS_IS_OK(status)) {
3104 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3105 : dom_sid_str_buf(sid, &buf),
3106 : nt_errstr(status));
3107 0 : TALLOC_FREE(tmp_ctx);
3108 0 : return status;
3109 : }
3110 :
3111 0 : *td = d;
3112 0 : TALLOC_FREE(tmp_ctx);
3113 0 : return NT_STATUS_OK;
3114 : }
3115 :
3116 0 : static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3117 : struct ldb_context *sam_ldb,
3118 : struct ldb_dn *base_dn,
3119 : const char *netbios_name,
3120 : struct trustAuthInOutBlob *taiob)
3121 : {
3122 0 : struct ldb_request *req = NULL;
3123 0 : struct ldb_message *msg = NULL;
3124 0 : struct ldb_dn *dn = NULL;
3125 : uint32_t i;
3126 : int ret;
3127 : bool ok;
3128 :
3129 0 : dn = ldb_dn_copy(mem_ctx, base_dn);
3130 0 : if (dn == NULL) {
3131 0 : return NT_STATUS_NO_MEMORY;
3132 : }
3133 0 : ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3134 0 : if (!ok) {
3135 0 : return NT_STATUS_NO_MEMORY;
3136 : }
3137 :
3138 0 : msg = ldb_msg_new(mem_ctx);
3139 0 : if (msg == NULL) {
3140 0 : return NT_STATUS_NO_MEMORY;
3141 : }
3142 0 : msg->dn = dn;
3143 :
3144 0 : ret = ldb_msg_add_string(msg, "objectClass", "user");
3145 0 : if (ret != LDB_SUCCESS) {
3146 0 : return NT_STATUS_NO_MEMORY;
3147 : }
3148 :
3149 0 : ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3150 0 : if (ret != LDB_SUCCESS) {
3151 0 : return NT_STATUS_NO_MEMORY;
3152 : }
3153 :
3154 0 : ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3155 : UF_INTERDOMAIN_TRUST_ACCOUNT);
3156 0 : if (ret != LDB_SUCCESS) {
3157 0 : return NT_STATUS_NO_MEMORY;
3158 : }
3159 :
3160 0 : for (i = 0; i < taiob->count; i++) {
3161 0 : struct AuthenticationInformation *auth_info =
3162 0 : &taiob->current.array[i];
3163 0 : const char *attribute = NULL;
3164 : struct ldb_val v;
3165 :
3166 0 : switch (taiob->current.array[i].AuthType) {
3167 0 : case TRUST_AUTH_TYPE_NT4OWF:
3168 0 : attribute = "unicodePwd";
3169 0 : v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3170 0 : v.length = 16;
3171 0 : break;
3172 :
3173 0 : case TRUST_AUTH_TYPE_CLEAR:
3174 0 : attribute = "clearTextPassword";
3175 0 : v.data = auth_info->AuthInfo.clear.password;
3176 0 : v.length = auth_info->AuthInfo.clear.size;
3177 0 : break;
3178 :
3179 0 : default:
3180 0 : continue;
3181 : }
3182 :
3183 0 : ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3184 0 : if (ret != LDB_SUCCESS) {
3185 0 : return NT_STATUS_NO_MEMORY;
3186 : }
3187 : }
3188 :
3189 : /* create the trusted_domain user account */
3190 0 : ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3191 : ldb_op_default_callback, NULL);
3192 0 : if (ret != LDB_SUCCESS) {
3193 0 : return NT_STATUS_NO_MEMORY;
3194 : }
3195 :
3196 0 : ret = ldb_request_add_control(
3197 : req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3198 : false, NULL);
3199 0 : if (ret != LDB_SUCCESS) {
3200 0 : return NT_STATUS_NO_MEMORY;
3201 : }
3202 :
3203 0 : ret = dsdb_autotransaction_request(sam_ldb, req);
3204 0 : if (ret != LDB_SUCCESS) {
3205 0 : DEBUG(0,("Failed to create user record %s: %s\n",
3206 : ldb_dn_get_linearized(msg->dn),
3207 : ldb_errstring(sam_ldb)));
3208 :
3209 0 : switch (ret) {
3210 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
3211 0 : return NT_STATUS_DOMAIN_EXISTS;
3212 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3213 0 : return NT_STATUS_ACCESS_DENIED;
3214 0 : default:
3215 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3216 : }
3217 : }
3218 :
3219 0 : return NT_STATUS_OK;
3220 : }
3221 :
3222 1 : static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3223 : const char* domain,
3224 : const struct pdb_trusted_domain *td)
3225 : {
3226 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3227 : methods->private_data, struct pdb_samba_dsdb_state);
3228 1 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3229 1 : bool in_txn = false;
3230 1 : struct ldb_dn *base_dn = NULL;
3231 1 : struct ldb_message *msg = NULL;
3232 1 : const char *attrs[] = {
3233 : NULL
3234 : };
3235 1 : char *netbios_encoded = NULL;
3236 1 : char *dns_encoded = NULL;
3237 1 : char *sid_encoded = NULL;
3238 : int ret;
3239 : struct trustAuthInOutBlob taiob;
3240 : enum ndr_err_code ndr_err;
3241 : NTSTATUS status;
3242 : bool ok;
3243 :
3244 1 : base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3245 1 : if (base_dn == NULL) {
3246 0 : TALLOC_FREE(tmp_ctx);
3247 0 : status = NT_STATUS_NO_MEMORY;
3248 0 : goto out;
3249 : }
3250 : /*
3251 : * We expect S-1-5-21-A-B-C, but we don't
3252 : * allow S-1-5-21-0-0-0 as this is used
3253 : * for claims and compound identities.
3254 : */
3255 1 : ok = dom_sid_is_valid_account_domain(&td->security_identifier);
3256 1 : if (!ok) {
3257 0 : status = NT_STATUS_INVALID_PARAMETER;
3258 0 : goto out;
3259 : }
3260 :
3261 1 : if (strequal(td->netbios_name, "BUILTIN")) {
3262 0 : status = NT_STATUS_INVALID_PARAMETER;
3263 0 : goto out;
3264 : }
3265 1 : if (strequal(td->domain_name, "BUILTIN")) {
3266 0 : status = NT_STATUS_INVALID_PARAMETER;
3267 0 : goto out;
3268 : }
3269 :
3270 1 : dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3271 1 : if (dns_encoded == NULL) {
3272 0 : status = NT_STATUS_NO_MEMORY;
3273 0 : goto out;
3274 : }
3275 1 : netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3276 1 : if (netbios_encoded == NULL) {
3277 0 : status =NT_STATUS_NO_MEMORY;
3278 0 : goto out;
3279 : }
3280 1 : sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3281 1 : if (sid_encoded == NULL) {
3282 0 : status = NT_STATUS_NO_MEMORY;
3283 0 : goto out;
3284 : }
3285 :
3286 1 : ok = samdb_is_pdc(state->ldb);
3287 1 : if (!ok) {
3288 0 : DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3289 0 : TALLOC_FREE(tmp_ctx);
3290 0 : status = NT_STATUS_INVALID_DOMAIN_ROLE;
3291 0 : goto out;
3292 : }
3293 :
3294 1 : status = dsdb_trust_search_tdo(state->ldb,
3295 1 : td->netbios_name,
3296 1 : td->domain_name,
3297 : attrs,
3298 : tmp_ctx,
3299 : &msg);
3300 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3301 0 : DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3302 : nt_errstr(status));
3303 0 : status = NT_STATUS_INVALID_DOMAIN_STATE;
3304 0 : goto out;
3305 : }
3306 :
3307 1 : ret = ldb_transaction_start(state->ldb);
3308 1 : if (ret != LDB_SUCCESS) {
3309 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3310 0 : goto out;
3311 : }
3312 1 : in_txn = true;
3313 :
3314 1 : msg = ldb_msg_new(tmp_ctx);
3315 1 : if (msg == NULL) {
3316 0 : status = NT_STATUS_NO_MEMORY;
3317 0 : goto out;
3318 : }
3319 :
3320 1 : msg->dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3321 1 : if (msg->dn == NULL) {
3322 0 : status = NT_STATUS_NO_MEMORY;
3323 0 : goto out;
3324 : }
3325 :
3326 1 : ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s", td->domain_name);
3327 1 : if (!ok) {
3328 0 : status = NT_STATUS_NO_MEMORY;
3329 0 : goto out;
3330 : }
3331 :
3332 1 : ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3333 1 : if (ret != LDB_SUCCESS) {
3334 0 : status = NT_STATUS_NO_MEMORY;
3335 0 : goto out;
3336 : }
3337 :
3338 1 : ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3339 1 : if (ret != LDB_SUCCESS) {
3340 0 : status = NT_STATUS_NO_MEMORY;
3341 0 : goto out;
3342 : }
3343 :
3344 1 : ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3345 1 : if (ret != LDB_SUCCESS) {
3346 0 : status = NT_STATUS_NO_MEMORY;
3347 0 : goto out;
3348 : }
3349 :
3350 1 : ret = samdb_msg_add_dom_sid(state->ldb,
3351 : tmp_ctx,
3352 : msg,
3353 : "securityIdentifier",
3354 : &td->security_identifier);
3355 1 : if (ret != LDB_SUCCESS) {
3356 0 : status = NT_STATUS_NO_MEMORY;
3357 0 : goto out;
3358 : }
3359 :
3360 1 : ret = samdb_msg_add_int(state->ldb,
3361 : tmp_ctx,
3362 : msg,
3363 : "trustType",
3364 1 : td->trust_type);
3365 1 : if (ret != LDB_SUCCESS) {
3366 0 : status = NT_STATUS_NO_MEMORY;
3367 0 : goto out;
3368 : }
3369 :
3370 1 : ret = samdb_msg_add_int(state->ldb,
3371 : tmp_ctx,
3372 : msg,
3373 : "trustAttributes",
3374 1 : td->trust_attributes);
3375 1 : if (ret != LDB_SUCCESS) {
3376 0 : status =NT_STATUS_NO_MEMORY;
3377 0 : goto out;
3378 : }
3379 :
3380 1 : ret = samdb_msg_add_int(state->ldb,
3381 : tmp_ctx,
3382 : msg,
3383 : "trustDirection",
3384 1 : td->trust_direction);
3385 1 : if (ret != LDB_SUCCESS) {
3386 0 : status = NT_STATUS_NO_MEMORY;
3387 0 : goto out;
3388 : }
3389 :
3390 1 : if (td->trust_auth_incoming.data != NULL) {
3391 0 : ret = ldb_msg_add_value(msg,
3392 : "trustAuthIncoming",
3393 0 : &td->trust_auth_incoming,
3394 : NULL);
3395 0 : if (ret != LDB_SUCCESS) {
3396 0 : status = NT_STATUS_NO_MEMORY;
3397 0 : goto out;
3398 : }
3399 : }
3400 1 : if (td->trust_auth_outgoing.data != NULL) {
3401 1 : ret = ldb_msg_add_value(msg,
3402 : "trustAuthOutgoing",
3403 1 : &td->trust_auth_outgoing,
3404 : NULL);
3405 1 : if (ret != LDB_SUCCESS) {
3406 0 : status = NT_STATUS_NO_MEMORY;
3407 0 : goto out;
3408 : }
3409 : }
3410 :
3411 : /* create the trusted_domain */
3412 1 : ret = ldb_add(state->ldb, msg);
3413 1 : switch (ret) {
3414 1 : case LDB_SUCCESS:
3415 1 : break;
3416 :
3417 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
3418 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3419 : ldb_dn_get_linearized(msg->dn),
3420 : ldb_errstring(state->ldb));
3421 0 : status = NT_STATUS_DOMAIN_EXISTS;
3422 0 : goto out;
3423 :
3424 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3425 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3426 : ldb_dn_get_linearized(msg->dn),
3427 : ldb_errstring(state->ldb));
3428 0 : status = NT_STATUS_ACCESS_DENIED;
3429 0 : goto out;
3430 :
3431 0 : default:
3432 0 : DBG_ERR("Failed to create trusted domain record %s: %s\n",
3433 : ldb_dn_get_linearized(msg->dn),
3434 : ldb_errstring(state->ldb));
3435 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3436 0 : goto out;
3437 : }
3438 :
3439 1 : ndr_err = ndr_pull_struct_blob(
3440 : &td->trust_auth_outgoing,
3441 : tmp_ctx,
3442 : &taiob,
3443 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3444 1 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3445 0 : status = ndr_map_error2ntstatus(ndr_err);
3446 0 : goto out;
3447 : }
3448 :
3449 1 : if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3450 0 : status = add_trust_user(tmp_ctx,
3451 : state->ldb,
3452 : base_dn,
3453 0 : td->netbios_name,
3454 : &taiob);
3455 0 : if (!NT_STATUS_IS_OK(status)) {
3456 0 : goto out;
3457 : }
3458 : }
3459 :
3460 1 : ret = ldb_transaction_commit(state->ldb);
3461 1 : if (ret != LDB_SUCCESS) {
3462 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3463 : }
3464 1 : in_txn = false;
3465 :
3466 : /*
3467 : * TODO: Notify winbindd that we have a new trust
3468 : */
3469 :
3470 1 : status = NT_STATUS_OK;
3471 :
3472 1 : out:
3473 1 : if (in_txn) {
3474 0 : ldb_transaction_cancel(state->ldb);
3475 : }
3476 1 : TALLOC_FREE(tmp_ctx);
3477 1 : return status;
3478 : }
3479 :
3480 0 : static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3481 : struct pdb_samba_dsdb_state *state,
3482 : const char *trust_user)
3483 : {
3484 0 : const char *attrs[] = { "userAccountControl", NULL };
3485 : struct ldb_message **msgs;
3486 : uint32_t uac;
3487 : int ret;
3488 :
3489 0 : ret = gendb_search(state->ldb,
3490 : mem_ctx,
3491 : ldb_get_default_basedn(state->ldb),
3492 : &msgs,
3493 : attrs,
3494 : "samAccountName=%s$",
3495 : trust_user);
3496 0 : if (ret > 1) {
3497 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3498 : }
3499 :
3500 0 : if (ret == 0) {
3501 0 : return NT_STATUS_OK;
3502 : }
3503 :
3504 0 : uac = ldb_msg_find_attr_as_uint(msgs[0],
3505 : "userAccountControl",
3506 : 0);
3507 0 : if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3508 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
3509 : }
3510 :
3511 0 : ret = ldb_delete(state->ldb, msgs[0]->dn);
3512 0 : switch (ret) {
3513 0 : case LDB_SUCCESS:
3514 0 : break;
3515 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3516 0 : return NT_STATUS_ACCESS_DENIED;
3517 0 : default:
3518 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3519 : }
3520 :
3521 0 : return NT_STATUS_OK;
3522 : }
3523 :
3524 1 : static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3525 : const char *domain)
3526 : {
3527 1 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3528 : methods->private_data, struct pdb_samba_dsdb_state);
3529 1 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3530 1 : struct pdb_trusted_domain *td = NULL;
3531 1 : struct ldb_dn *tdo_dn = NULL;
3532 1 : bool in_txn = false;
3533 : NTSTATUS status;
3534 : int ret;
3535 : bool ok;
3536 :
3537 1 : status = pdb_samba_dsdb_get_trusted_domain(methods,
3538 : tmp_ctx,
3539 : domain,
3540 : &td);
3541 1 : if (!NT_STATUS_IS_OK(status)) {
3542 0 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3543 0 : DBG_ERR("Searching TDO for %s returned %s\n",
3544 : domain, nt_errstr(status));
3545 0 : return status;
3546 : }
3547 0 : DBG_NOTICE("No TDO object for %s\n", domain);
3548 0 : return NT_STATUS_OK;
3549 : }
3550 :
3551 1 : tdo_dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3552 1 : if (tdo_dn == NULL) {
3553 0 : status = NT_STATUS_NO_MEMORY;
3554 0 : goto out;
3555 : }
3556 :
3557 1 : ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s", domain);
3558 1 : if (!ok) {
3559 0 : TALLOC_FREE(tmp_ctx);
3560 0 : status = NT_STATUS_NO_MEMORY;
3561 0 : goto out;
3562 : }
3563 :
3564 1 : ret = ldb_transaction_start(state->ldb);
3565 1 : if (ret != LDB_SUCCESS) {
3566 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3567 0 : goto out;
3568 : }
3569 1 : in_txn = true;
3570 :
3571 1 : ret = ldb_delete(state->ldb, tdo_dn);
3572 1 : if (ret != LDB_SUCCESS) {
3573 0 : status = NT_STATUS_INVALID_HANDLE;
3574 0 : goto out;
3575 : }
3576 :
3577 1 : if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3578 0 : status = delete_trust_user(tmp_ctx, state, domain);
3579 0 : if (!NT_STATUS_IS_OK(status)) {
3580 0 : goto out;
3581 : }
3582 : }
3583 :
3584 1 : ret = ldb_transaction_commit(state->ldb);
3585 1 : if (ret != LDB_SUCCESS) {
3586 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3587 0 : goto out;
3588 : }
3589 1 : in_txn = false;
3590 :
3591 1 : status = NT_STATUS_OK;
3592 :
3593 1 : out:
3594 1 : if (in_txn) {
3595 0 : ldb_transaction_cancel(state->ldb);
3596 : }
3597 1 : TALLOC_FREE(tmp_ctx);
3598 :
3599 1 : return status;
3600 : }
3601 :
3602 0 : static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3603 : TALLOC_CTX *mem_ctx,
3604 : uint32_t *_num_domains,
3605 : struct pdb_trusted_domain ***_domains)
3606 : {
3607 0 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3608 : m->private_data, struct pdb_samba_dsdb_state);
3609 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3610 0 : const char * const attrs[] = {
3611 : "securityIdentifier",
3612 : "flatName",
3613 : "trustPartner",
3614 : "trustAuthOutgoing",
3615 : "trustAuthIncoming",
3616 : "trustAttributes",
3617 : "trustDirection",
3618 : "trustType",
3619 : "trustPosixOffset",
3620 : "msDS-SupportedEncryptionTypes",
3621 : "msDS-TrustForestTrustInfo",
3622 : NULL
3623 : };
3624 0 : struct ldb_result *res = NULL;
3625 : unsigned int i;
3626 0 : struct pdb_trusted_domain **domains = NULL;
3627 : NTSTATUS status;
3628 0 : uint32_t di = 0;
3629 :
3630 0 : *_num_domains = 0;
3631 0 : *_domains = NULL;
3632 :
3633 0 : status = dsdb_trust_search_tdos(state->ldb, NULL,
3634 : attrs, tmp_ctx, &res);
3635 0 : if (!NT_STATUS_IS_OK(status)) {
3636 0 : DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
3637 0 : TALLOC_FREE(tmp_ctx);
3638 0 : return status;
3639 : }
3640 :
3641 0 : if (res->count == 0) {
3642 0 : TALLOC_FREE(tmp_ctx);
3643 0 : return NT_STATUS_OK;
3644 : }
3645 :
3646 0 : domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3647 : res->count);
3648 0 : if (domains == NULL) {
3649 0 : TALLOC_FREE(tmp_ctx);
3650 0 : return NT_STATUS_NO_MEMORY;
3651 : }
3652 :
3653 0 : for (i = 0; i < res->count; i++) {
3654 0 : struct ldb_message *msg = res->msgs[i];
3655 0 : struct pdb_trusted_domain *d = NULL;
3656 :
3657 0 : status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3658 0 : if (!NT_STATUS_IS_OK(status)) {
3659 0 : DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s ",
3660 : nt_errstr(status));
3661 0 : TALLOC_FREE(tmp_ctx);
3662 0 : return status;
3663 : }
3664 :
3665 0 : domains[di++] = d;
3666 : }
3667 :
3668 0 : domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3669 : di);
3670 0 : *_domains = talloc_move(mem_ctx, &domains);
3671 0 : *_num_domains = di;
3672 0 : TALLOC_FREE(tmp_ctx);
3673 0 : return NT_STATUS_OK;
3674 : }
3675 :
3676 74 : static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3677 : {
3678 74 : return true;
3679 : }
3680 :
3681 0 : static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3682 : {
3683 0 : return true;
3684 : }
3685 :
3686 3845 : static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3687 : {
3688 3845 : m->name = "samba_dsdb";
3689 3845 : m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3690 3845 : m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3691 3845 : m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3692 3845 : m->create_user = pdb_samba_dsdb_create_user;
3693 3845 : m->delete_user = pdb_samba_dsdb_delete_user;
3694 3845 : m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3695 3845 : m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3696 3845 : m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3697 3845 : m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3698 3845 : m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3699 3845 : m->getgrsid = pdb_samba_dsdb_getgrsid;
3700 3845 : m->getgrgid = pdb_samba_dsdb_getgrgid;
3701 3845 : m->getgrnam = pdb_samba_dsdb_getgrnam;
3702 3845 : m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3703 3845 : m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3704 3845 : m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3705 3845 : m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3706 3845 : m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3707 3845 : m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3708 3845 : m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3709 3845 : m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3710 3845 : m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3711 3845 : m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3712 3845 : m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3713 3845 : m->create_alias = pdb_samba_dsdb_create_alias;
3714 3845 : m->delete_alias = pdb_samba_dsdb_delete_alias;
3715 3845 : m->get_aliasinfo = pdb_default_get_aliasinfo;
3716 3845 : m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3717 3845 : m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3718 3845 : m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3719 3845 : m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3720 3845 : m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3721 3845 : m->lookup_names = pdb_samba_dsdb_lookup_names;
3722 3845 : m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3723 3845 : m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3724 3845 : m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3725 3845 : m->search_users = pdb_samba_dsdb_search_users;
3726 3845 : m->search_groups = pdb_samba_dsdb_search_groups;
3727 3845 : m->search_aliases = pdb_samba_dsdb_search_aliases;
3728 3845 : m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3729 3845 : m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3730 3845 : m->capabilities = pdb_samba_dsdb_capabilities;
3731 3845 : m->new_rid = pdb_samba_dsdb_new_rid;
3732 3845 : m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3733 3845 : m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3734 3845 : m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3735 3845 : m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3736 3845 : m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3737 3845 : m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3738 3845 : m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3739 3845 : m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3740 3845 : m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3741 3845 : m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3742 3845 : m->is_responsible_for_wellknown =
3743 : pdb_samba_dsdb_is_responsible_for_wellknown;
3744 3845 : m->is_responsible_for_everything_else =
3745 : pdb_samba_dsdb_is_responsible_for_everything_else;
3746 3845 : }
3747 :
3748 3727 : static void free_private_data(void **vp)
3749 : {
3750 3727 : struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3751 : *vp, struct pdb_samba_dsdb_state);
3752 3727 : talloc_unlink(state, state->ldb);
3753 3727 : return;
3754 : }
3755 :
3756 3845 : static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3757 : {
3758 : struct pdb_domain_info *dom_info;
3759 : struct dom_sid stored_sid;
3760 : struct GUID stored_guid;
3761 3845 : bool sid_exists_and_matches = false;
3762 3845 : bool guid_exists_and_matches = false;
3763 : bool ret;
3764 :
3765 3845 : dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3766 3845 : if (!dom_info) {
3767 0 : return NT_STATUS_UNSUCCESSFUL;
3768 : }
3769 :
3770 3845 : ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3771 3845 : if (ret) {
3772 3816 : if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3773 3816 : sid_exists_and_matches = true;
3774 : }
3775 : }
3776 :
3777 3845 : if (sid_exists_and_matches == false) {
3778 29 : secrets_clear_domain_protection(dom_info->name);
3779 29 : ret = secrets_store_domain_sid(dom_info->name,
3780 29 : &dom_info->sid);
3781 29 : ret &= secrets_mark_domain_protected(dom_info->name);
3782 29 : if (!ret) {
3783 0 : goto done;
3784 : }
3785 : }
3786 :
3787 3845 : ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3788 3845 : if (ret) {
3789 3795 : if (GUID_equal(&stored_guid, &dom_info->guid)) {
3790 3795 : guid_exists_and_matches = true;
3791 : }
3792 : }
3793 :
3794 3845 : if (guid_exists_and_matches == false) {
3795 50 : secrets_clear_domain_protection(dom_info->name);
3796 50 : ret = secrets_store_domain_guid(dom_info->name,
3797 50 : &dom_info->guid);
3798 50 : ret &= secrets_mark_domain_protected(dom_info->name);
3799 50 : if (!ret) {
3800 0 : goto done;
3801 : }
3802 : }
3803 :
3804 3845 : done:
3805 3845 : TALLOC_FREE(dom_info);
3806 3845 : if (!ret) {
3807 0 : return NT_STATUS_UNSUCCESSFUL;
3808 : }
3809 3845 : return NT_STATUS_OK;
3810 : }
3811 :
3812 3845 : static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3813 : const char *location)
3814 : {
3815 : struct pdb_methods *m;
3816 : struct pdb_samba_dsdb_state *state;
3817 : NTSTATUS status;
3818 3845 : char *errstring = NULL;
3819 : int ret;
3820 :
3821 3845 : if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3822 0 : return status;
3823 : }
3824 :
3825 3845 : state = talloc_zero(m, struct pdb_samba_dsdb_state);
3826 3845 : if (state == NULL) {
3827 0 : goto nomem;
3828 : }
3829 3845 : m->private_data = state;
3830 3845 : m->free_private_data = free_private_data;
3831 3845 : pdb_samba_dsdb_init_methods(m);
3832 :
3833 3845 : state->ev = s4_event_context_init(state);
3834 3845 : if (!state->ev) {
3835 0 : DEBUG(0, ("s4_event_context_init failed\n"));
3836 0 : goto nomem;
3837 : }
3838 :
3839 3845 : state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3840 3845 : if (state->lp_ctx == NULL) {
3841 0 : DEBUG(0, ("loadparm_init_s3 failed\n"));
3842 0 : goto nomem;
3843 : }
3844 :
3845 3845 : if (location == NULL) {
3846 3787 : location = "sam.ldb";
3847 : }
3848 :
3849 3845 : ret = samdb_connect_url(state,
3850 : state->ev,
3851 : state->lp_ctx,
3852 : system_session(state->lp_ctx),
3853 : 0,
3854 : location,
3855 : NULL,
3856 : &state->ldb,
3857 : &errstring);
3858 :
3859 3845 : if (!state->ldb) {
3860 0 : DEBUG(0, ("samdb_connect failed: %s: %s\n",
3861 : errstring, ldb_strerror(ret)));
3862 0 : status = NT_STATUS_INTERNAL_ERROR;
3863 0 : goto fail;
3864 : }
3865 :
3866 3845 : state->idmap_ctx = idmap_init(state, state->ev,
3867 : state->lp_ctx);
3868 3845 : if (!state->idmap_ctx) {
3869 0 : DEBUG(0, ("idmap failed\n"));
3870 0 : status = NT_STATUS_INTERNAL_ERROR;
3871 0 : goto fail;
3872 : }
3873 :
3874 3845 : status = pdb_samba_dsdb_init_secrets(m);
3875 3845 : if (!NT_STATUS_IS_OK(status)) {
3876 0 : DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3877 0 : goto fail;
3878 : }
3879 :
3880 3845 : *pdb_method = m;
3881 3845 : return NT_STATUS_OK;
3882 0 : nomem:
3883 0 : status = NT_STATUS_NO_MEMORY;
3884 0 : fail:
3885 0 : TALLOC_FREE(m);
3886 0 : return status;
3887 : }
3888 :
3889 : NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3890 682 : NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3891 : {
3892 682 : NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3893 : pdb_init_samba_dsdb);
3894 682 : if (!NT_STATUS_IS_OK(status)) {
3895 0 : return status;
3896 : }
3897 682 : return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3898 : pdb_init_samba_dsdb);
3899 : }
|