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