r8224: - add objectGUID ldif_handler
[Samba/aatanasov.git] / source4 / dsdb / samdb / samdb.c
blobf51d3c6102f66d4f794f6ffdf276f93395be6dae
1 /*
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.
23 #include "includes.h"
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"
28 #include "db_wrap.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,
44 TALLOC_CTX *mem_ctx,
45 const char *basedn,
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)
51 va_list ap;
52 int i, count;
54 va_start(ap, format);
55 count = gendb_search_v(sam_ldb, mem_ctx, basedn,
56 res, attrs, format, ap);
57 va_end(ap);
59 i=0;
61 while (i<count) {
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];
70 count -= 1;
71 talloc_free(entry_sid);
72 continue;
74 talloc_free(entry_sid);
75 i += 1;
78 return count;
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,
85 TALLOC_CTX *mem_ctx,
86 const char *basedn,
87 const char *attr_name,
88 const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
90 int count;
91 const char * const attrs[2] = { attr_name, NULL };
92 struct ldb_message **res = NULL;
94 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
95 if (count > 1) {
96 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
97 attr_name, format, count));
99 if (count != 1) {
100 talloc_free(res);
101 return NULL;
104 return samdb_result_string(res[0], attr_name, NULL);
109 search the sam for a single string attribute in exactly 1 record
111 const char *samdb_search_string(struct ldb_context *sam_ldb,
112 TALLOC_CTX *mem_ctx,
113 const char *basedn,
114 const char *attr_name,
115 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
117 va_list ap;
118 const char *str;
120 va_start(ap, format);
121 str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
122 va_end(ap);
124 return str;
128 search the sam for a dom_sid attribute in exactly 1 record
130 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
131 TALLOC_CTX *mem_ctx,
132 const char *basedn,
133 const char *attr_name,
134 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
136 va_list ap;
137 int count;
138 struct ldb_message **res;
139 const char * const attrs[2] = { attr_name, NULL };
140 struct dom_sid *sid;
142 va_start(ap, format);
143 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
144 va_end(ap);
145 if (count > 1) {
146 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
147 attr_name, format, count));
149 if (count != 1) {
150 talloc_free(res);
151 return NULL;
153 sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
154 talloc_free(res);
155 return sid;
159 return the count of the number of records in the sam matching the query
161 int samdb_search_count(struct ldb_context *sam_ldb,
162 TALLOC_CTX *mem_ctx,
163 const char *basedn,
164 const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
166 va_list ap;
167 struct ldb_message **res;
168 const char * const attrs[] = { NULL };
169 int ret;
171 va_start(ap, format);
172 ret = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
173 va_end(ap);
175 return ret;
180 search the sam for a single integer attribute in exactly 1 record
182 uint_t samdb_search_uint(struct ldb_context *sam_ldb,
183 TALLOC_CTX *mem_ctx,
184 uint_t default_value,
185 const char *basedn,
186 const char *attr_name,
187 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
189 va_list ap;
190 int count;
191 struct ldb_message **res;
192 const char * const attrs[2] = { attr_name, NULL };
194 va_start(ap, format);
195 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
196 va_end(ap);
198 if (count != 1) {
199 return default_value;
202 return samdb_result_uint(res[0], attr_name, default_value);
206 search the sam for a single signed 64 bit integer attribute in exactly 1 record
208 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
209 TALLOC_CTX *mem_ctx,
210 int64_t default_value,
211 const char *basedn,
212 const char *attr_name,
213 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
215 va_list ap;
216 int count;
217 struct ldb_message **res;
218 const char * const attrs[2] = { attr_name, NULL };
220 va_start(ap, format);
221 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
222 va_end(ap);
224 if (count != 1) {
225 return default_value;
228 return samdb_result_int64(res[0], attr_name, default_value);
232 search the sam for multipe records each giving a single string attribute
233 return the number of matches, or -1 on error
235 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
236 TALLOC_CTX *mem_ctx,
237 const char *basedn,
238 const char ***strs,
239 const char *attr_name,
240 const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
242 va_list ap;
243 int count, i;
244 const char * const attrs[2] = { attr_name, NULL };
245 struct ldb_message **res = NULL;
247 va_start(ap, format);
248 count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
249 va_end(ap);
251 if (count <= 0) {
252 return count;
255 /* make sure its single valued */
256 for (i=0;i<count;i++) {
257 if (res[i]->num_elements != 1) {
258 DEBUG(1,("samdb: search for %s %s not single valued\n",
259 attr_name, format));
260 talloc_free(res);
261 return -1;
265 *strs = talloc_array(mem_ctx, const char *, count+1);
266 if (! *strs) {
267 talloc_free(res);
268 return -1;
271 for (i=0;i<count;i++) {
272 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
274 (*strs)[count] = NULL;
276 return count;
280 pull a uint from a result set.
282 uint_t samdb_result_uint(struct ldb_message *msg, const char *attr, uint_t default_value)
284 return ldb_msg_find_uint(msg, attr, default_value);
288 pull a (signed) int64 from a result set.
290 int64_t samdb_result_int64(struct ldb_message *msg, const char *attr, int64_t default_value)
292 return ldb_msg_find_int64(msg, attr, default_value);
296 pull a string from a result set.
298 const char *samdb_result_string(struct ldb_message *msg, const char *attr,
299 const char *default_value)
301 return ldb_msg_find_string(msg, attr, default_value);
305 pull a rid from a objectSid in a result set.
307 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
308 const char *attr, uint32_t default_value)
310 struct dom_sid *sid;
311 uint32_t rid;
313 sid = samdb_result_dom_sid(mem_ctx, msg, attr);
314 if (sid == NULL) {
315 return default_value;
317 rid = sid->sub_auths[sid->num_auths-1];
318 talloc_free(sid);
319 return rid;
323 pull a dom_sid structure from a objectSid in a result set.
325 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
326 const char *attr)
328 const struct ldb_val *v;
329 struct dom_sid *sid;
330 NTSTATUS status;
331 v = ldb_msg_find_ldb_val(msg, attr);
332 if (v == NULL) {
333 return NULL;
335 sid = talloc(mem_ctx, struct dom_sid);
336 if (sid == NULL) {
337 return NULL;
339 status = ndr_pull_struct_blob(v, sid, sid,
340 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
341 if (!NT_STATUS_IS_OK(status)) {
342 talloc_free(sid);
343 return NULL;
345 return sid;
349 pull a guid structure from a objectGUID in a result set.
351 struct GUID samdb_result_guid(struct ldb_message *msg, const char *attr)
353 const struct ldb_val *v;
354 NTSTATUS status;
355 struct GUID guid;
356 TALLOC_CTX *mem_ctx;
358 ZERO_STRUCT(guid);
360 v = ldb_msg_find_ldb_val(msg, attr);
361 if (!v) return guid;
363 mem_ctx = talloc_named_const(NULL, 0, "samdb_result_guid");
364 if (!mem_ctx) return guid;
365 status = ndr_pull_struct_blob(v, mem_ctx, &guid,
366 (ndr_pull_flags_fn_t)ndr_pull_GUID);
367 talloc_free(mem_ctx);
368 if (!NT_STATUS_IS_OK(status)) {
369 return guid;
372 return guid;
376 pull a sid prefix from a objectSid in a result set.
377 this is used to find the domain sid for a user
379 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
380 const char *attr)
382 struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
383 if (!sid || sid->num_auths < 1) return NULL;
384 sid->num_auths--;
385 return sid;
389 pull a NTTIME in a result set.
391 NTTIME samdb_result_nttime(struct ldb_message *msg, const char *attr, const char *default_value)
393 const char *str = ldb_msg_find_string(msg, attr, default_value);
394 return nttime_from_string(str);
398 pull a uint64_t from a result set.
400 uint64_t samdb_result_uint64(struct ldb_message *msg, const char *attr, uint64_t default_value)
402 return ldb_msg_find_uint64(msg, attr, default_value);
407 construct the allow_password_change field from the PwdLastSet attribute and the
408 domain password settings
410 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb,
411 TALLOC_CTX *mem_ctx,
412 const char *domain_dn,
413 struct ldb_message *msg,
414 const char *attr)
416 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
417 int64_t minPwdAge;
419 if (attr_time == 0) {
420 return 0;
423 minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0,
424 domain_dn, "minPwdAge", NULL);
426 /* yes, this is a -= not a += as minPwdAge is stored as the negative
427 of the number of 100-nano-seconds */
428 attr_time -= minPwdAge;
430 return attr_time;
434 construct the force_password_change field from the PwdLastSet attribute and the
435 domain password settings
437 NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb,
438 TALLOC_CTX *mem_ctx,
439 const char *domain_dn,
440 struct ldb_message *msg,
441 const char *attr)
443 uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
444 int64_t maxPwdAge;
446 if (attr_time == 0) {
447 return 0;
450 maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
451 if (maxPwdAge == 0) {
452 return 0;
453 } else {
454 attr_time -= maxPwdAge;
457 return attr_time;
461 pull a samr_Password structutre from a result set.
463 struct samr_Password samdb_result_hash(struct ldb_message *msg, const char *attr)
465 struct samr_Password hash;
466 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
467 ZERO_STRUCT(hash);
468 if (val) {
469 memcpy(hash.hash, val->data, MIN(val->length, sizeof(hash.hash)));
471 return hash;
475 pull an array of samr_Password structutres from a result set.
477 uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
478 const char *attr, struct samr_Password **hashes)
480 uint_t count = 0;
481 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
482 int i;
484 *hashes = NULL;
485 if (!val) {
486 return 0;
488 count = val->length / 16;
489 if (count == 0) {
490 return 0;
493 *hashes = talloc_array(mem_ctx, struct samr_Password, count);
494 if (! *hashes) {
495 return 0;
498 for (i=0;i<count;i++) {
499 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
502 return count;
505 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
506 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd)
509 const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL);
511 struct samr_Password *lmPwdHash, *ntPwdHash;
512 if (unicodePwd) {
513 if (nt_pwd) {
514 ntPwdHash = talloc(mem_ctx, struct samr_Password);
515 if (!ntPwdHash) {
516 return NT_STATUS_NO_MEMORY;
519 E_md4hash(unicodePwd, ntPwdHash->hash);
520 *nt_pwd = ntPwdHash;
523 if (lm_pwd) {
524 BOOL lm_hash_ok;
526 lmPwdHash = talloc(mem_ctx, struct samr_Password);
527 if (!lmPwdHash) {
528 return NT_STATUS_NO_MEMORY;
531 /* compute the new nt and lm hashes */
532 lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash);
534 if (lm_hash_ok) {
535 *lm_pwd = lmPwdHash;
536 } else {
537 *lm_pwd = NULL;
540 } else {
541 if (nt_pwd) {
542 int num_nt;
543 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
544 if (num_nt == 0) {
545 *nt_pwd = NULL;
546 } else if (num_nt > 1) {
547 return NT_STATUS_INTERNAL_DB_CORRUPTION;
548 } else {
549 *nt_pwd = &ntPwdHash[0];
552 if (lm_pwd) {
553 int num_lm;
554 num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
555 if (num_lm == 0) {
556 *lm_pwd = NULL;
557 } else if (num_lm > 1) {
558 return NT_STATUS_INTERNAL_DB_CORRUPTION;
559 } else {
560 *lm_pwd = &lmPwdHash[0];
565 return NT_STATUS_OK;
569 pull a samr_LogonHours structutre from a result set.
571 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
573 struct samr_LogonHours hours;
574 const int units_per_week = 168;
575 const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
576 ZERO_STRUCT(hours);
577 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
578 if (!hours.bits) {
579 return hours;
581 hours.units_per_week = units_per_week;
582 memset(hours.bits, 0xFF, units_per_week);
583 if (val) {
584 memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
586 return hours;
590 pull a set of account_flags from a result set.
592 uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
594 uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
595 return samdb_uf2acb(userAccountControl);
599 copy from a template record to a message
601 int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
602 struct ldb_message *msg, const char *expression)
604 struct ldb_message **res, *t;
605 int ret, i, j;
608 /* pull the template record */
609 ret = gendb_search(sam_ldb, mem_ctx, NULL, &res, NULL, "%s", expression);
610 if (ret != 1) {
611 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
612 expression, ret));
613 return -1;
615 t = res[0];
617 for (i=0;i<t->num_elements;i++) {
618 struct ldb_message_element *el = &t->elements[i];
619 /* some elements should not be copied from the template */
620 if (strcasecmp(el->name, "cn") == 0 ||
621 strcasecmp(el->name, "name") == 0 ||
622 strcasecmp(el->name, "sAMAccountName") == 0) {
623 continue;
625 for (j=0;j<el->num_values;j++) {
626 if (strcasecmp(el->name, "objectClass") == 0 &&
627 (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
628 strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
629 strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
630 strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
631 strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 ||
632 strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 ||
633 strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
634 continue;
636 samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
637 (char *)el->values[j].data);
641 return 0;
646 allocate a new id, attempting to do it atomically
647 return 0 on failure, the id on success
649 static NTSTATUS _samdb_allocate_next_id(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn,
650 const char *attr, uint32_t *id)
652 struct ldb_message msg;
653 int ret;
654 const char *str;
655 struct ldb_val vals[2];
656 struct ldb_message_element els[2];
658 str = samdb_search_string(sam_ldb, mem_ctx, dn, attr, NULL);
659 if (!str) {
660 DEBUG(1,("id not found at %s %s\n", dn, attr));
661 return NT_STATUS_OBJECT_NAME_INVALID;
664 *id = strtol(str, NULL, 0);
665 if ((*id)+1 == 0) {
666 /* out of IDs ! */
667 return NT_STATUS_INSUFFICIENT_RESOURCES;
670 /* we do a delete and add as a single operation. That prevents
671 a race */
672 ZERO_STRUCT(msg);
673 msg.dn = talloc_strdup(mem_ctx, dn);
674 if (!msg.dn) {
675 return NT_STATUS_NO_MEMORY;
677 msg.num_elements = 2;
678 msg.elements = els;
680 els[0].num_values = 1;
681 els[0].values = &vals[0];
682 els[0].flags = LDB_FLAG_MOD_DELETE;
683 els[0].name = talloc_strdup(mem_ctx, attr);
684 if (!els[0].name) {
685 return NT_STATUS_NO_MEMORY;
688 els[1].num_values = 1;
689 els[1].values = &vals[1];
690 els[1].flags = LDB_FLAG_MOD_ADD;
691 els[1].name = els[0].name;
693 vals[0].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", *id);
694 if (!vals[0].data) {
695 return NT_STATUS_NO_MEMORY;
697 vals[0].length = strlen((const char *)vals[0].data);
699 vals[1].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", (*id)+1);
700 if (!vals[1].data) {
701 return NT_STATUS_NO_MEMORY;
703 vals[1].length = strlen((const char *)vals[1].data);
705 ret = ldb_modify(sam_ldb, &msg);
706 if (ret != 0) {
707 return NT_STATUS_UNEXPECTED_IO_ERROR;
710 (*id)++;
712 return NT_STATUS_OK;
716 allocate a new id, attempting to do it atomically
717 return 0 on failure, the id on success
719 NTSTATUS samdb_allocate_next_id(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn, const char *attr,
720 uint32_t *id)
722 int tries = 10;
723 NTSTATUS status;
725 /* we need to try multiple times to cope with two account
726 creations at the same time */
727 while (tries--) {
728 status = _samdb_allocate_next_id(sam_ldb, mem_ctx, dn, attr, id);
729 if (!NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
730 break;
734 if (NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR, status)) {
735 DEBUG(1,("Failed to increment id %s at %s\n", attr, dn));
738 return status;
743 add a string element to a message
745 int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
746 const char *attr_name, const char *str)
748 char *s = talloc_strdup(mem_ctx, str);
749 char *a = talloc_strdup(mem_ctx, attr_name);
750 if (s == NULL || a == NULL) {
751 return -1;
753 return ldb_msg_add_string(sam_ldb, msg, a, s);
757 add a dom_sid element to a message
759 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
760 const char *attr_name, struct dom_sid *sid)
762 struct ldb_val v;
763 NTSTATUS status;
764 status = ndr_push_struct_blob(&v, mem_ctx, sid,
765 (ndr_push_flags_fn_t)ndr_push_dom_sid);
766 if (!NT_STATUS_IS_OK(status)) {
767 return -1;
769 return ldb_msg_add_value(sam_ldb, msg, attr_name, &v);
774 add a delete element operation to a message
776 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
777 const char *attr_name)
779 char *a = talloc_strdup(mem_ctx, attr_name);
780 if (a == NULL) {
781 return -1;
783 /* we use an empty replace rather than a delete, as it allows for
784 samdb_replace() to be used everywhere */
785 return ldb_msg_add_empty(sam_ldb, msg, a, LDB_FLAG_MOD_REPLACE);
789 add a add attribute value to a message
791 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
792 const char *attr_name, const char *value)
794 struct ldb_message_element *el;
795 char *a, *v;
796 int ret;
797 a = talloc_strdup(mem_ctx, attr_name);
798 if (a == NULL)
799 return -1;
800 v = talloc_strdup(mem_ctx, value);
801 if (v == NULL)
802 return -1;
803 ret = ldb_msg_add_string(sam_ldb, msg, a, v);
804 if (ret != 0)
805 return ret;
806 el = ldb_msg_find_element(msg, a);
807 if (el == NULL)
808 return -1;
809 el->flags = LDB_FLAG_MOD_ADD;
810 return 0;
814 add a delete attribute value to a message
816 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
817 const char *attr_name, const char *value)
819 struct ldb_message_element *el;
820 char *a, *v;
821 int ret;
822 a = talloc_strdup(mem_ctx, attr_name);
823 if (a == NULL)
824 return -1;
825 v = talloc_strdup(mem_ctx, value);
826 if (v == NULL)
827 return -1;
828 ret = ldb_msg_add_string(sam_ldb, msg, a, v);
829 if (ret != 0)
830 return ret;
831 el = ldb_msg_find_element(msg, a);
832 if (el == NULL)
833 return -1;
834 el->flags = LDB_FLAG_MOD_DELETE;
835 return 0;
839 add a uint_t element to a message
841 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
842 const char *attr_name, uint_t v)
844 const char *s = talloc_asprintf(mem_ctx, "%u", v);
845 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
849 add a (signed) int64_t element to a message
851 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
852 const char *attr_name, int64_t v)
854 const char *s = talloc_asprintf(mem_ctx, "%lld", v);
855 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
859 add a uint64_t element to a message
861 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
862 const char *attr_name, uint64_t v)
864 const char *s = talloc_asprintf(mem_ctx, "%llu", v);
865 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
869 add a samr_Password element to a message
871 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
872 const char *attr_name, struct samr_Password *hash)
874 struct ldb_val val;
875 val.data = talloc_memdup(mem_ctx, hash->hash, 16);
876 if (!val.data) {
877 return -1;
879 val.length = 16;
880 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
884 add a samr_Password array to a message
886 int samdb_msg_add_hashes(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
887 const char *attr_name, struct samr_Password *hashes, uint_t count)
889 struct ldb_val val;
890 int i;
891 val.data = talloc_array_size(mem_ctx, 16, count);
892 val.length = count*16;
893 if (!val.data) {
894 return -1;
896 for (i=0;i<count;i++) {
897 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
899 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
903 add a acct_flags element to a message
905 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
906 const char *attr_name, uint32_t v)
908 return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, samdb_acb2uf(v));
912 add a logon_hours element to a message
914 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
915 const char *attr_name, struct samr_LogonHours *hours)
917 struct ldb_val val;
918 val.length = hours->units_per_week / 8;
919 val.data = hours->bits;
920 return ldb_msg_add_value(sam_ldb, msg, attr_name, &val);
924 add a general value element to a message
926 int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
927 const char *attr_name, const struct ldb_val *val)
929 return ldb_msg_add_value(sam_ldb, msg, attr_name, val);
933 sets a general value element to a message
935 int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
936 const char *attr_name, const struct ldb_val *val)
938 struct ldb_message_element *el;
940 el = ldb_msg_find_element(msg, attr_name);
941 if (el) {
942 el->num_values = 0;
944 return ldb_msg_add_value(sam_ldb, msg, attr_name, val);
948 set a string element in a message
950 int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
951 const char *attr_name, const char *str)
953 struct ldb_message_element *el;
955 el = ldb_msg_find_element(msg, attr_name);
956 if (el) {
957 el->num_values = 0;
959 return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
963 set a ldaptime element in a message
965 int samdb_msg_set_ldaptime(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
966 const char *attr_name, time_t t)
968 char *str = ldap_timestring(mem_ctx, t);
969 if (!str) {
970 return -1;
972 return samdb_msg_set_string(sam_ldb, mem_ctx, msg, attr_name, str);
976 add a record
978 int samdb_add(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
980 int ret;
981 struct ldb_val v;
982 NTSTATUS status;
983 struct GUID guid = GUID_random();
985 status = ndr_push_struct_blob(&v, mem_ctx, &guid,
986 (ndr_push_flags_fn_t)ndr_push_GUID);
987 if (!NT_STATUS_IS_OK(status)) {
988 return -1;
991 ret = ldb_msg_add_value(sam_ldb, msg, "objectGUID", &v);
992 if (ret != 0) return ret;
994 return ldb_add(sam_ldb, msg);
998 delete a record
1000 int samdb_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, const char *dn)
1002 return ldb_delete(sam_ldb, dn);
1006 modify a record
1008 int samdb_modify(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
1010 return ldb_modify(sam_ldb, msg);
1014 replace elements in a record
1016 int samdb_replace(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg)
1018 int i;
1020 /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
1021 for (i=0;i<msg->num_elements;i++) {
1022 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1025 /* modify the samdb record */
1026 return samdb_modify(sam_ldb, mem_ctx, msg);
1030 return a default security descriptor
1032 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1034 struct security_descriptor *sd;
1036 sd = security_descriptor_initialise(mem_ctx);
1038 return sd;