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 * 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
);
96 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
97 attr_name
, format
, count
));
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
,
114 const char *attr_name
,
115 const char *format
, ...) _PRINTF_ATTRIBUTE(5,6)
120 va_start(ap
, format
);
121 str
= samdb_search_string_v(sam_ldb
, mem_ctx
, basedn
, attr_name
, format
, ap
);
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
,
133 const char *attr_name
,
134 const char *format
, ...) _PRINTF_ATTRIBUTE(5,6)
138 struct ldb_message
**res
;
139 const char * const attrs
[2] = { attr_name
, NULL
};
142 va_start(ap
, format
);
143 count
= gendb_search_v(sam_ldb
, mem_ctx
, basedn
, &res
, attrs
, format
, ap
);
146 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n",
147 attr_name
, format
, count
));
153 sid
= samdb_result_dom_sid(mem_ctx
, res
[0], attr_name
);
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
,
164 const char *format
, ...) _PRINTF_ATTRIBUTE(4,5)
167 struct ldb_message
**res
;
168 const char * const attrs
[] = { NULL
};
171 va_start(ap
, format
);
172 ret
= gendb_search_v(sam_ldb
, mem_ctx
, basedn
, &res
, attrs
, format
, ap
);
180 search the sam for a single integer attribute in exactly 1 record
182 uint_t
samdb_search_uint(struct ldb_context
*sam_ldb
,
184 uint_t default_value
,
186 const char *attr_name
,
187 const char *format
, ...) _PRINTF_ATTRIBUTE(6,7)
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
);
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
,
210 int64_t default_value
,
212 const char *attr_name
,
213 const char *format
, ...) _PRINTF_ATTRIBUTE(6,7)
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
);
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
,
239 const char *attr_name
,
240 const char *format
, ...) _PRINTF_ATTRIBUTE(6,7)
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
);
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",
265 *strs
= talloc_array(mem_ctx
, const char *, count
+1);
271 for (i
=0;i
<count
;i
++) {
272 (*strs
)[i
] = samdb_result_string(res
[i
], attr_name
, NULL
);
274 (*strs
)[count
] = NULL
;
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
)
313 sid
= samdb_result_dom_sid(mem_ctx
, msg
, attr
);
315 return default_value
;
317 rid
= sid
->sub_auths
[sid
->num_auths
-1];
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
,
328 const struct ldb_val
*v
;
331 v
= ldb_msg_find_ldb_val(msg
, attr
);
335 sid
= talloc(mem_ctx
, struct dom_sid
);
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
)) {
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
;
360 v
= ldb_msg_find_ldb_val(msg
, attr
);
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
)) {
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
,
382 struct dom_sid
*sid
= samdb_result_dom_sid(mem_ctx
, msg
, attr
);
383 if (!sid
|| sid
->num_auths
< 1) return NULL
;
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
,
412 const char *domain_dn
,
413 struct ldb_message
*msg
,
416 uint64_t attr_time
= samdb_result_uint64(msg
, attr
, 0);
419 if (attr_time
== 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
;
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
,
439 const char *domain_dn
,
440 struct ldb_message
*msg
,
443 uint64_t attr_time
= samdb_result_uint64(msg
, attr
, 0);
446 if (attr_time
== 0) {
450 maxPwdAge
= samdb_search_int64(sam_ldb
, mem_ctx
, 0, domain_dn
, "maxPwdAge", NULL
);
451 if (maxPwdAge
== 0) {
454 attr_time
-= maxPwdAge
;
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
);
469 memcpy(hash
.hash
, val
->data
, MIN(val
->length
, sizeof(hash
.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
)
481 const struct ldb_val
*val
= ldb_msg_find_ldb_val(msg
, attr
);
488 count
= val
->length
/ 16;
493 *hashes
= talloc_array(mem_ctx
, struct samr_Password
, count
);
498 for (i
=0;i
<count
;i
++) {
499 memcpy((*hashes
)[i
].hash
, (i
*16)+(char *)val
->data
, 16);
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
;
514 ntPwdHash
= talloc(mem_ctx
, struct samr_Password
);
516 return NT_STATUS_NO_MEMORY
;
519 E_md4hash(unicodePwd
, ntPwdHash
->hash
);
526 lmPwdHash
= talloc(mem_ctx
, struct samr_Password
);
528 return NT_STATUS_NO_MEMORY
;
531 /* compute the new nt and lm hashes */
532 lm_hash_ok
= E_deshash(unicodePwd
, lmPwdHash
->hash
);
543 num_nt
= samdb_result_hashes(mem_ctx
, msg
, "ntPwdHash", &ntPwdHash
);
546 } else if (num_nt
> 1) {
547 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
549 *nt_pwd
= &ntPwdHash
[0];
554 num_lm
= samdb_result_hashes(mem_ctx
, msg
, "lmPwdHash", &lmPwdHash
);
557 } else if (num_lm
> 1) {
558 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
560 *lm_pwd
= &lmPwdHash
[0];
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
);
577 hours
.bits
= talloc_array(mem_ctx
, uint8_t, units_per_week
);
581 hours
.units_per_week
= units_per_week
;
582 memset(hours
.bits
, 0xFF, units_per_week
);
584 memcpy(hours
.bits
, val
->data
, MIN(val
->length
, units_per_week
));
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
;
608 /* pull the template record */
609 ret
= gendb_search(sam_ldb
, mem_ctx
, NULL
, &res
, NULL
, "%s", expression
);
611 DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
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) {
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)) {
636 samdb_msg_add_string(sam_ldb
, mem_ctx
, msg
, el
->name
,
637 (char *)el
->values
[j
].data
);
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
;
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
);
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);
667 return NT_STATUS_INSUFFICIENT_RESOURCES
;
670 /* we do a delete and add as a single operation. That prevents
673 msg
.dn
= talloc_strdup(mem_ctx
, dn
);
675 return NT_STATUS_NO_MEMORY
;
677 msg
.num_elements
= 2;
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
);
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
);
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);
701 return NT_STATUS_NO_MEMORY
;
703 vals
[1].length
= strlen((const char *)vals
[1].data
);
705 ret
= ldb_modify(sam_ldb
, &msg
);
707 return NT_STATUS_UNEXPECTED_IO_ERROR
;
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
,
725 /* we need to try multiple times to cope with two account
726 creations at the same time */
728 status
= _samdb_allocate_next_id(sam_ldb
, mem_ctx
, dn
, attr
, id
);
729 if (!NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR
, status
)) {
734 if (NT_STATUS_EQUAL(NT_STATUS_UNEXPECTED_IO_ERROR
, status
)) {
735 DEBUG(1,("Failed to increment id %s at %s\n", attr
, dn
));
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
) {
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
)
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
)) {
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
);
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
;
797 a
= talloc_strdup(mem_ctx
, attr_name
);
800 v
= talloc_strdup(mem_ctx
, value
);
803 ret
= ldb_msg_add_string(sam_ldb
, msg
, a
, v
);
806 el
= ldb_msg_find_element(msg
, a
);
809 el
->flags
= LDB_FLAG_MOD_ADD
;
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
;
822 a
= talloc_strdup(mem_ctx
, attr_name
);
825 v
= talloc_strdup(mem_ctx
, value
);
828 ret
= ldb_msg_add_string(sam_ldb
, msg
, a
, v
);
831 el
= ldb_msg_find_element(msg
, a
);
834 el
->flags
= LDB_FLAG_MOD_DELETE
;
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
)
875 val
.data
= talloc_memdup(mem_ctx
, hash
->hash
, 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
)
891 val
.data
= talloc_array_size(mem_ctx
, 16, count
);
892 val
.length
= count
*16;
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
)
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
);
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
);
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
);
972 return samdb_msg_set_string(sam_ldb
, mem_ctx
, msg
, attr_name
, str
);
978 int samdb_add(struct ldb_context
*sam_ldb
, TALLOC_CTX
*mem_ctx
, struct ldb_message
*msg
)
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
)) {
991 ret
= ldb_msg_add_value(sam_ldb
, msg
, "objectGUID", &v
);
992 if (ret
!= 0) return ret
;
994 return ldb_add(sam_ldb
, msg
);
1000 int samdb_delete(struct ldb_context
*sam_ldb
, TALLOC_CTX
*mem_ctx
, const char *dn
)
1002 return ldb_delete(sam_ldb
, dn
);
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
)
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
);