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 "system/time.h"
29 #include "system/filesys.h"
33 connect to the SAM database
34 return an opaque context pointer on success, or NULL on failure
36 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx,
37 struct auth_session_info *session_info)
39 struct ldb_context *ldb;
40 ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), session_info,
49 search the sam for the specified attributes in a specific domain, filter on
50 objectSid being in domain_sid.
52 int samdb_search_domain(struct ldb_context *sam_ldb,
54 const struct ldb_dn *basedn,
55 struct ldb_message ***res,
56 const char * const *attrs,
57 const struct dom_sid *domain_sid,
58 const char *format, ...) _PRINTF_ATTRIBUTE(7,8)
64 count = gendb_search_v(sam_ldb, mem_ctx, basedn,
65 res, attrs, format, ap);
71 struct dom_sid *entry_sid;
73 entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
75 if ((entry_sid == NULL) ||
76 (!dom_sid_in_domain(domain_sid, entry_sid))) {
77 /* Delete that entry from the result set */
78 (*res)[i] = (*res)[count-1];
80 talloc_free(entry_sid);
83 talloc_free(entry_sid);
91 search the sam for a single string attribute in exactly 1 record
93 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
95 const struct ldb_dn *basedn,
96 const char *attr_name,
97 const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
100 const char *attrs[2] = { NULL, NULL };
101 struct ldb_message **res = NULL;
103 attrs[0] = attr_name;
105 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
107 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
108 attr_name, format, count));
115 return samdb_result_string(res[0], attr_name, NULL);
120 search the sam for a single string attribute in exactly 1 record
122 const char *samdb_search_string(struct ldb_context *sam_ldb,
124 const struct ldb_dn *basedn,
125 const char *attr_name,
126 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
131 va_start(ap, format);
132 str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
138 struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
140 const struct ldb_dn *basedn,
141 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
145 struct ldb_message **res = NULL;
148 va_start(ap, format);
149 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
152 if (count != 1) return NULL;
154 ret = talloc_steal(mem_ctx, res[0]->dn);
161 search the sam for a dom_sid attribute in exactly 1 record
163 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
165 const struct ldb_dn *basedn,
166 const char *attr_name,
167 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
171 struct ldb_message **res;
172 const char *attrs[2] = { NULL, NULL };
175 attrs[0] = attr_name;
177 va_start(ap, format);
178 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
181 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
182 attr_name, format, count));
188 sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
194 return the count of the number of records in the sam matching the query
196 int samdb_search_count(struct ldb_context *sam_ldb,
198 const struct ldb_dn *basedn,
199 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
202 struct ldb_message **res;
203 const char * const attrs[] = { NULL };
206 va_start(ap, format);
207 ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
215 search the sam for a single integer attribute in exactly 1 record
217 uint_t samdb_search_uint(struct ldb_context *sam_ldb,
219 uint_t default_value,
220 const struct ldb_dn *basedn,
221 const char *attr_name,
222 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
226 struct ldb_message **res;
227 const char *attrs[2] = { NULL, NULL };
229 attrs[0] = attr_name;
231 va_start(ap, format);
232 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
236 return default_value;
239 return samdb_result_uint(res[0], attr_name, default_value);
243 search the sam for a single signed 64 bit integer attribute in exactly 1 record
245 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
247 int64_t default_value,
248 const struct ldb_dn *basedn,
249 const char *attr_name,
250 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
254 struct ldb_message **res;
255 const char *attrs[2] = { NULL, NULL };
257 attrs[0] = attr_name;
259 va_start(ap, format);
260 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
264 return default_value;
267 return samdb_result_int64(res[0], attr_name, default_value);
271 search the sam for multipe records each giving a single string attribute
272 return the number of matches, or -1 on error
274 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
276 const struct ldb_dn *basedn,
278 const char *attr_name,
279 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
283 const char *attrs[2] = { NULL, NULL };
284 struct ldb_message **res = NULL;
286 attrs[0] = attr_name;
288 va_start(ap, format);
289 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
296 /* make sure its single valued */
297 for (i=0;i<count;i++) {
298 if (res[i]->num_elements != 1) {
299 DEBUG(1,("samdb: search for %s %s not single valued\n",
306 *strs = talloc_array(mem_ctx, const char *, count+1);
312 for (i=0;i<count;i++) {
313 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
315 (*strs)[count] = NULL;
321 pull a uint from a result set.
323 uint_t samdb_result_uint(struct ldb_message *msg, const char *attr, uint_t default_value)
325 return ldb_msg_find_uint(msg, attr, default_value);
329 pull a (signed) int64 from a result set.
331 int64_t samdb_result_int64(struct ldb_message *msg, const char *attr, int64_t default_value)
333 return ldb_msg_find_int64(msg, attr, default_value);
337 pull a string from a result set.
339 const char *samdb_result_string(struct ldb_message *msg, const char *attr,
340 const char *default_value)
342 return ldb_msg_find_string(msg, attr, default_value);
345 struct ldb_dn *samdb_result_dn(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
346 const char *attr, struct ldb_dn *default_value)
348 const char *string = samdb_result_string(msg, attr, NULL);
349 if (string == NULL) return default_value;
350 return ldb_dn_explode(mem_ctx, string);
354 pull a rid from a objectSid in a result set.
356 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
357 const char *attr, uint32_t default_value)
362 sid = samdb_result_dom_sid(mem_ctx, msg, attr);
364 return default_value;
366 rid = sid->sub_auths[sid->num_auths-1];
372 pull a dom_sid structure from a objectSid in a result set.
374 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
377 const struct ldb_val *v;
380 v = ldb_msg_find_ldb_val(msg, attr);
384 sid = talloc(mem_ctx, struct dom_sid);
388 status = ndr_pull_struct_blob(v, sid, sid,
389 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
390 if (!NT_STATUS_IS_OK(status)) {
398 pull a guid structure from a objectGUID in a result set.
400 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
402 const struct ldb_val *v;
409 v = ldb_msg_find_ldb_val(msg, attr);
412 mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
413 if (!mem_ctx) return guid;
414 status = ndr_pull_struct_blob(v, mem_ctx, &guid,
415 (ndr_pull_flags_fn_t)ndr_pull_GUID);
416 talloc_free(mem_ctx);
417 if (!NT_STATUS_IS_OK(status)) {
425 pull a sid prefix from a objectSid in a result set.
426 this is used to find the domain sid for a user
428 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
431 struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
432 if (!sid || sid->num_auths < 1) return NULL;
438 pull a NTTIME in a result set.
440 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, NTTIME default_value)
442 const char *str = ldb_msg_find_string(msg, attr, NULL);
443 if (!str) return default_value;
444 return nttime_from_string(str);
448 pull a uint64_t from a result set.
450 uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
452 return ldb_msg_find_uint64(msg, attr, default_value);
457 construct the allow_password_change field from the PwdLastSet attribute and the
458 domain password settings
460 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
462 const struct ldb_dn *domain_dn,
463 struct ldb_message *msg,
466 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
469 if (attr_time == 0) {
473 minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
475 /* yes, this is a -= not a += as minPwdAge is stored as the negative
476 of the number of 100-nano-seconds */
477 attr_time -= minPwdAge;
483 construct the force_password_change field from the PwdLastSet attribute and the
484 domain password settings
486 NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
488 const struct ldb_dn *domain_dn,
489 struct ldb_message *msg,
492 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
495 if (attr_time == 0) {
499 maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
500 if (maxPwdAge == 0) {
503 attr_time -= maxPwdAge;
510 pull a samr_Password structutre from a result set.
512 struct samr_Password samdb_result_hash(struct ldb_message *msg, const char *attr)
514 struct samr_Password hash;
515 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
518 memcpy(hash.hash, val->data, MIN(val->length, sizeof(hash.hash)));
524 pull an array of samr_Password structutres from a result set.
526 uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
527 const char *attr, struct samr_Password **hashes)
530 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
537 count = val->length / 16;
542 *hashes = talloc_array(mem_ctx, struct samr_Password, count);
547 for (i=0;i<count;i++) {
548 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
554 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
555 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
558 const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL);
560 struct samr_Password *lmPwdHash, *ntPwdHash;
563 ntPwdHash = talloc(mem_ctx, struct samr_Password);
565 return NT_STATUS_NO_MEMORY;
568 E_md4hash(unicodePwd, ntPwdHash->hash);
575 lmPwdHash = talloc(mem_ctx, struct samr_Password);
577 return NT_STATUS_NO_MEMORY;
580 /* compute the new nt and lm hashes */
581 lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash);
592 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
595 } else if (num_nt > 1) {
596 return NT_STATUS_INTERNAL_DB_CORRUPTION;
598 *nt_pwd = &ntPwdHash[0];
603 num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
606 } else if (num_lm > 1) {
607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
609 *lm_pwd = &lmPwdHash[0];
618 pull a samr_LogonHours structutre from a result set.
620 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
622 struct samr_LogonHours hours;
623 const int units_per_week = 168;
624 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
626 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
630 hours.units_per_week = units_per_week;
631 memset(hours.bits, 0xFF, units_per_week);
633 memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
639 pull a set of account_flags from a result set.
641 uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
643 uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
644 return samdb_uf2acb(userAccountControl);
648 copy from a template record to a message
650 int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
651 struct ldb_message *msg, const char *expression)
653 struct ldb_message **res, *t;
657 /* pull the template record */
658 ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
660 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
666 for (i=0;i<t->num_elements;i++) {
667 struct ldb_message_element *el = &t->elements[i];
668 /* some elements should not be copied from the template */
669 if (strcasecmp(el->name, "cn") == 0 ||
670 strcasecmp(el->name, "name") == 0 ||
671 strcasecmp(el->name, "sAMAccountName") == 0) {
674 for (j=0;j<el->num_values;j++) {
675 if (strcasecmp(el->name, "objectClass") == 0 &&
676 (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
677 strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
678 strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
679 strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
680 strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
681 strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
682 strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
685 samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
686 (char *)el->values[j].data);
695 add a string element to a message
697 int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
698 const char *attr_name, const char *str)
700 char *s = talloc_strdup(mem_ctx, str);
701 char *a = talloc_strdup(mem_ctx, attr_name);
702 if (s == NULL || a == NULL) {
705 return ldb_msg_add_string(msg, a, s);
709 add a dom_sid element to a message
711 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
712 const char *attr_name, struct dom_sid *sid)
716 status = ndr_push_struct_blob(&v, mem_ctx, sid,
717 (ndr_push_flags_fn_t)ndr_push_dom_sid);
718 if (!NT_STATUS_IS_OK(status)) {
721 return ldb_msg_add_value(msg, attr_name, &v);
726 add a delete element operation to a message
728 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
729 const char *attr_name)
731 char *a = talloc_strdup(mem_ctx, attr_name);
735 /* we use an empty replace rather than a delete, as it allows for
736 samdb_replace() to be used everywhere */
737 return ldb_msg_add_empty(msg, a, LDB_FLAG_MOD_REPLACE);
741 add a add attribute value to a message
743 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
744 const char *attr_name, const char *value)
746 struct ldb_message_element *el;
749 a = talloc_strdup(mem_ctx, attr_name);
752 v = talloc_strdup(mem_ctx, value);
755 ret = ldb_msg_add_string(msg, a, v);
758 el = ldb_msg_find_element(msg, a);
761 el->flags = LDB_FLAG_MOD_ADD;
766 add a delete attribute value to a message
768 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
769 const char *attr_name, const char *value)
771 struct ldb_message_element *el;
774 a = talloc_strdup(mem_ctx, attr_name);
777 v = talloc_strdup(mem_ctx, value);
780 ret = ldb_msg_add_string(msg, a, v);
783 el = ldb_msg_find_element(msg, a);
786 el->flags = LDB_FLAG_MOD_DELETE;
791 add a uint_t element to a message
793 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
794 const char *attr_name, uint_t v)
796 const char *s = talloc_asprintf(mem_ctx, "%u", v);
797 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
801 add a (signed) int64_t element to a message
803 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
804 const char *attr_name, int64_t v)
806 const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
807 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
811 add a uint64_t element to a message
813 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
814 const char *attr_name, uint64_t v)
816 const char *s = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)v);
817 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
821 add a samr_Password element to a message
823 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
824 const char *attr_name, struct samr_Password *hash)
827 val.data = talloc_memdup(mem_ctx, hash->hash, 16);
832 return ldb_msg_add_value(msg, attr_name, &val);
836 add a samr_Password array to a message
838 int samdb_msg_add_hashes(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
839 const char *attr_name, struct samr_Password *hashes, uint_t count)
843 val.data = talloc_array_size(mem_ctx, 16, count);
844 val.length = count*16;
848 for (i=0;i<count;i++) {
849 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
851 return ldb_msg_add_value(msg, attr_name, &val);
855 add a acct_flags element to a message
857 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
858 const char *attr_name, uint32_t v)
860 return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
864 add a logon_hours element to a message
866 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
867 const char *attr_name, struct samr_LogonHours *hours)
870 val.length = hours->units_per_week / 8;
871 val.data = hours->bits;
872 return ldb_msg_add_value(msg, attr_name, &val);
876 add a general value element to a message
878 int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
879 const char *attr_name, const struct ldb_val *val)
881 return ldb_msg_add_value(msg, attr_name, val);
885 sets a general value element to a message
887 int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
888 const char *attr_name, const struct ldb_val *val)
890 struct ldb_message_element *el;
892 el = ldb_msg_find_element(msg, attr_name);
896 return ldb_msg_add_value(msg, attr_name, val);
900 set a string element in a message
902 int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
903 const char *attr_name, const char *str)
905 struct ldb_message_element *el;
907 el = ldb_msg_find_element(msg, attr_name);
911 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
917 int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
919 return ldb_add(sam_ldb, msg);
925 int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const struct ldb_dn *dn)
927 return ldb_delete(sam_ldb, dn);
933 int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
935 return ldb_modify(sam_ldb, msg);
939 replace elements in a record
941 int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
945 /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
946 for (i=0;i<msg->num_elements;i++) {
947 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
950 /* modify the samdb record */
951 return samdb_modify(sam_ldb, mem_ctx, msg);
955 return a default security descriptor
957 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
959 struct security_descriptor *sd;
961 sd = security_descriptor_initialise(mem_ctx);
966 struct ldb_dn *samdb_base_dn(TALLOC_CTX *mem_ctx)
968 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
969 int server_role = lp_server_role();
970 const char **split_realm;
977 if ((server_role == ROLE_DOMAIN_PDC)
978 || (server_role == ROLE_DOMAIN_BDC)) {
980 split_realm = str_list_make(tmp_ctx, lp_realm(), ".");
982 talloc_free(tmp_ctx);
986 i = str_list_length(split_realm);
988 for (; i >= 0; i--) {
989 dn = ldb_dn_build_child(tmp_ctx, "dc", split_realm[i], dn);
991 talloc_free(tmp_ctx);
997 return ldb_dn_string_compose(mem_ctx, NULL, "cn=%s", lp_netbios_name());
1002 work out the domain sid for the current open ldb
1004 const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
1006 const char *attrs[] = { "rootDomainNamingContext", NULL };
1008 struct ldb_result *res = NULL;
1009 TALLOC_CTX *tmp_ctx;
1010 struct dom_sid *domain_sid;
1011 const char *basedn_s;
1012 struct ldb_dn *basedn;
1014 /* see if we have a cached copy */
1015 domain_sid = ldb_get_opaque(ldb, "cache.domain_sid");
1020 tmp_ctx = talloc_new(ldb);
1021 if (tmp_ctx == NULL) {
1025 basedn = ldb_dn_explode(tmp_ctx, "");
1026 if (basedn == NULL) {
1030 /* find the basedn of the domain from the rootdse */
1031 ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, attrs, &res);
1032 talloc_steal(tmp_ctx, res);
1033 if (ret != LDB_SUCCESS || res->count != 1) {
1037 basedn_s = ldb_msg_find_string(res->msgs[0], "rootDomainNamingContext", NULL);
1038 if (basedn_s == NULL) {
1042 basedn = ldb_dn_explode(tmp_ctx, basedn_s);
1043 if (basedn == NULL) {
1047 /* find the domain_sid */
1048 domain_sid = samdb_search_dom_sid(ldb, tmp_ctx, basedn,
1049 "objectSid", "objectClass=domainDNS");
1050 if (domain_sid == NULL) {
1054 /* cache the domain_sid in the ldb */
1055 if (ldb_set_opaque(ldb, "cache.domain_sid", domain_sid) != LDB_SUCCESS) {
1059 talloc_steal(ldb, domain_sid);
1060 talloc_free(tmp_ctx);
1065 DEBUG(1,("Failed to find domain_sid for open ldb\n"));
1066 talloc_free(tmp_ctx);