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 "lib/ldb/include/ldb.h"
28 connect to the SAM database
29 return an opaque context pointer on success, or NULL on failure
31 void *samdb_connect(TALLOC_CTX *mem_ctx)
33 return ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
37 search the sam for the specified attributes - varargs variant
39 int samdb_search(void *ctx,
42 struct ldb_message ***res,
43 const char * const *attrs,
44 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
46 struct ldb_wrap *sam_ctx = ctx;
51 count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, res, attrs, format, ap);
58 free up a search result
60 int samdb_search_free(void *ctx,
61 TALLOC_CTX *mem_ctx, struct ldb_message **res)
63 struct ldb_wrap *sam_ctx = ctx;
64 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
65 return ldb_search_free(sam_ctx->ldb, res);
69 search the sam for a single string attribute in exactly 1 record
71 const char *samdb_search_string_v(void *ctx,
74 const char *attr_name,
75 const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
77 struct ldb_wrap *sam_ctx = ctx;
79 const char * const attrs[2] = { attr_name, NULL };
80 struct ldb_message **res = NULL;
82 count = gendb_search_v(sam_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
84 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
85 attr_name, format, count));
88 samdb_search_free(ctx, mem_ctx, res);
92 return samdb_result_string(res[0], attr_name, NULL);
97 search the sam for a single string attribute in exactly 1 record
99 const char *samdb_search_string(void *ctx,
102 const char *attr_name,
103 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
108 va_start(ap, format);
109 str = samdb_search_string_v(ctx, mem_ctx, basedn, attr_name, format, ap);
116 return the count of the number of records in the sam matching the query
118 int samdb_search_count(void *ctx,
121 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
123 struct ldb_wrap *samdb_ctx = ctx;
125 struct ldb_message **res;
126 const char * const attrs[] = { NULL };
129 va_start(ap, format);
130 ret = gendb_search_v(samdb_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
138 search the sam for a single integer attribute in exactly 1 record
140 uint_t samdb_search_uint(void *ctx,
142 uint_t default_value,
144 const char *attr_name,
145 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
147 struct ldb_wrap *samdb_ctx = ctx;
150 struct ldb_message **res;
151 const char * const attrs[2] = { attr_name, NULL };
153 va_start(ap, format);
154 count = gendb_search_v(samdb_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
158 return default_value;
161 return samdb_result_uint(res[0], attr_name, default_value);
165 search the sam for a single signed 64 bit integer attribute in exactly 1 record
167 int64_t samdb_search_int64(void *ctx,
169 int64_t default_value,
171 const char *attr_name,
172 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
174 struct ldb_wrap *samdb_ctx = ctx;
177 struct ldb_message **res;
178 const char * const attrs[2] = { attr_name, NULL };
180 va_start(ap, format);
181 count = gendb_search_v(samdb_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
185 return default_value;
188 return samdb_result_int64(res[0], attr_name, default_value);
192 search the sam for multipe records each giving a single string attribute
193 return the number of matches, or -1 on error
195 int samdb_search_string_multiple(void *ctx,
199 const char *attr_name,
200 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
202 struct ldb_wrap *samdb_ctx = ctx;
205 const char * const attrs[2] = { attr_name, NULL };
206 struct ldb_message **res = NULL;
208 va_start(ap, format);
209 count = gendb_search_v(samdb_ctx->ldb, mem_ctx, basedn, &res, attrs, format, ap);
216 /* make sure its single valued */
217 for (i=0;i<count;i++) {
218 if (res[i]->num_elements != 1) {
219 DEBUG(1,("samdb: search for %s %s not single valued\n",
221 samdb_search_free(ctx, mem_ctx, res);
226 *strs = talloc_array_p(mem_ctx, const char *, count+1);
228 samdb_search_free(ctx, mem_ctx, res);
232 for (i=0;i<count;i++) {
233 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
235 (*strs)[count] = NULL;
241 pull a uint from a result set.
243 uint_t samdb_result_uint(struct ldb_message *msg, const char *attr, uint_t default_value)
245 return ldb_msg_find_uint(msg, attr, default_value);
249 pull a (signed) int64 from a result set.
251 int64_t samdb_result_int64(struct ldb_message *msg, const char *attr, int64_t default_value)
253 return ldb_msg_find_int64(msg, attr, default_value);
257 pull a string from a result set.
259 const char *samdb_result_string(struct ldb_message *msg, const char *attr,
260 const char *default_value)
262 return ldb_msg_find_string(msg, attr, default_value);
266 pull a rid from a objectSid in a result set.
268 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
269 const char *attr, uint32_t default_value)
272 const char *sidstr = ldb_msg_find_string(msg, attr, NULL);
273 if (!sidstr) return default_value;
275 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
276 if (!sid) return default_value;
278 return sid->sub_auths[sid->num_auths-1];
282 pull a dom_sid structure from a objectSid in a result set.
284 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
287 const char *sidstr = ldb_msg_find_string(msg, attr, NULL);
288 if (!sidstr) return NULL;
290 return dom_sid_parse_talloc(mem_ctx, sidstr);
294 pull a guid structure from a objectGUID in a result set.
296 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
300 const char *guidstr = ldb_msg_find_string(msg, attr, NULL);
304 if (!guidstr) return guid;
306 status = GUID_from_string(guidstr, &guid);
307 if (!NT_STATUS_IS_OK(status)) {
316 pull a sid prefix from a objectSid in a result set.
317 this is used to find the domain sid for a user
319 const char *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
322 struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
323 if (!sid || sid->num_auths < 1) return NULL;
327 return dom_sid_string(mem_ctx, sid);
331 pull a NTTIME in a result set.
333 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, const char *default_value)
335 const char *str = ldb_msg_find_string(msg, attr, default_value);
336 return nttime_from_string(str);
340 pull a uint64_t from a result set.
342 uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
344 return ldb_msg_find_uint64(msg, attr, default_value);
349 construct the allow_password_change field from the PwdLastSet attribute and the
350 domain password settings
352 NTTIME samdb_result_allow_password_change(void *ctx, TALLOC_CTX *mem_ctx,
353 const char *domain_dn,
354 struct ldb_message *msg,
357 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
360 if (attr_time == 0) {
364 minPwdAge = samdb_search_int64(ctx, mem_ctx, 0, NULL,
365 "minPwdAge", "dn=%s", domain_dn);
367 /* yes, this is a -= not a += as minPwdAge is stored as the negative
368 of the number of 100-nano-seconds */
369 attr_time -= minPwdAge;
375 construct the force_password_change field from the PwdLastSet attribute and the
376 domain password settings
378 NTTIME samdb_result_force_password_change(void *ctx, TALLOC_CTX *mem_ctx,
379 const char *domain_dn,
380 struct ldb_message *msg,
383 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
386 if (attr_time == 0) {
390 maxPwdAge = samdb_search_int64(ctx, mem_ctx, 0, NULL, "maxPwdAge", "dn=%s", domain_dn);
391 if (maxPwdAge == 0) {
394 attr_time -= maxPwdAge;
401 pull a samr_Password structutre from a result set.
403 struct samr_Password samdb_result_hash(struct ldb_message *msg, const char *attr)
405 struct samr_Password hash;
406 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
409 memcpy(hash.hash, val->data, MIN(val->length, sizeof(hash.hash)));
415 pull an array of samr_Password structutres from a result set.
417 uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
418 const char *attr, struct samr_Password **hashes)
421 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
428 count = val->length / 16;
433 *hashes = talloc_array_p(mem_ctx, struct samr_Password, count);
438 for (i=0;i<count;i++) {
439 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
445 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
446 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
449 const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL);
451 struct samr_Password *lmPwdHash, *ntPwdHash;
454 ntPwdHash = talloc_p(mem_ctx, struct samr_Password);
456 return NT_STATUS_NO_MEMORY;
459 E_md4hash(unicodePwd, ntPwdHash->hash);
466 lmPwdHash = talloc_p(mem_ctx, struct samr_Password);
468 return NT_STATUS_NO_MEMORY;
471 /* compute the new nt and lm hashes */
472 lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash);
483 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
486 } else if (num_nt > 1) {
487 return NT_STATUS_INTERNAL_DB_CORRUPTION;
489 *nt_pwd = &ntPwdHash[0];
494 num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
497 } else if (num_lm > 1) {
498 return NT_STATUS_INTERNAL_DB_CORRUPTION;
500 *lm_pwd = &lmPwdHash[0];
509 pull a samr_LogonHours structutre from a result set.
511 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
513 struct samr_LogonHours hours;
514 const int units_per_week = 168;
515 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
517 hours.bitmap = talloc_array_p(mem_ctx, uint8, units_per_week);
521 hours.units_per_week = units_per_week;
522 memset(hours.bitmap, 0xFF, units_per_week);
524 memcpy(hours.bitmap, val->data, MIN(val->length, units_per_week));
530 pull a set of account_flags from a result set.
532 uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
534 uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
535 return samdb_uf2acb(userAccountControl);
539 copy from a template record to a message
541 int samdb_copy_template(void *ctx, TALLOC_CTX *mem_ctx,
542 struct ldb_message *msg, const char *expression)
544 struct ldb_message **res, *t;
548 /* pull the template record */
549 ret = samdb_search(ctx, mem_ctx, NULL, &res, NULL, "%s", expression);
551 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
557 for (i=0;i<t->num_elements;i++) {
558 struct ldb_message_element *el = &t->elements[i];
559 /* some elements should not be copied from the template */
560 if (strcasecmp(el->name, "cn") == 0 ||
561 strcasecmp(el->name, "name") == 0 ||
562 strcasecmp(el->name, "sAMAccountName") == 0) {
565 for (j=0;j<el->num_values;j++) {
566 if (strcasecmp(el->name, "objectClass") == 0 &&
567 (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
568 strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
569 strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
570 strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0)) {
573 samdb_msg_add_string(ctx, mem_ctx, msg, el->name,
574 (char *)el->values[j].data);
583 allocate a new id, attempting to do it atomically
584 return 0 on failure, the id on success
586 static NTSTATUS _samdb_allocate_next_id(void *ctx, TALLOC_CTX *mem_ctx, const char *dn,
587 const char *attr, uint32_t *id)
589 struct ldb_wrap *sam_ctx = ctx;
590 struct ldb_message msg;
593 struct ldb_val vals[2];
594 struct ldb_message_element els[2];
596 str = samdb_search_string(ctx, mem_ctx, NULL, attr, "dn=%s", dn);
598 DEBUG(1,("id not found at %s %s\n", dn, attr));
599 return NT_STATUS_OBJECT_NAME_INVALID;
602 *id = strtol(str, NULL, 0);
605 return NT_STATUS_INSUFFICIENT_RESOURCES;
608 /* we do a delete and add as a single operation. That prevents
611 msg.dn = talloc_strdup(mem_ctx, dn);
613 return NT_STATUS_NO_MEMORY;
615 msg.num_elements = 2;
618 els[0].num_values = 1;
619 els[0].values = &vals[0];
620 els[0].flags = LDB_FLAG_MOD_DELETE;
621 els[0].name = talloc_strdup(mem_ctx, attr);
623 return NT_STATUS_NO_MEMORY;
626 els[1].num_values = 1;
627 els[1].values = &vals[1];
628 els[1].flags = LDB_FLAG_MOD_ADD;
629 els[1].name = els[0].name;
631 vals[0].data = talloc_asprintf(mem_ctx, "%u", *id);
633 return NT_STATUS_NO_MEMORY;
635 vals[0].length = strlen(vals[0].data);
637 vals[1].data = talloc_asprintf(mem_ctx, "%u", (*id)+1);
639 return NT_STATUS_NO_MEMORY;
641 vals[1].length = strlen(vals[1].data);
643 ret = ldb_modify(sam_ctx->ldb, &msg);
645 return NT_STATUS_UNEXPECTED_IO_ERROR;
654 allocate a new id, attempting to do it atomically
655 return 0 on failure, the id on success
657 NTSTATUS samdb_allocate_next_id(void *ctx, TALLOC_CTX *mem_ctx, const char *dn, const char *attr,
663 /* we need to try multiple times to cope with two account
664 creations at the same time */
666 status = _samdb_allocate_next_id(ctx, mem_ctx, dn, attr, id);
667 if (!NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
672 if (NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
673 DEBUG(1,("Failed to increment id %s at %s\n", attr, dn));
681 add a string element to a message
683 int samdb_msg_add_string(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
684 const char *attr_name, const char *str)
686 struct ldb_wrap *sam_ctx = ctx;
687 char *s = talloc_strdup(mem_ctx, str);
688 char *a = talloc_strdup(mem_ctx, attr_name);
689 if (s == NULL || a == NULL) {
692 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
693 return ldb_msg_add_string(sam_ctx->ldb, msg, a, s);
697 add a delete element operation to a message
699 int samdb_msg_add_delete(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
700 const char *attr_name)
702 struct ldb_wrap *sam_ctx = ctx;
703 char *a = talloc_strdup(mem_ctx, attr_name);
707 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
708 /* we use an empty replace rather than a delete, as it allows for
709 samdb_replace() to be used everywhere */
710 return ldb_msg_add_empty(sam_ctx->ldb, msg, a, LDB_FLAG_MOD_REPLACE);
714 add a add attribute value to a message
716 int samdb_msg_add_addval(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
717 const char *attr_name, const char *value)
719 struct ldb_wrap *sam_ctx = ctx;
720 struct ldb_message_element *el;
723 a = talloc_strdup(mem_ctx, attr_name);
726 v = talloc_strdup(mem_ctx, value);
729 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
730 ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v);
733 el = ldb_msg_find_element(msg, a);
736 el->flags = LDB_FLAG_MOD_ADD;
741 add a delete attribute value to a message
743 int samdb_msg_add_delval(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
744 const char *attr_name, const char *value)
746 struct ldb_wrap *sam_ctx = ctx;
747 struct ldb_message_element *el;
750 a = talloc_strdup(mem_ctx, attr_name);
753 v = talloc_strdup(mem_ctx, value);
756 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
757 ret = ldb_msg_add_string(sam_ctx->ldb, msg, a, v);
760 el = ldb_msg_find_element(msg, a);
763 el->flags = LDB_FLAG_MOD_DELETE;
768 add a uint_t element to a message
770 int samdb_msg_add_uint(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
771 const char *attr_name, uint_t v)
773 const char *s = talloc_asprintf(mem_ctx, "%u", v);
774 return samdb_msg_add_string(ctx, mem_ctx, msg, attr_name, s);
778 add a (signed) int64_t element to a message
780 int samdb_msg_add_int64(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
781 const char *attr_name, int64_t v)
783 const char *s = talloc_asprintf(mem_ctx, "%lld", v);
784 return samdb_msg_add_string(ctx, mem_ctx, msg, attr_name, s);
788 add a uint64_t element to a message
790 int samdb_msg_add_uint64(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
791 const char *attr_name, uint64_t v)
793 const char *s = talloc_asprintf(mem_ctx, "%llu", v);
794 return samdb_msg_add_string(ctx, mem_ctx, msg, attr_name, s);
798 add a samr_Password element to a message
800 int samdb_msg_add_hash(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
801 const char *attr_name, struct samr_Password hash)
803 struct ldb_wrap *sam_ctx = ctx;
805 val.data = talloc(mem_ctx, 16);
810 memcpy(val.data, hash.hash, 16);
811 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
812 return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
816 add a samr_Password array to a message
818 int samdb_msg_add_hashes(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
819 const char *attr_name, struct samr_Password *hashes, uint_t count)
821 struct ldb_wrap *sam_ctx = ctx;
824 val.data = talloc(mem_ctx, count*16);
825 val.length = count*16;
829 for (i=0;i<count;i++) {
830 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
832 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
833 return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
837 add a acct_flags element to a message
839 int samdb_msg_add_acct_flags(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
840 const char *attr_name, uint32_t v)
842 return samdb_msg_add_uint(ctx, mem_ctx, msg, attr_name, samdb_acb2uf(v));
846 add a logon_hours element to a message
848 int samdb_msg_add_logon_hours(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
849 const char *attr_name, struct samr_LogonHours *hours)
851 struct ldb_wrap *sam_ctx = ctx;
853 val.length = hours->units_per_week / 8;
854 val.data = hours->bitmap;
855 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
856 return ldb_msg_add_value(sam_ctx->ldb, msg, attr_name, &val);
860 set a string element in a message
862 int samdb_msg_set_string(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
863 const char *attr_name, const char *str)
865 struct ldb_wrap *sam_ctx = ctx;
866 struct ldb_message_element *el;
868 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
870 el = ldb_msg_find_element(msg, attr_name);
874 return samdb_msg_add_string(ctx, mem_ctx, msg, attr_name, str);
878 set a ldaptime element in a message
880 int samdb_msg_set_ldaptime(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
881 const char *attr_name, time_t t)
883 char *str = ldap_timestring(mem_ctx, t);
887 return samdb_msg_set_string(ctx, mem_ctx, msg, attr_name, str);
893 int samdb_add(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
895 struct ldb_wrap *sam_ctx = ctx;
897 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
898 return ldb_add(sam_ctx->ldb, msg);
904 int samdb_delete(void *ctx, TALLOC_CTX *mem_ctx, const char *dn)
906 struct ldb_wrap *sam_ctx = ctx;
908 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
909 return ldb_delete(sam_ctx->ldb, dn);
915 int samdb_modify(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
917 struct ldb_wrap *sam_ctx = ctx;
919 ldb_set_alloc(sam_ctx->ldb, talloc_realloc_fn, mem_ctx);
920 return ldb_modify(sam_ctx->ldb, msg);
924 replace elements in a record
926 int samdb_replace(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
930 /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
931 for (i=0;i<msg->num_elements;i++) {
932 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
935 /* modify the samdb record */
936 return samdb_modify(ctx, mem_ctx, msg);
940 return a default security descriptor
942 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
944 struct security_descriptor *sd;
946 sd = security_descriptor_initialise(mem_ctx);