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"
26 #include "system/time.h"
27 #include "system/filesys.h"
31 connect to the SAM database
32 return an opaque context pointer on success, or NULL on failure
34 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx)
36 return ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL);
40 search the sam for the specified attributes in a specific domain, filter on
41 objectSid being in domain_sid.
43 int samdb_search_domain(struct ldb_context *sam_ldb,
46 struct ldb_message ***res,
47 const char * const *attrs,
48 const struct dom_sid *domain_sid,
49 const char *format, ...) _PRINTF_ATTRIBUTE(7,8)
55 count = gendb_search_v(sam_ldb, mem_ctx, basedn,
56 res, attrs, format, ap);
62 struct dom_sid *entry_sid;
64 entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
66 if ((entry_sid == NULL) ||
67 (!dom_sid_in_domain(domain_sid, entry_sid))) {
68 /* Delete that entry from the result set */
69 (*res)[i] = (*res)[count-1];
71 talloc_free(entry_sid);
74 talloc_free(entry_sid);
82 search the sam for a single string attribute in exactly 1 record
84 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
87 const char *attr_name,
88 const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
91 const char *attrs[2] = { NULL, NULL };
92 struct ldb_message **res = NULL;
96 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
98 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
99 attr_name, format, count));
106 return samdb_result_string(res[0], attr_name, NULL);
111 search the sam for a single string attribute in exactly 1 record
113 const char *samdb_search_string(struct ldb_context *sam_ldb,
116 const char *attr_name,
117 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
122 va_start(ap, format);
123 str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
130 search the sam for a dom_sid attribute in exactly 1 record
132 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
135 const char *attr_name,
136 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
140 struct ldb_message **res;
141 const char *attrs[2] = { NULL, NULL };
144 attrs[0] = attr_name;
146 va_start(ap, format);
147 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
150 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
151 attr_name, format, count));
157 sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
163 return the count of the number of records in the sam matching the query
165 int samdb_search_count(struct ldb_context *sam_ldb,
168 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
171 struct ldb_message **res;
172 const char * const attrs[] = { NULL };
175 va_start(ap, format);
176 ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
184 search the sam for a single integer attribute in exactly 1 record
186 uint_t samdb_search_uint(struct ldb_context *sam_ldb,
188 uint_t default_value,
190 const char *attr_name,
191 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
195 struct ldb_message **res;
196 const char *attrs[2] = { NULL, NULL };
198 attrs[0] = attr_name;
200 va_start(ap, format);
201 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
205 return default_value;
208 return samdb_result_uint(res[0], attr_name, default_value);
212 search the sam for a single signed 64 bit integer attribute in exactly 1 record
214 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
216 int64_t default_value,
218 const char *attr_name,
219 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
223 struct ldb_message **res;
224 const char *attrs[2] = { NULL, NULL };
226 attrs[0] = attr_name;
228 va_start(ap, format);
229 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
233 return default_value;
236 return samdb_result_int64(res[0], attr_name, default_value);
240 search the sam for multipe records each giving a single string attribute
241 return the number of matches, or -1 on error
243 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
247 const char *attr_name,
248 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
252 const char *attrs[2] = { NULL, NULL };
253 struct ldb_message **res = NULL;
255 attrs[0] = attr_name;
257 va_start(ap, format);
258 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
265 /* make sure its single valued */
266 for (i=0;i<count;i++) {
267 if (res[i]->num_elements != 1) {
268 DEBUG(1,("samdb: search for %s %s not single valued\n",
275 *strs = talloc_array(mem_ctx, const char *, count+1);
281 for (i=0;i<count;i++) {
282 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
284 (*strs)[count] = NULL;
290 pull a uint from a result set.
292 uint_t samdb_result_uint(struct ldb_message *msg, const char *attr, uint_t default_value)
294 return ldb_msg_find_uint(msg, attr, default_value);
298 pull a (signed) int64 from a result set.
300 int64_t samdb_result_int64(struct ldb_message *msg, const char *attr, int64_t default_value)
302 return ldb_msg_find_int64(msg, attr, default_value);
306 pull a string from a result set.
308 const char *samdb_result_string(struct ldb_message *msg, const char *attr,
309 const char *default_value)
311 return ldb_msg_find_string(msg, attr, default_value);
315 pull a rid from a objectSid in a result set.
317 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
318 const char *attr, uint32_t default_value)
323 sid = samdb_result_dom_sid(mem_ctx, msg, attr);
325 return default_value;
327 rid = sid->sub_auths[sid->num_auths-1];
333 pull a dom_sid structure from a objectSid in a result set.
335 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
338 const struct ldb_val *v;
341 v = ldb_msg_find_ldb_val(msg, attr);
345 sid = talloc(mem_ctx, struct dom_sid);
349 status = ndr_pull_struct_blob(v, sid, sid,
350 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
351 if (!NT_STATUS_IS_OK(status)) {
359 pull a guid structure from a objectGUID in a result set.
361 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
363 const struct ldb_val *v;
370 v = ldb_msg_find_ldb_val(msg, attr);
373 mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
374 if (!mem_ctx) return guid;
375 status = ndr_pull_struct_blob(v, mem_ctx, &guid,
376 (ndr_pull_flags_fn_t)ndr_pull_GUID);
377 talloc_free(mem_ctx);
378 if (!NT_STATUS_IS_OK(status)) {
386 pull a sid prefix from a objectSid in a result set.
387 this is used to find the domain sid for a user
389 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
392 struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
393 if (!sid || sid->num_auths < 1) return NULL;
399 pull a NTTIME in a result set.
401 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, const char *default_value)
403 const char *str = ldb_msg_find_string(msg, attr, default_value);
404 return nttime_from_string(str);
408 pull a uint64_t from a result set.
410 uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
412 return ldb_msg_find_uint64(msg, attr, default_value);
417 construct the allow_password_change field from the PwdLastSet attribute and the
418 domain password settings
420 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
422 const char *domain_dn,
423 struct ldb_message *msg,
426 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
429 if (attr_time == 0) {
433 minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0,
434 domain_dn, "minPwdAge", "dn=%s", domain_dn);
436 /* yes, this is a -= not a += as minPwdAge is stored as the negative
437 of the number of 100-nano-seconds */
438 attr_time -= minPwdAge;
444 construct the force_password_change field from the PwdLastSet attribute and the
445 domain password settings
447 NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
449 const char *domain_dn,
450 struct ldb_message *msg,
453 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
456 if (attr_time == 0) {
460 maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn,
461 "maxPwdAge", "dn=%s", domain_dn);
462 if (maxPwdAge == 0) {
465 attr_time -= maxPwdAge;
472 pull a samr_Password structutre from a result set.
474 struct samr_Password samdb_result_hash(struct ldb_message *msg, const char *attr)
476 struct samr_Password hash;
477 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
480 memcpy(hash.hash, val->data, MIN(val->length, sizeof(hash.hash)));
486 pull an array of samr_Password structutres from a result set.
488 uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
489 const char *attr, struct samr_Password **hashes)
492 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
499 count = val->length / 16;
504 *hashes = talloc_array(mem_ctx, struct samr_Password, count);
509 for (i=0;i<count;i++) {
510 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
516 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
517 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
520 const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL);
522 struct samr_Password *lmPwdHash, *ntPwdHash;
525 ntPwdHash = talloc(mem_ctx, struct samr_Password);
527 return NT_STATUS_NO_MEMORY;
530 E_md4hash(unicodePwd, ntPwdHash->hash);
537 lmPwdHash = talloc(mem_ctx, struct samr_Password);
539 return NT_STATUS_NO_MEMORY;
542 /* compute the new nt and lm hashes */
543 lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash);
554 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
557 } else if (num_nt > 1) {
558 return NT_STATUS_INTERNAL_DB_CORRUPTION;
560 *nt_pwd = &ntPwdHash[0];
565 num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
568 } else if (num_lm > 1) {
569 return NT_STATUS_INTERNAL_DB_CORRUPTION;
571 *lm_pwd = &lmPwdHash[0];
580 pull a samr_LogonHours structutre from a result set.
582 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
584 struct samr_LogonHours hours;
585 const int units_per_week = 168;
586 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
588 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
592 hours.units_per_week = units_per_week;
593 memset(hours.bits, 0xFF, units_per_week);
595 memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
601 pull a set of account_flags from a result set.
603 uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
605 uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
606 return samdb_uf2acb(userAccountControl);
610 copy from a template record to a message
612 int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
613 struct ldb_message *msg, const char *expression)
615 struct ldb_message **res, *t;
619 /* pull the template record */
620 ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
622 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
628 for (i=0;i<t->num_elements;i++) {
629 struct ldb_message_element *el = &t->elements[i];
630 /* some elements should not be copied from the template */
631 if (strcasecmp(el->name, "cn") == 0 ||
632 strcasecmp(el->name, "name") == 0 ||
633 strcasecmp(el->name, "sAMAccountName") == 0) {
636 for (j=0;j<el->num_values;j++) {
637 if (strcasecmp(el->name, "objectClass") == 0 &&
638 (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
639 strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
640 strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
641 strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
642 strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
643 strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
644 strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
647 samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
648 (char *)el->values[j].data);
657 allocate a new id, attempting to do it atomically
658 return 0 on failure, the id on success
660 static NTSTATUS _samdb_allocate_next_id(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn,
661 const char *attr, uint32_t *id)
663 struct ldb_message msg;
666 struct ldb_val vals[2];
667 struct ldb_message_element els[2];
669 str = samdb_search_string(sam_ldb, mem_ctx, dn, attr, "dn=%s", dn);
671 DEBUG(1,("id not found at %s %s\n", dn, attr));
672 return NT_STATUS_OBJECT_NAME_INVALID;
675 *id = strtol(str, NULL, 0);
678 return NT_STATUS_INSUFFICIENT_RESOURCES;
681 /* we do a delete and add as a single operation. That prevents
684 msg.dn = talloc_strdup(mem_ctx, dn);
686 return NT_STATUS_NO_MEMORY;
688 msg.num_elements = 2;
691 els[0].num_values = 1;
692 els[0].values = &vals[0];
693 els[0].flags = LDB_FLAG_MOD_DELETE;
694 els[0].name = talloc_strdup(mem_ctx, attr);
696 return NT_STATUS_NO_MEMORY;
699 els[1].num_values = 1;
700 els[1].values = &vals[1];
701 els[1].flags = LDB_FLAG_MOD_ADD;
702 els[1].name = els[0].name;
704 vals[0].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", *id);
706 return NT_STATUS_NO_MEMORY;
708 vals[0].length = strlen((const char *)vals[0].data);
710 vals[1].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", (*id)+1);
712 return NT_STATUS_NO_MEMORY;
714 vals[1].length = strlen((const char *)vals[1].data);
716 ret = ldb_modify(sam_ldb, &msg);
718 return NT_STATUS_UNEXPECTED_IO_ERROR;
727 allocate a new id, attempting to do it atomically
728 return 0 on failure, the id on success
730 NTSTATUS samdb_allocate_next_id(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn, const char *attr,
736 /* we need to try multiple times to cope with two account
737 creations at the same time */
739 status = _samdb_allocate_next_id(sam_ldb, mem_ctx, dn, attr, id);
740 if (!NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
745 if (NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
746 DEBUG(1,("Failed to increment id %s at %s\n", attr, dn));
754 add a string element to a message
756 int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
757 const char *attr_name, const char *str)
759 char *s = talloc_strdup(mem_ctx, str);
760 char *a = talloc_strdup(mem_ctx, attr_name);
761 if (s == NULL || a == NULL) {
764 return ldb_msg_add_string(sam_ldb, msg, a, s);
768 add a dom_sid element to a message
770 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
771 const char *attr_name, struct dom_sid *sid)
775 status = ndr_push_struct_blob(&v, mem_ctx, sid,
776 (ndr_push_flags_fn_t)ndr_push_dom_sid);
777 if (!NT_STATUS_IS_OK(status)) {
780 return ldb_msg_add_value(sam_ldb, msg, attr_name, &v);
785 add a delete element operation to a message
787 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
788 const char *attr_name)
790 char *a = talloc_strdup(mem_ctx, attr_name);
794 /* we use an empty replace rather than a delete, as it allows for
795 samdb_replace() to be used everywhere */
796 return ldb_msg_add_empty(sam_ldb, msg, a, LDB_FLAG_MOD_REPLACE);
800 add a add attribute value to a message
802 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
803 const char *attr_name, const char *value)
805 struct ldb_message_element *el;
808 a = talloc_strdup(mem_ctx, attr_name);
811 v = talloc_strdup(mem_ctx, value);
814 ret = ldb_msg_add_string(sam_ldb, msg, a, v);
817 el = ldb_msg_find_element(msg, a);
820 el->flags = LDB_FLAG_MOD_ADD;
825 add a delete attribute value to a message
827 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
828 const char *attr_name, const char *value)
830 struct ldb_message_element *el;
833 a = talloc_strdup(mem_ctx, attr_name);
836 v = talloc_strdup(mem_ctx, value);
839 ret = ldb_msg_add_string(sam_ldb, msg, a, v);
842 el = ldb_msg_find_element(msg, a);
845 el->flags = LDB_FLAG_MOD_DELETE;
850 add a uint_t element to a message
852 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
853 const char *attr_name, uint_t v)
855 const char *s = talloc_asprintf(mem_ctx, "%u", v);
856 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
860 add a (signed) int64_t element to a message
862 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
863 const char *attr_name, int64_t v)
865 const char *s = talloc_asprintf(mem_ctx, "%lld", v);
866 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
870 add a uint64_t element to a message
872 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
873 const char *attr_name, uint64_t v)
875 const char *s = talloc_asprintf(mem_ctx, "%llu", v);
876 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
880 add a samr_Password element to a message
882 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
883 const char *attr_name, struct samr_Password *hash)
886 val.data = talloc_memdup(mem_ctx, hash->hash, 16);
891 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
895 add a samr_Password array to a message
897 int samdb_msg_add_hashes(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
898 const char *attr_name, struct samr_Password *hashes, uint_t count)
902 val.data = talloc_array_size(mem_ctx, 16, count);
903 val.length = count*16;
907 for (i=0;i<count;i++) {
908 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
910 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
914 add a acct_flags element to a message
916 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
917 const char *attr_name, uint32_t v)
919 return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
923 add a logon_hours element to a message
925 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
926 const char *attr_name, struct samr_LogonHours *hours)
929 val.length = hours->units_per_week / 8;
930 val.data = hours->bits;
931 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
935 add a general value element to a message
937 int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
938 const char *attr_name, const struct ldb_val *val)
940 return ldb_msg_add_value(sam_ldb, msg, attr_name, val);
944 sets a general value element to a message
946 int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
947 const char *attr_name, const struct ldb_val *val)
949 struct ldb_message_element *el;
951 el = ldb_msg_find_element(msg, attr_name);
955 return ldb_msg_add_value(sam_ldb, msg, attr_name, val);
959 set a string element in a message
961 int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
962 const char *attr_name, const char *str)
964 struct ldb_message_element *el;
966 el = ldb_msg_find_element(msg, attr_name);
970 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
974 set a ldaptime element in a message
976 int samdb_msg_set_ldaptime(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
977 const char *attr_name, time_t t)
979 char *str = ldap_timestring(mem_ctx, t);
983 return samdb_msg_set_string(sam_ldb, mem_ctx, msg, attr_name, str);
989 int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
991 return ldb_add(sam_ldb, msg);
997 int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn)
999 return ldb_delete(sam_ldb, dn);
1005 int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
1007 return ldb_modify(sam_ldb, msg);
1011 replace elements in a record
1013 int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
1017 /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
1018 for (i=0;i<msg->num_elements;i++) {
1019 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1022 /* modify the samdb record */
1023 return samdb_modify(sam_ldb, mem_ctx, msg);
1027 return a default security descriptor
1029 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1031 struct security_descriptor *sd;
1033 sd = security_descriptor_initialise(mem_ctx);