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