2 Unix SMB/CIFS implementation.
4 interface functions for the sam database
6 Copyright (C) Andrew Tridgell 2004
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "librpc/gen_ndr/ndr_netlogon.h"
25 #include "librpc/gen_ndr/ndr_misc.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_errors.h"
28 #include "libcli/security/proto.h"
29 #include "system/time.h"
30 #include "system/filesys.h"
32 #include "dsdb/samdb/samdb.h"
36 connect to the SAM database
37 return an opaque context pointer on success, or NULL on failure
39 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
40 struct auth_session_info *session_info)
42 struct ldb_context *ldb;
43 ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), session_info,
52 search the sam for the specified attributes in a specific domain, filter on
53 objectSid being in domain_sid.
55 int samdb_search_domain(struct ldb_context *sam_ldb,
57 const struct ldb_dn *basedn,
58 struct ldb_message ***res,
59 const char * const *attrs,
60 const struct dom_sid *domain_sid,
61 const char *format, ...) _PRINTF_ATTRIBUTE(7,8)
67 count = gendb_search_v(sam_ldb, mem_ctx, basedn,
68 res, attrs, format, ap);
74 struct dom_sid *entry_sid;
76 entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
78 if ((entry_sid == NULL) ||
79 (!dom_sid_in_domain(domain_sid, entry_sid))) {
80 /* Delete that entry from the result set */
81 (*res)[i] = (*res)[count-1];
83 talloc_free(entry_sid);
86 talloc_free(entry_sid);
94 search the sam for a single string attribute in exactly 1 record
96 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
98 const struct ldb_dn *basedn,
99 const char *attr_name,
100 const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
103 const char *attrs[2] = { NULL, NULL };
104 struct ldb_message **res = NULL;
106 attrs[0] = attr_name;
108 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
110 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
111 attr_name, format, count));
118 return samdb_result_string(res[0], attr_name, NULL);
123 search the sam for a single string attribute in exactly 1 record
125 const char *samdb_search_string(struct ldb_context *sam_ldb,
127 const struct ldb_dn *basedn,
128 const char *attr_name,
129 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
134 va_start(ap, format);
135 str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
141 struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
143 const struct ldb_dn *basedn,
144 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
148 struct ldb_message **res = NULL;
151 va_start(ap, format);
152 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
155 if (count != 1) return NULL;
157 ret = talloc_steal(mem_ctx, res[0]->dn);
164 search the sam for a dom_sid attribute in exactly 1 record
166 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
168 const struct ldb_dn *basedn,
169 const char *attr_name,
170 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
174 struct ldb_message **res;
175 const char *attrs[2] = { NULL, NULL };
178 attrs[0] = attr_name;
180 va_start(ap, format);
181 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
184 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
185 attr_name, format, count));
191 sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
197 return the count of the number of records in the sam matching the query
199 int samdb_search_count(struct ldb_context *sam_ldb,
201 const struct ldb_dn *basedn,
202 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
205 struct ldb_message **res;
206 const char * const attrs[] = { NULL };
209 va_start(ap, format);
210 ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
218 search the sam for a single integer attribute in exactly 1 record
220 uint_t samdb_search_uint(struct ldb_context *sam_ldb,
222 uint_t default_value,
223 const struct ldb_dn *basedn,
224 const char *attr_name,
225 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
229 struct ldb_message **res;
230 const char *attrs[2] = { NULL, NULL };
232 attrs[0] = attr_name;
234 va_start(ap, format);
235 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
239 return default_value;
242 return samdb_result_uint(res[0], attr_name, default_value);
246 search the sam for a single signed 64 bit integer attribute in exactly 1 record
248 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
250 int64_t default_value,
251 const struct ldb_dn *basedn,
252 const char *attr_name,
253 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
257 struct ldb_message **res;
258 const char *attrs[2] = { NULL, NULL };
260 attrs[0] = attr_name;
262 va_start(ap, format);
263 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
267 return default_value;
270 return samdb_result_int64(res[0], attr_name, default_value);
274 search the sam for multipe records each giving a single string attribute
275 return the number of matches, or -1 on error
277 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
279 const struct ldb_dn *basedn,
281 const char *attr_name,
282 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
286 const char *attrs[2] = { NULL, NULL };
287 struct ldb_message **res = NULL;
289 attrs[0] = attr_name;
291 va_start(ap, format);
292 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
299 /* make sure its single valued */
300 for (i=0;i<count;i++) {
301 if (res[i]->num_elements != 1) {
302 DEBUG(1,("samdb: search for %s %s not single valued\n",
309 *strs = talloc_array(mem_ctx, const char *, count+1);
315 for (i=0;i<count;i++) {
316 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
318 (*strs)[count] = NULL;
324 pull a uint from a result set.
326 uint_t samdb_result_uint(struct ldb_message *msg, const char *attr, uint_t default_value)
328 return ldb_msg_find_uint(msg, attr, default_value);
332 pull a (signed) int64 from a result set.
334 int64_t samdb_result_int64(struct ldb_message *msg, const char *attr, int64_t default_value)
336 return ldb_msg_find_int64(msg, attr, default_value);
340 pull a string from a result set.
342 const char *samdb_result_string(struct ldb_message *msg, const char *attr,
343 const char *default_value)
345 return ldb_msg_find_string(msg, attr, default_value);
348 struct ldb_dn *samdb_result_dn(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
349 const char *attr, struct ldb_dn *default_value)
351 const char *string = samdb_result_string(msg, attr, NULL);
352 if (string == NULL) return default_value;
353 return ldb_dn_explode(mem_ctx, string);
357 pull a rid from a objectSid in a result set.
359 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
360 const char *attr, uint32_t default_value)
365 sid = samdb_result_dom_sid(mem_ctx, msg, attr);
367 return default_value;
369 rid = sid->sub_auths[sid->num_auths-1];
375 pull a dom_sid structure from a objectSid in a result set.
377 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
380 const struct ldb_val *v;
383 v = ldb_msg_find_ldb_val(msg, attr);
387 sid = talloc(mem_ctx, struct dom_sid);
391 status = ndr_pull_struct_blob(v, sid, sid,
392 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
393 if (!NT_STATUS_IS_OK(status)) {
401 pull a guid structure from a objectGUID in a result set.
403 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
405 const struct ldb_val *v;
412 v = ldb_msg_find_ldb_val(msg, attr);
415 mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
416 if (!mem_ctx) return guid;
417 status = ndr_pull_struct_blob(v, mem_ctx, &guid,
418 (ndr_pull_flags_fn_t)ndr_pull_GUID);
419 talloc_free(mem_ctx);
420 if (!NT_STATUS_IS_OK(status)) {
428 pull a sid prefix from a objectSid in a result set.
429 this is used to find the domain sid for a user
431 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
434 struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
435 if (!sid || sid->num_auths < 1) return NULL;
441 pull a NTTIME in a result set.
443 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
445 const char *str = ldb_msg_find_string(msg, attr, NULL);
446 if (!str) return default_value;
447 return nttime_from_string(str);
451 pull a uint64_t from a result set.
453 uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
455 return ldb_msg_find_uint64(msg, attr, default_value);
460 construct the allow_password_change field from the PwdLastSet attribute and the
461 domain password settings
463 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
465 const struct ldb_dn *domain_dn,
466 struct ldb_message *msg,
469 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
472 if (attr_time == 0) {
476 minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
478 /* yes, this is a -= not a += as minPwdAge is stored as the negative
479 of the number of 100-nano-seconds */
480 attr_time -= minPwdAge;
486 construct the force_password_change field from the PwdLastSet attribute and the
487 domain password settings
489 NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
491 const struct ldb_dn *domain_dn,
492 struct ldb_message *msg)
494 uint64_t attr_time = samdb_result_uint64(msg, "pwdLastSet", 0);
495 uint32_t user_flags = samdb_result_uint64(msg, "userAccountControl", 0);
498 if (user_flags & UF_DONT_EXPIRE_PASSWD) {
499 return 0x7FFFFFFFFFFFFFFFULL;
502 if (attr_time == 0) {
506 maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
507 if (maxPwdAge == 0) {
510 attr_time -= maxPwdAge;
517 pull a samr_Password structutre from a result set.
519 struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
521 struct samr_Password *hash = NULL;
522 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
523 if (val && (val->length >= sizeof(hash->hash))) {
524 hash = talloc(mem_ctx, struct samr_Password);
525 memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
531 pull an array of samr_Password structutres from a result set.
533 uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
534 const char *attr, struct samr_Password **hashes)
537 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
544 count = val->length / 16;
549 *hashes = talloc_array(mem_ctx, struct samr_Password, count);
554 for (i=0;i<count;i++) {
555 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
561 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
562 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
564 struct samr_Password *lmPwdHash, *ntPwdHash;
567 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
570 } else if (num_nt > 1) {
571 return NT_STATUS_INTERNAL_DB_CORRUPTION;
573 *nt_pwd = &ntPwdHash[0];
578 num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
581 } else if (num_lm > 1) {
582 return NT_STATUS_INTERNAL_DB_CORRUPTION;
584 *lm_pwd = &lmPwdHash[0];
591 pull a samr_LogonHours structutre from a result set.
593 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
595 struct samr_LogonHours hours;
596 const int units_per_week = 168;
597 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
599 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
603 hours.units_per_week = units_per_week;
604 memset(hours.bits, 0xFF, units_per_week);
606 memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
612 pull a set of account_flags from a result set.
614 uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
616 uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
617 return samdb_uf2acb(userAccountControl);
621 copy from a template record to a message
623 int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
624 struct ldb_message *msg, const char *expression)
626 struct ldb_message **res, *t;
630 /* pull the template record */
631 ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
633 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
639 for (i=0;i<t->num_elements;i++) {
640 struct ldb_message_element *el = &t->elements[i];
641 /* some elements should not be copied from the template */
642 if (strcasecmp(el->name, "cn") == 0 ||
643 strcasecmp(el->name, "name") == 0 ||
644 strcasecmp(el->name, "sAMAccountName") == 0) {
647 for (j=0;j<el->num_values;j++) {
648 if (strcasecmp(el->name, "objectClass") == 0 &&
649 (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
650 strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
651 strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
652 strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
653 strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
654 strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
655 strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
658 samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
659 (char *)el->values[j].data);
668 add a string element to a message
670 int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
671 const char *attr_name, const char *str)
673 char *s = talloc_strdup(mem_ctx, str);
674 char *a = talloc_strdup(mem_ctx, attr_name);
675 if (s == NULL || a == NULL) {
678 return ldb_msg_add_string(msg, a, s);
682 add a dom_sid element to a message
684 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
685 const char *attr_name, struct dom_sid *sid)
689 status = ndr_push_struct_blob(&v, mem_ctx, sid,
690 (ndr_push_flags_fn_t)ndr_push_dom_sid);
691 if (!NT_STATUS_IS_OK(status)) {
694 return ldb_msg_add_value(msg, attr_name, &v);
699 add a delete element operation to a message
701 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
702 const char *attr_name)
704 /* we use an empty replace rather than a delete, as it allows for
705 samdb_replace() to be used everywhere */
706 return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE);
710 add a add attribute value to a message
712 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
713 const char *attr_name, const char *value)
715 struct ldb_message_element *el;
718 a = talloc_strdup(mem_ctx, attr_name);
721 v = talloc_strdup(mem_ctx, value);
724 ret = ldb_msg_add_string(msg, a, v);
727 el = ldb_msg_find_element(msg, a);
730 el->flags = LDB_FLAG_MOD_ADD;
735 add a delete attribute value to a message
737 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
738 const char *attr_name, const char *value)
740 struct ldb_message_element *el;
743 a = talloc_strdup(mem_ctx, attr_name);
746 v = talloc_strdup(mem_ctx, value);
749 ret = ldb_msg_add_string(msg, a, v);
752 el = ldb_msg_find_element(msg, a);
755 el->flags = LDB_FLAG_MOD_DELETE;
760 add a uint_t element to a message
762 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
763 const char *attr_name, uint_t v)
765 const char *s = talloc_asprintf(mem_ctx, "%u", v);
766 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
770 add a (signed) int64_t element to a message
772 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
773 const char *attr_name, int64_t v)
775 const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
776 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
780 add a uint64_t element to a message
782 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
783 const char *attr_name, uint64_t v)
785 const char *s = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)v);
786 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
790 add a samr_Password element to a message
792 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
793 const char *attr_name, struct samr_Password *hash)
796 val.data = talloc_memdup(mem_ctx, hash->hash, 16);
801 return ldb_msg_add_value(msg, attr_name, &val);
805 add a samr_Password array to a message
807 int samdb_msg_add_hashes(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
808 const char *attr_name, struct samr_Password *hashes, uint_t count)
812 val.data = talloc_array_size(mem_ctx, 16, count);
813 val.length = count*16;
817 for (i=0;i<count;i++) {
818 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
820 return ldb_msg_add_value(msg, attr_name, &val);
824 add a acct_flags element to a message
826 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
827 const char *attr_name, uint32_t v)
829 return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
833 add a logon_hours element to a message
835 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
836 const char *attr_name, struct samr_LogonHours *hours)
839 val.length = hours->units_per_week / 8;
840 val.data = hours->bits;
841 return ldb_msg_add_value(msg, attr_name, &val);
845 add a general value element to a message
847 int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
848 const char *attr_name, const struct ldb_val *val)
850 return ldb_msg_add_value(msg, attr_name, val);
854 sets a general value element to a message
856 int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
857 const char *attr_name, const struct ldb_val *val)
859 struct ldb_message_element *el;
861 el = ldb_msg_find_element(msg, attr_name);
865 return ldb_msg_add_value(msg, attr_name, val);
869 set a string element in a message
871 int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
872 const char *attr_name, const char *str)
874 struct ldb_message_element *el;
876 el = ldb_msg_find_element(msg, attr_name);
880 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
886 int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
888 return ldb_add(sam_ldb, msg);
894 int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const struct ldb_dn *dn)
896 return ldb_delete(sam_ldb, dn);
902 int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
904 return ldb_modify(sam_ldb, msg);
908 replace elements in a record
910 int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
914 /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
915 for (i=0;i<msg->num_elements;i++) {
916 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
919 /* modify the samdb record */
920 return samdb_modify(sam_ldb, mem_ctx, msg);
924 return a default security descriptor
926 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
928 struct security_descriptor *sd;
930 sd = security_descriptor_initialise(mem_ctx);
935 struct ldb_dn *samdb_base_dn(TALLOC_CTX *mem_ctx)
937 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
938 int server_role = lp_server_role();
939 const char **split_realm;
946 if ((server_role == ROLE_DOMAIN_PDC)
947 || (server_role == ROLE_DOMAIN_BDC)) {
949 split_realm = str_list_make(tmp_ctx, lp_realm(), ".");
951 talloc_free(tmp_ctx);
955 i = str_list_length(split_realm);
957 for (; i >= 0; i--) {
958 dn = ldb_dn_build_child(tmp_ctx, "dc", split_realm[i], dn);
960 talloc_free(tmp_ctx);
966 return ldb_dn_string_compose(mem_ctx, NULL, "cn=%s", lp_netbios_name());
971 work out the domain sid for the current open ldb
973 const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
975 const char *attrs[] = { "rootDomainNamingContext", NULL };
977 struct ldb_result *res = NULL;
979 struct dom_sid *domain_sid;
980 const char *basedn_s;
981 struct ldb_dn *basedn;
983 /* see if we have a cached copy */
984 domain_sid = ldb_get_opaque(ldb, "cache.domain_sid");
989 tmp_ctx = talloc_new(ldb);
990 if (tmp_ctx == NULL) {
994 basedn = ldb_dn_explode(tmp_ctx, "");
995 if (basedn == NULL) {
999 /* find the basedn of the domain from the rootdse */
1000 ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, attrs, &res);
1001 talloc_steal(tmp_ctx, res);
1002 if (ret != LDB_SUCCESS || res->count != 1) {
1006 basedn_s = ldb_msg_find_string(res->msgs[0], "rootDomainNamingContext", NULL);
1007 if (basedn_s == NULL) {
1011 basedn = ldb_dn_explode(tmp_ctx, basedn_s);
1012 if (basedn == NULL) {
1016 /* find the domain_sid */
1017 domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, basedn,
1018 "objectSid", "objectClass=domainDNS");
1019 if (domain_sid == NULL) {
1023 /* cache the domain_sid in the ldb */
1024 if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) {
1028 talloc_steal(ldb, domain_sid);
1029 talloc_free(tmp_ctx);
1034 DEBUG(1,("Failed to find domain_sid for open ldb\n"));
1035 talloc_free(tmp_ctx);