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