b9bff91eb84aaaaa3110b7a59d172ddcb327a9d0
[metze/samba/wip.git] / source4 / dsdb / common / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 2004
6    Copyright (C) Volker Lendecke 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
8    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "events/events.h"
26 #include "ldb.h"
27 #include "ldb_errors.h"
28 #include "../lib/util/util_ldb.h"
29 #include "../lib/crypto/crypto.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "libcli/security/security.h"
32 #include "librpc/gen_ndr/ndr_security.h"
33 #include "librpc/gen_ndr/ndr_misc.h"
34 #include "../libds/common/flags.h"
35 #include "dsdb/common/proto.h"
36 #include "libcli/ldap/ldap_ndr.h"
37 #include "param/param.h"
38 #include "libcli/auth/libcli_auth.h"
39 #include "librpc/gen_ndr/ndr_drsblobs.h"
40 #include "system/locale.h"
41 #include "lib/util/tsort.h"
42 #include "dsdb/common/util.h"
43 #include "lib/socket/socket.h"
44 #include "dsdb/samdb/ldb_modules/util.h"
45
46 /*
47   search the sam for the specified attributes in a specific domain, filter on
48   objectSid being in domain_sid.
49 */
50 int samdb_search_domain(struct ldb_context *sam_ldb,
51                         TALLOC_CTX *mem_ctx, 
52                         struct ldb_dn *basedn,
53                         struct ldb_message ***res,
54                         const char * const *attrs,
55                         const struct dom_sid *domain_sid,
56                         const char *format, ...)  _PRINTF_ATTRIBUTE(7,8)
57 {
58         va_list ap;
59         int i, count;
60
61         va_start(ap, format);
62         count = gendb_search_v(sam_ldb, mem_ctx, basedn,
63                                res, attrs, format, ap);
64         va_end(ap);
65
66         i=0;
67
68         while (i<count) {
69                 struct dom_sid *entry_sid;
70
71                 entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
72
73                 if ((entry_sid == NULL) ||
74                     (!dom_sid_in_domain(domain_sid, entry_sid))) {
75                         /* Delete that entry from the result set */
76                         (*res)[i] = (*res)[count-1];
77                         count -= 1;
78                         talloc_free(entry_sid);
79                         continue;
80                 }
81                 talloc_free(entry_sid);
82                 i += 1;
83         }
84
85         return count;
86 }
87
88 /*
89   search the sam for a single string attribute in exactly 1 record
90 */
91 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
92                                   TALLOC_CTX *mem_ctx,
93                                   struct ldb_dn *basedn,
94                                   const char *attr_name,
95                                   const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
96 {
97         int count;
98         const char *attrs[2] = { NULL, NULL };
99         struct ldb_message **res = NULL;
100
101         attrs[0] = attr_name;
102
103         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
104         if (count > 1) {                
105                 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
106                          attr_name, format, count));
107         }
108         if (count != 1) {
109                 talloc_free(res);
110                 return NULL;
111         }
112
113         return samdb_result_string(res[0], attr_name, NULL);
114 }
115
116 /*
117   search the sam for a single string attribute in exactly 1 record
118 */
119 const char *samdb_search_string(struct ldb_context *sam_ldb,
120                                 TALLOC_CTX *mem_ctx,
121                                 struct ldb_dn *basedn,
122                                 const char *attr_name,
123                                 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
124 {
125         va_list ap;
126         const char *str;
127
128         va_start(ap, format);
129         str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
130         va_end(ap);
131
132         return str;
133 }
134
135 struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
136                                TALLOC_CTX *mem_ctx,
137                                struct ldb_dn *basedn,
138                                const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
139 {
140         va_list ap;
141         struct ldb_dn *ret;
142         struct ldb_message **res = NULL;
143         int count;
144
145         va_start(ap, format);
146         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
147         va_end(ap);
148
149         if (count != 1) return NULL;
150
151         ret = talloc_steal(mem_ctx, res[0]->dn);
152         talloc_free(res);
153
154         return ret;
155 }
156
157 /*
158   search the sam for a dom_sid attribute in exactly 1 record
159 */
160 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
161                                      TALLOC_CTX *mem_ctx,
162                                      struct ldb_dn *basedn,
163                                      const char *attr_name,
164                                      const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
165 {
166         va_list ap;
167         int count;
168         struct ldb_message **res;
169         const char *attrs[2] = { NULL, NULL };
170         struct dom_sid *sid;
171
172         attrs[0] = attr_name;
173
174         va_start(ap, format);
175         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
176         va_end(ap);
177         if (count > 1) {                
178                 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
179                          attr_name, format, count));
180         }
181         if (count != 1) {
182                 talloc_free(res);
183                 return NULL;
184         }
185         sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
186         talloc_free(res);
187         return sid;     
188 }
189
190 /*
191   return the count of the number of records in the sam matching the query
192 */
193 int samdb_search_count(struct ldb_context *sam_ldb,
194                        struct ldb_dn *basedn,
195                        const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
196 {
197         va_list ap;
198         struct ldb_message **res;
199         const char *attrs[] = { NULL };
200         int ret;
201         TALLOC_CTX *tmp_ctx = talloc_new(sam_ldb);
202
203         va_start(ap, format);
204         ret = gendb_search_v(sam_ldb, tmp_ctx, basedn, &res, attrs, format, ap);
205         va_end(ap);
206         talloc_free(tmp_ctx);
207
208         return ret;
209 }
210
211
212 /*
213   search the sam for a single integer attribute in exactly 1 record
214 */
215 unsigned int samdb_search_uint(struct ldb_context *sam_ldb,
216                          TALLOC_CTX *mem_ctx,
217                          unsigned int default_value,
218                          struct ldb_dn *basedn,
219                          const char *attr_name,
220                          const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
221 {
222         va_list ap;
223         int count;
224         struct ldb_message **res;
225         const char *attrs[2] = { NULL, NULL };
226
227         attrs[0] = attr_name;
228
229         va_start(ap, format);
230         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
231         va_end(ap);
232
233         if (count != 1) {
234                 return default_value;
235         }
236
237         return samdb_result_uint(res[0], attr_name, default_value);
238 }
239
240 /*
241   search the sam for a single signed 64 bit integer attribute in exactly 1 record
242 */
243 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
244                            TALLOC_CTX *mem_ctx,
245                            int64_t default_value,
246                            struct ldb_dn *basedn,
247                            const char *attr_name,
248                            const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
249 {
250         va_list ap;
251         int count;
252         struct ldb_message **res;
253         const char *attrs[2] = { NULL, NULL };
254
255         attrs[0] = attr_name;
256
257         va_start(ap, format);
258         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
259         va_end(ap);
260
261         if (count != 1) {
262                 return default_value;
263         }
264
265         return samdb_result_int64(res[0], attr_name, default_value);
266 }
267
268 /*
269   search the sam for multipe records each giving a single string attribute
270   return the number of matches, or -1 on error
271 */
272 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
273                                  TALLOC_CTX *mem_ctx,
274                                  struct ldb_dn *basedn,
275                                  const char ***strs,
276                                  const char *attr_name,
277                                  const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
278 {
279         va_list ap;
280         int count, i;
281         const char *attrs[2] = { NULL, NULL };
282         struct ldb_message **res = NULL;
283
284         attrs[0] = attr_name;
285
286         va_start(ap, format);
287         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
288         va_end(ap);
289
290         if (count <= 0) {
291                 return count;
292         }
293
294         /* make sure its single valued */
295         for (i=0;i<count;i++) {
296                 if (res[i]->num_elements != 1) {
297                         DEBUG(1,("samdb: search for %s %s not single valued\n", 
298                                  attr_name, format));
299                         talloc_free(res);
300                         return -1;
301                 }
302         }
303
304         *strs = talloc_array(mem_ctx, const char *, count+1);
305         if (! *strs) {
306                 talloc_free(res);
307                 return -1;
308         }
309
310         for (i=0;i<count;i++) {
311                 (*strs)[i] = samdb_result_string(res[i], attr_name, NULL);
312         }
313         (*strs)[count] = NULL;
314
315         return count;
316 }
317
318 /*
319   pull a uint from a result set. 
320 */
321 unsigned int samdb_result_uint(const struct ldb_message *msg, const char *attr, unsigned int default_value)
322 {
323         return ldb_msg_find_attr_as_uint(msg, attr, default_value);
324 }
325
326 /*
327   pull a (signed) int64 from a result set. 
328 */
329 int64_t samdb_result_int64(const struct ldb_message *msg, const char *attr, int64_t default_value)
330 {
331         return ldb_msg_find_attr_as_int64(msg, attr, default_value);
332 }
333
334 /*
335   pull a string from a result set. 
336 */
337 const char *samdb_result_string(const struct ldb_message *msg, const char *attr, 
338                                 const char *default_value)
339 {
340         return ldb_msg_find_attr_as_string(msg, attr, default_value);
341 }
342
343 struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
344                                const char *attr, struct ldb_dn *default_value)
345 {
346         struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
347         if (!ret_dn) {
348                 return default_value;
349         }
350         return ret_dn;
351 }
352
353 /*
354   pull a rid from a objectSid in a result set. 
355 */
356 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
357                                    const char *attr, uint32_t default_value)
358 {
359         struct dom_sid *sid;
360         uint32_t rid;
361
362         sid = samdb_result_dom_sid(mem_ctx, msg, attr);
363         if (sid == NULL) {
364                 return default_value;
365         }
366         rid = sid->sub_auths[sid->num_auths-1];
367         talloc_free(sid);
368         return rid;
369 }
370
371 /*
372   pull a dom_sid structure from a objectSid in a result set. 
373 */
374 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
375                                      const char *attr)
376 {
377         const struct ldb_val *v;
378         struct dom_sid *sid;
379         enum ndr_err_code ndr_err;
380         v = ldb_msg_find_ldb_val(msg, attr);
381         if (v == NULL) {
382                 return NULL;
383         }
384         sid = talloc(mem_ctx, struct dom_sid);
385         if (sid == NULL) {
386                 return NULL;
387         }
388         ndr_err = ndr_pull_struct_blob(v, sid, NULL, sid,
389                                        (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
390         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
391                 talloc_free(sid);
392                 return NULL;
393         }
394         return sid;
395 }
396
397 /*
398   pull a guid structure from a objectGUID in a result set. 
399 */
400 struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
401 {
402         const struct ldb_val *v;
403         struct GUID guid;
404         NTSTATUS status;
405
406         v = ldb_msg_find_ldb_val(msg, attr);
407         if (!v) return GUID_zero();
408
409         status = GUID_from_ndr_blob(v, &guid);
410         if (!NT_STATUS_IS_OK(status)) {
411                 return GUID_zero();
412         }
413
414         return guid;
415 }
416
417 /*
418   pull a sid prefix from a objectSid in a result set. 
419   this is used to find the domain sid for a user
420 */
421 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
422                                         const char *attr)
423 {
424         struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
425         if (!sid || sid->num_auths < 1) return NULL;
426         sid->num_auths--;
427         return sid;
428 }
429
430 /*
431   pull a NTTIME in a result set. 
432 */
433 NTTIME samdb_result_nttime(const struct ldb_message *msg, const char *attr,
434                            NTTIME default_value)
435 {
436         return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
437 }
438
439 /*
440  * Windows stores 0 for lastLogoff.
441  * But when a MS DC return the lastLogoff (as Logoff Time)
442  * it returns 0x7FFFFFFFFFFFFFFF, not returning this value in this case
443  * cause windows 2008 and newer version to fail for SMB requests
444  */
445 NTTIME samdb_result_last_logoff(const struct ldb_message *msg)
446 {
447         NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "lastLogoff",0);
448
449         if (ret == 0)
450                 ret = 0x7FFFFFFFFFFFFFFFULL;
451
452         return ret;
453 }
454
455 /*
456  * Windows uses both 0 and 9223372036854775807 (0x7FFFFFFFFFFFFFFFULL) to
457  * indicate an account doesn't expire.
458  *
459  * When Windows initially creates an account, it sets
460  * accountExpires = 9223372036854775807 (0x7FFFFFFFFFFFFFFF).  However,
461  * when changing from an account having a specific expiration date to
462  * that account never expiring, it sets accountExpires = 0.
463  *
464  * Consolidate that logic here to allow clearer logic for account expiry in
465  * the rest of the code.
466  */
467 NTTIME samdb_result_account_expires(const struct ldb_message *msg)
468 {
469         NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "accountExpires",
470                                                  0);
471
472         if (ret == 0)
473                 ret = 0x7FFFFFFFFFFFFFFFULL;
474
475         return ret;
476 }
477
478 /*
479   pull a uint64_t from a result set. 
480 */
481 uint64_t samdb_result_uint64(const struct ldb_message *msg, const char *attr,
482                              uint64_t default_value)
483 {
484         return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
485 }
486
487
488 /*
489   construct the allow_password_change field from the PwdLastSet attribute and the 
490   domain password settings
491 */
492 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb, 
493                                           TALLOC_CTX *mem_ctx, 
494                                           struct ldb_dn *domain_dn, 
495                                           struct ldb_message *msg, 
496                                           const char *attr)
497 {
498         uint64_t attr_time = samdb_result_uint64(msg, attr, 0);
499         int64_t minPwdAge;
500
501         if (attr_time == 0) {
502                 return 0;
503         }
504
505         minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
506
507         /* yes, this is a -= not a += as minPwdAge is stored as the negative
508            of the number of 100-nano-seconds */
509         attr_time -= minPwdAge;
510
511         return attr_time;
512 }
513
514 /*
515   construct the force_password_change field from the PwdLastSet
516   attribute, the userAccountControl and the domain password settings
517 */
518 NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb, 
519                                           TALLOC_CTX *mem_ctx, 
520                                           struct ldb_dn *domain_dn, 
521                                           struct ldb_message *msg)
522 {
523         uint64_t attr_time = samdb_result_uint64(msg, "pwdLastSet", 0);
524         uint32_t userAccountControl = samdb_result_uint64(msg, "userAccountControl", 0);
525         int64_t maxPwdAge;
526
527         /* Machine accounts don't expire, and there is a flag for 'no expiry' */
528         if (!(userAccountControl & UF_NORMAL_ACCOUNT)
529             || (userAccountControl & UF_DONT_EXPIRE_PASSWD)) {
530                 return 0x7FFFFFFFFFFFFFFFULL;
531         }
532
533         if (attr_time == 0) {
534                 return 0;
535         }
536
537         maxPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "maxPwdAge", NULL);
538         if (maxPwdAge == 0) {
539                 return 0x7FFFFFFFFFFFFFFFULL;
540         } else {
541                 attr_time -= maxPwdAge;
542         }
543
544         return attr_time;
545 }
546
547 /*
548   pull a samr_Password structutre from a result set. 
549 */
550 struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, const char *attr)
551 {
552         struct samr_Password *hash = NULL;
553         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
554         if (val && (val->length >= sizeof(hash->hash))) {
555                 hash = talloc(mem_ctx, struct samr_Password);
556                 memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
557         }
558         return hash;
559 }
560
561 /*
562   pull an array of samr_Password structures from a result set.
563 */
564 unsigned int samdb_result_hashes(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
565                            const char *attr, struct samr_Password **hashes)
566 {
567         unsigned int count, i;
568         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
569
570         *hashes = NULL;
571         if (!val) {
572                 return 0;
573         }
574         count = val->length / 16;
575         if (count == 0) {
576                 return 0;
577         }
578
579         *hashes = talloc_array(mem_ctx, struct samr_Password, count);
580         if (! *hashes) {
581                 return 0;
582         }
583
584         for (i=0;i<count;i++) {
585                 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
586         }
587
588         return count;
589 }
590
591 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct ldb_message *msg, 
592                                 struct samr_Password **lm_pwd, struct samr_Password **nt_pwd) 
593 {
594         struct samr_Password *lmPwdHash, *ntPwdHash;
595         if (nt_pwd) {
596                 unsigned int num_nt;
597                 num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
598                 if (num_nt == 0) {
599                         *nt_pwd = NULL;
600                 } else if (num_nt > 1) {
601                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
602                 } else {
603                         *nt_pwd = &ntPwdHash[0];
604                 }
605         }
606         if (lm_pwd) {
607                 /* Ensure that if we have turned off LM
608                  * authentication, that we never use the LM hash, even
609                  * if we store it */
610                 if (lp_lanman_auth(lp_ctx)) {
611                         unsigned int num_lm;
612                         num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
613                         if (num_lm == 0) {
614                                 *lm_pwd = NULL;
615                         } else if (num_lm > 1) {
616                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
617                         } else {
618                                 *lm_pwd = &lmPwdHash[0];
619                         }
620                 } else {
621                         *lm_pwd = NULL;
622                 }
623         }
624         return NT_STATUS_OK;
625 }
626
627 /*
628   pull a samr_LogonHours structutre from a result set. 
629 */
630 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
631 {
632         struct samr_LogonHours hours;
633         const int units_per_week = 168;
634         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
635         ZERO_STRUCT(hours);
636         hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
637         if (!hours.bits) {
638                 return hours;
639         }
640         hours.units_per_week = units_per_week;
641         memset(hours.bits, 0xFF, units_per_week);
642         if (val) {
643                 memcpy(hours.bits, val->data, MIN(val->length, units_per_week));
644         }
645         return hours;
646 }
647
648 /*
649   pull a set of account_flags from a result set. 
650
651   This requires that the attributes: 
652    pwdLastSet
653    userAccountControl
654   be included in 'msg'
655 */
656 uint32_t samdb_result_acct_flags(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 
657                                  struct ldb_message *msg, struct ldb_dn *domain_dn)
658 {
659         uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
660         uint32_t acct_flags = ds_uf2acb(userAccountControl);
661         NTTIME must_change_time;
662         NTTIME now;
663
664         must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
665                                                               domain_dn, msg);
666
667         /* Test account expire time */
668         unix_to_nt_time(&now, time(NULL));
669         /* check for expired password */
670         if (must_change_time < now) {
671                 acct_flags |= ACB_PW_EXPIRED;
672         }
673         return acct_flags;
674 }
675
676 struct lsa_BinaryString samdb_result_parameters(TALLOC_CTX *mem_ctx,
677                                                 struct ldb_message *msg,
678                                                 const char *attr)
679 {
680         struct lsa_BinaryString s;
681         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
682
683         ZERO_STRUCT(s);
684
685         if (!val) {
686                 return s;
687         }
688
689         s.array = talloc_array(mem_ctx, uint16_t, val->length/2);
690         if (!s.array) {
691                 return s;
692         }
693         s.length = s.size = val->length;
694         memcpy(s.array, val->data, val->length);
695
696         return s;
697 }
698
699 /* Find an attribute, with a particular value */
700
701 /* The current callers of this function expect a very specific
702  * behaviour: In particular, objectClass subclass equivilance is not
703  * wanted.  This means that we should not lookup the schema for the
704  * comparison function */
705 struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb, 
706                                                  const struct ldb_message *msg, 
707                                                  const char *name, const char *value)
708 {
709         unsigned int i;
710         struct ldb_message_element *el = ldb_msg_find_element(msg, name);
711
712         if (!el) {
713                 return NULL;
714         }
715
716         for (i=0;i<el->num_values;i++) {
717                 if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
718                         return el;
719                 }
720         }
721
722         return NULL;
723 }
724
725 /*
726  * This is intended for use by the "password hash" module since there
727  * password changes can be specified through one message element with the
728  * new password (to set) and another one with the old password (to unset).
729  *
730  * The first which sets a password (new value) can have flags
731  * (LDB_FLAG_MOD_ADD, LDB_FLAG_MOD_REPLACE) but also none (on "add" operations
732  * for entries). The latter (old value) has always specified
733  * LDB_FLAG_MOD_DELETE.
734  *
735  * Returns LDB_ERR_NO_SUCH_ATTRIBUTE if the attribute which should be deleted
736  * doesn't contain only one value (this is the Windows Server behaviour)
737  * otherwise LDB_SUCCESS.
738  */
739 int samdb_msg_find_old_and_new_ldb_val(const struct ldb_message *msg,
740                                        const char *name,
741                                        const struct ldb_val **new_val,
742                                        const struct ldb_val **old_val)
743 {
744         unsigned int i;
745
746         *new_val = NULL;
747         *old_val = NULL;
748
749         if (msg == NULL) {
750                 return LDB_SUCCESS;
751         }
752
753         for (i = 0; i < msg->num_elements; i++) {
754                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
755                         if (msg->elements[i].flags == LDB_FLAG_MOD_DELETE) {
756                                 *old_val = &msg->elements[i].values[0];
757                         } else {
758                                 *new_val = &msg->elements[i].values[0];
759                         }
760                 }
761         }
762
763         return LDB_SUCCESS;
764 }
765
766 int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
767 {
768         if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
769                 return samdb_msg_add_string(ldb, msg, msg, name, set_value);
770         }
771         return LDB_SUCCESS;
772 }
773
774 int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
775 {
776         struct ldb_message_element *el;
777
778         el = ldb_msg_find_element(msg, name);
779         if (el) {
780                 return LDB_SUCCESS;
781         }
782
783         return samdb_msg_add_string(ldb, msg, msg, name, set_value);
784 }
785
786
787
788 /*
789   add a string element to a message
790 */
791 int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
792                          const char *attr_name, const char *str)
793 {
794         char *s = talloc_strdup(mem_ctx, str);
795         char *a = talloc_strdup(mem_ctx, attr_name);
796         if (s == NULL || a == NULL) {
797                 return LDB_ERR_OPERATIONS_ERROR;
798         }
799         return ldb_msg_add_string(msg, a, s);
800 }
801
802 /*
803   add a dom_sid element to a message
804 */
805 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
806                          const char *attr_name, struct dom_sid *sid)
807 {
808         struct ldb_val v;
809         enum ndr_err_code ndr_err;
810
811         ndr_err = ndr_push_struct_blob(&v, mem_ctx, 
812                                        lp_iconv_convenience(ldb_get_opaque(sam_ldb, "loadparm")),
813                                        sid,
814                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
815         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
816                 return LDB_ERR_OPERATIONS_ERROR;
817         }
818         return ldb_msg_add_value(msg, attr_name, &v, NULL);
819 }
820
821
822 /*
823   add a delete element operation to a message
824 */
825 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
826                          const char *attr_name)
827 {
828         /* we use an empty replace rather than a delete, as it allows for 
829            dsdb_replace() to be used everywhere */
830         return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
831 }
832
833 /*
834   add a add attribute value to a message
835 */
836 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
837                          const char *attr_name, const char *value)
838 {
839         struct ldb_message_element *el;
840         char *a, *v;
841         int ret;
842         a = talloc_strdup(mem_ctx, attr_name);
843         if (a == NULL)
844                 return LDB_ERR_OPERATIONS_ERROR;
845         v = talloc_strdup(mem_ctx, value);
846         if (v == NULL)
847                 return LDB_ERR_OPERATIONS_ERROR;
848         ret = ldb_msg_add_string(msg, a, v);
849         if (ret != 0)
850                 return ret;
851         el = ldb_msg_find_element(msg, a);
852         if (el == NULL)
853                 return LDB_ERR_OPERATIONS_ERROR;
854         el->flags = LDB_FLAG_MOD_ADD;
855         return LDB_SUCCESS;
856 }
857
858 /*
859   add a delete attribute value to a message
860 */
861 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
862                          const char *attr_name, const char *value)
863 {
864         struct ldb_message_element *el;
865         char *a, *v;
866         int ret;
867         a = talloc_strdup(mem_ctx, attr_name);
868         if (a == NULL)
869                 return LDB_ERR_OPERATIONS_ERROR;
870         v = talloc_strdup(mem_ctx, value);
871         if (v == NULL)
872                 return LDB_ERR_OPERATIONS_ERROR;
873         ret = ldb_msg_add_string(msg, a, v);
874         if (ret != 0)
875                 return ret;
876         el = ldb_msg_find_element(msg, a);
877         if (el == NULL)
878                 return LDB_ERR_OPERATIONS_ERROR;
879         el->flags = LDB_FLAG_MOD_DELETE;
880         return LDB_SUCCESS;
881 }
882
883 /*
884   add a int element to a message
885 */
886 int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
887                        const char *attr_name, int v)
888 {
889         const char *s = talloc_asprintf(mem_ctx, "%d", v);
890         return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
891 }
892
893 /*
894   add a unsigned int element to a message
895 */
896 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
897                        const char *attr_name, unsigned int v)
898 {
899         return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
900 }
901
902 /*
903   add a (signed) int64_t element to a message
904 */
905 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
906                         const char *attr_name, int64_t v)
907 {
908         const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
909         return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, s);
910 }
911
912 /*
913   add a uint64_t element to a message
914 */
915 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
916                         const char *attr_name, uint64_t v)
917 {
918         return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
919 }
920
921 /*
922   add a samr_Password element to a message
923 */
924 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
925                        const char *attr_name, struct samr_Password *hash)
926 {
927         struct ldb_val val;
928         val.data = talloc_memdup(mem_ctx, hash->hash, 16);
929         if (!val.data) {
930                 return LDB_ERR_OPERATIONS_ERROR;
931         }
932         val.length = 16;
933         return ldb_msg_add_value(msg, attr_name, &val, NULL);
934 }
935
936 /*
937   add a samr_Password array to a message
938 */
939 int samdb_msg_add_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
940                          const char *attr_name, struct samr_Password *hashes,
941                          unsigned int count)
942 {
943         struct ldb_val val;
944         unsigned int i;
945         val.data = talloc_array_size(mem_ctx, 16, count);
946         val.length = count*16;
947         if (!val.data) {
948                 return LDB_ERR_OPERATIONS_ERROR;
949         }
950         for (i=0;i<count;i++) {
951                 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
952         }
953         return ldb_msg_add_value(msg, attr_name, &val, NULL);
954 }
955
956 /*
957   add a acct_flags element to a message
958 */
959 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
960                              const char *attr_name, uint32_t v)
961 {
962         return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, ds_acb2uf(v));
963 }
964
965 /*
966   add a logon_hours element to a message
967 */
968 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
969                               const char *attr_name, struct samr_LogonHours *hours)
970 {
971         struct ldb_val val;
972         val.length = hours->units_per_week / 8;
973         val.data = hours->bits;
974         return ldb_msg_add_value(msg, attr_name, &val, NULL);
975 }
976
977 /*
978   add a parameters element to a message
979 */
980 int samdb_msg_add_parameters(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
981                              const char *attr_name, struct lsa_BinaryString *parameters)
982 {
983         struct ldb_val val;
984         val.length = parameters->length;
985         val.data = (uint8_t *)parameters->array;
986         return ldb_msg_add_value(msg, attr_name, &val, NULL);
987 }
988 /*
989   add a general value element to a message
990 */
991 int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
992                               const char *attr_name, const struct ldb_val *val)
993 {
994         return ldb_msg_add_value(msg, attr_name, val, NULL);
995 }
996
997 /*
998   sets a general value element to a message
999 */
1000 int samdb_msg_set_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1001                         const char *attr_name, const struct ldb_val *val)
1002 {
1003         struct ldb_message_element *el;
1004
1005         el = ldb_msg_find_element(msg, attr_name);
1006         if (el) {
1007                 el->num_values = 0;
1008         }
1009         return ldb_msg_add_value(msg, attr_name, val, NULL);
1010 }
1011
1012 /*
1013   set a string element in a message
1014 */
1015 int samdb_msg_set_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1016                          const char *attr_name, const char *str)
1017 {
1018         struct ldb_message_element *el;
1019
1020         el = ldb_msg_find_element(msg, attr_name);
1021         if (el) {
1022                 el->num_values = 0;
1023         }
1024         return samdb_msg_add_string(sam_ldb, mem_ctx, msg, attr_name, str);
1025 }
1026
1027 /*
1028  * Handle ldb_request in transaction
1029  */
1030 static int dsdb_autotransaction_request(struct ldb_context *sam_ldb,
1031                                         struct ldb_request *req)
1032 {
1033         int ret;
1034
1035         ret = ldb_transaction_start(sam_ldb);
1036         if (ret != LDB_SUCCESS) {
1037                 return ret;
1038         }
1039
1040         ret = ldb_request(sam_ldb, req);
1041         if (ret == LDB_SUCCESS) {
1042                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1043         }
1044
1045         if (ret == LDB_SUCCESS) {
1046                 return ldb_transaction_commit(sam_ldb);
1047         }
1048         ldb_transaction_cancel(sam_ldb);
1049
1050         return ret;
1051 }
1052
1053 /*
1054   return a default security descriptor
1055 */
1056 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1057 {
1058         struct security_descriptor *sd;
1059
1060         sd = security_descriptor_initialise(mem_ctx);
1061
1062         return sd;
1063 }
1064
1065 struct ldb_dn *samdb_aggregate_schema_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) 
1066 {
1067         struct ldb_dn *schema_dn = ldb_get_schema_basedn(sam_ctx);
1068         struct ldb_dn *aggregate_dn;
1069         if (!schema_dn) {
1070                 return NULL;
1071         }
1072
1073         aggregate_dn = ldb_dn_copy(mem_ctx, schema_dn);
1074         if (!aggregate_dn) {
1075                 return NULL;
1076         }
1077         if (!ldb_dn_add_child_fmt(aggregate_dn, "CN=Aggregate")) {
1078                 return NULL;
1079         }
1080         return aggregate_dn;
1081 }
1082
1083 struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1084 {
1085         struct ldb_dn *new_dn;
1086
1087         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1088         if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
1089                 talloc_free(new_dn);
1090                 return NULL;
1091         }
1092         return new_dn;
1093 }
1094
1095 struct ldb_dn *samdb_infrastructure_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1096 {
1097        struct ldb_dn *new_dn;
1098
1099        new_dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(sam_ctx));
1100        if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Infrastructure")) {
1101                talloc_free(new_dn);
1102                return NULL;
1103        }
1104        return new_dn;
1105 }
1106
1107 struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1108 {
1109         struct ldb_dn *new_dn;
1110
1111         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1112         if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
1113                 talloc_free(new_dn);
1114                 return NULL;
1115         }
1116         return new_dn;
1117 }
1118
1119 /*
1120   work out the domain sid for the current open ldb
1121 */
1122 const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
1123 {
1124         TALLOC_CTX *tmp_ctx;
1125         const struct dom_sid *domain_sid;
1126         const char *attrs[] = {
1127                 "objectSid",
1128                 NULL
1129         };
1130         struct ldb_result *res;
1131         int ret;
1132
1133         /* see if we have a cached copy */
1134         domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1135         if (domain_sid) {
1136                 return domain_sid;
1137         }
1138
1139         tmp_ctx = talloc_new(ldb);
1140         if (tmp_ctx == NULL) {
1141                 goto failed;
1142         }
1143
1144         ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectSid=*");
1145
1146         if (ret != LDB_SUCCESS) {
1147                 goto failed;
1148         }
1149
1150         if (res->count != 1) {
1151                 goto failed;
1152         }
1153
1154         domain_sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
1155         if (domain_sid == NULL) {
1156                 goto failed;
1157         }
1158
1159         /* cache the domain_sid in the ldb */
1160         if (ldb_set_opaque(ldb, "cache.domain_sid", discard_const_p(struct dom_sid, domain_sid)) != LDB_SUCCESS) {
1161                 goto failed;
1162         }
1163
1164         talloc_steal(ldb, domain_sid);
1165         talloc_free(tmp_ctx);
1166
1167         return domain_sid;
1168
1169 failed:
1170         talloc_free(tmp_ctx);
1171         return NULL;
1172 }
1173
1174 /*
1175   get domain sid from cache
1176 */
1177 const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
1178 {
1179         return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1180 }
1181
1182 bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
1183 {
1184         TALLOC_CTX *tmp_ctx;
1185         struct dom_sid *dom_sid_new;
1186         struct dom_sid *dom_sid_old;
1187
1188         /* see if we have a cached copy */
1189         dom_sid_old = talloc_get_type(ldb_get_opaque(ldb, 
1190                                                      "cache.domain_sid"), struct dom_sid);
1191
1192         tmp_ctx = talloc_new(ldb);
1193         if (tmp_ctx == NULL) {
1194                 goto failed;
1195         }
1196
1197         dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
1198         if (!dom_sid_new) {
1199                 goto failed;
1200         }
1201
1202         /* cache the domain_sid in the ldb */
1203         if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
1204                 goto failed;
1205         }
1206
1207         talloc_steal(ldb, dom_sid_new);
1208         talloc_free(tmp_ctx);
1209         talloc_free(dom_sid_old);
1210
1211         return true;
1212
1213 failed:
1214         DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
1215         talloc_free(tmp_ctx);
1216         return false;
1217 }
1218
1219 bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in)
1220 {
1221         TALLOC_CTX *tmp_ctx;
1222         struct ldb_dn *ntds_settings_dn_new;
1223         struct ldb_dn *ntds_settings_dn_old;
1224
1225         /* see if we have a cached copy */
1226         ntds_settings_dn_old = talloc_get_type(ldb_get_opaque(ldb, 
1227                                                               "cache.ntds_settings_dn"), struct ldb_dn);
1228
1229         tmp_ctx = talloc_new(ldb);
1230         if (tmp_ctx == NULL) {
1231                 goto failed;
1232         }
1233
1234         ntds_settings_dn_new = ldb_dn_copy(tmp_ctx, ntds_settings_dn_in);
1235         if (!ntds_settings_dn_new) {
1236                 goto failed;
1237         }
1238
1239         /* cache the domain_sid in the ldb */
1240         if (ldb_set_opaque(ldb, "cache.ntds_settings_dn", ntds_settings_dn_new) != LDB_SUCCESS) {
1241                 goto failed;
1242         }
1243
1244         talloc_steal(ldb, ntds_settings_dn_new);
1245         talloc_free(tmp_ctx);
1246         talloc_free(ntds_settings_dn_old);
1247
1248         return true;
1249
1250 failed:
1251         DEBUG(1,("Failed to set our NTDS Settings DN in the ldb!\n"));
1252         talloc_free(tmp_ctx);
1253         return false;
1254 }
1255
1256 /* Obtain the short name of the flexible single master operator
1257  * (FSMO), such as the PDC Emulator */
1258 const char *samdb_result_fsmo_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
1259                              const char *attr)
1260 {
1261         /* Format is cn=NTDS Settings,cn=<NETBIOS name of FSMO>,.... */
1262         struct ldb_dn *fsmo_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
1263         const struct ldb_val *val = ldb_dn_get_component_val(fsmo_dn, 1);
1264         const char *name = ldb_dn_get_component_name(fsmo_dn, 1);
1265
1266         if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
1267                 /* Ensure this matches the format.  This gives us a
1268                  * bit more confidence that a 'cn' value will be a
1269                  * ascii string */
1270                 return NULL;
1271         }
1272         if (val) {
1273                 return (char *)val->data;
1274         }
1275         return NULL;
1276 }
1277
1278 /*
1279   work out the ntds settings dn for the current open ldb
1280 */
1281 struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb)
1282 {
1283         TALLOC_CTX *tmp_ctx;
1284         const char *root_attrs[] = { "dsServiceName", NULL };
1285         int ret;
1286         struct ldb_result *root_res;
1287         struct ldb_dn *settings_dn;
1288
1289         /* see if we have a cached copy */
1290         settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "cache.ntds_settings_dn");
1291         if (settings_dn) {
1292                 return settings_dn;
1293         }
1294
1295         tmp_ctx = talloc_new(ldb);
1296         if (tmp_ctx == NULL) {
1297                 goto failed;
1298         }
1299
1300         ret = ldb_search(ldb, tmp_ctx, &root_res, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
1301         if (ret) {
1302                 DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n", 
1303                          ldb_errstring(ldb)));
1304                 goto failed;
1305         }
1306
1307         if (root_res->count != 1) {
1308                 goto failed;
1309         }
1310
1311         settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
1312
1313         /* cache the domain_sid in the ldb */
1314         if (ldb_set_opaque(ldb, "cache.settings_dn", settings_dn) != LDB_SUCCESS) {
1315                 goto failed;
1316         }
1317
1318         talloc_steal(ldb, settings_dn);
1319         talloc_free(tmp_ctx);
1320
1321         return settings_dn;
1322
1323 failed:
1324         DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
1325         talloc_free(tmp_ctx);
1326         return NULL;
1327 }
1328
1329 /*
1330   work out the ntds settings invocationId for the current open ldb
1331 */
1332 const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
1333 {
1334         TALLOC_CTX *tmp_ctx;
1335         const char *attrs[] = { "invocationId", NULL };
1336         int ret;
1337         struct ldb_result *res;
1338         struct GUID *invocation_id;
1339
1340         /* see if we have a cached copy */
1341         invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
1342         if (invocation_id) {
1343                 return invocation_id;
1344         }
1345
1346         tmp_ctx = talloc_new(ldb);
1347         if (tmp_ctx == NULL) {
1348                 goto failed;
1349         }
1350
1351         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
1352         if (ret) {
1353                 goto failed;
1354         }
1355
1356         if (res->count != 1) {
1357                 goto failed;
1358         }
1359
1360         invocation_id = talloc(tmp_ctx, struct GUID);
1361         if (!invocation_id) {
1362                 goto failed;
1363         }
1364
1365         *invocation_id = samdb_result_guid(res->msgs[0], "invocationId");
1366
1367         /* cache the domain_sid in the ldb */
1368         if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id) != LDB_SUCCESS) {
1369                 goto failed;
1370         }
1371
1372         talloc_steal(ldb, invocation_id);
1373         talloc_free(tmp_ctx);
1374
1375         return invocation_id;
1376
1377 failed:
1378         DEBUG(1,("Failed to find our own NTDS Settings invocationId in the ldb!\n"));
1379         talloc_free(tmp_ctx);
1380         return NULL;
1381 }
1382
1383 bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
1384 {
1385         TALLOC_CTX *tmp_ctx;
1386         struct GUID *invocation_id_new;
1387         struct GUID *invocation_id_old;
1388
1389         /* see if we have a cached copy */
1390         invocation_id_old = (struct GUID *)ldb_get_opaque(ldb, 
1391                                                          "cache.invocation_id");
1392
1393         tmp_ctx = talloc_new(ldb);
1394         if (tmp_ctx == NULL) {
1395                 goto failed;
1396         }
1397
1398         invocation_id_new = talloc(tmp_ctx, struct GUID);
1399         if (!invocation_id_new) {
1400                 goto failed;
1401         }
1402
1403         *invocation_id_new = *invocation_id_in;
1404
1405         /* cache the domain_sid in the ldb */
1406         if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id_new) != LDB_SUCCESS) {
1407                 goto failed;
1408         }
1409
1410         talloc_steal(ldb, invocation_id_new);
1411         talloc_free(tmp_ctx);
1412         talloc_free(invocation_id_old);
1413
1414         return true;
1415
1416 failed:
1417         DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
1418         talloc_free(tmp_ctx);
1419         return false;
1420 }
1421
1422 /*
1423   work out the ntds settings objectGUID for the current open ldb
1424 */
1425 const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
1426 {
1427         TALLOC_CTX *tmp_ctx;
1428         const char *attrs[] = { "objectGUID", NULL };
1429         int ret;
1430         struct ldb_result *res;
1431         struct GUID *ntds_guid;
1432
1433         /* see if we have a cached copy */
1434         ntds_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
1435         if (ntds_guid) {
1436                 return ntds_guid;
1437         }
1438
1439         tmp_ctx = talloc_new(ldb);
1440         if (tmp_ctx == NULL) {
1441                 goto failed;
1442         }
1443
1444         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
1445         if (ret) {
1446                 goto failed;
1447         }
1448
1449         if (res->count != 1) {
1450                 goto failed;
1451         }
1452
1453         ntds_guid = talloc(tmp_ctx, struct GUID);
1454         if (!ntds_guid) {
1455                 goto failed;
1456         }
1457
1458         *ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID");
1459
1460         /* cache the domain_sid in the ldb */
1461         if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid) != LDB_SUCCESS) {
1462                 goto failed;
1463         }
1464
1465         talloc_steal(ldb, ntds_guid);
1466         talloc_free(tmp_ctx);
1467
1468         return ntds_guid;
1469
1470 failed:
1471         DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
1472         talloc_free(tmp_ctx);
1473         return NULL;
1474 }
1475
1476 bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
1477 {
1478         TALLOC_CTX *tmp_ctx;
1479         struct GUID *ntds_guid_new;
1480         struct GUID *ntds_guid_old;
1481
1482         /* see if we have a cached copy */
1483         ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
1484
1485         tmp_ctx = talloc_new(ldb);
1486         if (tmp_ctx == NULL) {
1487                 goto failed;
1488         }
1489
1490         ntds_guid_new = talloc(tmp_ctx, struct GUID);
1491         if (!ntds_guid_new) {
1492                 goto failed;
1493         }
1494
1495         *ntds_guid_new = *ntds_guid_in;
1496
1497         /* cache the domain_sid in the ldb */
1498         if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid_new) != LDB_SUCCESS) {
1499                 goto failed;
1500         }
1501
1502         talloc_steal(ldb, ntds_guid_new);
1503         talloc_free(tmp_ctx);
1504         talloc_free(ntds_guid_old);
1505
1506         return true;
1507
1508 failed:
1509         DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
1510         talloc_free(tmp_ctx);
1511         return false;
1512 }
1513
1514 /*
1515   work out the server dn for the current open ldb
1516 */
1517 struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1518 {
1519         return ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb));
1520 }
1521
1522 /*
1523   work out the server dn for the current open ldb
1524 */
1525 struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1526 {
1527         struct ldb_dn *server_dn;
1528         struct ldb_dn *servers_dn;
1529         struct ldb_dn *server_site_dn;
1530
1531         /* TODO: there must be a saner way to do this!! */
1532         server_dn = samdb_server_dn(ldb, mem_ctx);
1533         if (!server_dn) return NULL;
1534
1535         servers_dn = ldb_dn_get_parent(mem_ctx, server_dn);
1536         talloc_free(server_dn);
1537         if (!servers_dn) return NULL;
1538
1539         server_site_dn = ldb_dn_get_parent(mem_ctx, servers_dn);
1540         talloc_free(servers_dn);
1541
1542         return server_site_dn;
1543 }
1544
1545 /*
1546   find a 'reference' DN that points at another object
1547   (eg. serverReference, rIDManagerReference etc)
1548  */
1549 int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
1550                        const char *attribute, struct ldb_dn **dn)
1551 {
1552         const char *attrs[2];
1553         struct ldb_result *res;
1554         int ret;
1555
1556         attrs[0] = attribute;
1557         attrs[1] = NULL;
1558
1559         ret = ldb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, NULL);
1560         if (ret != LDB_SUCCESS) {
1561                 return ret;
1562         }
1563         if (res->count != 1) {
1564                 talloc_free(res);
1565                 return LDB_ERR_NO_SUCH_OBJECT;
1566         }
1567
1568         *dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
1569         if (!*dn) {
1570                 talloc_free(res);
1571                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
1572         }
1573
1574         talloc_free(res);
1575         return LDB_SUCCESS;
1576 }
1577
1578 /*
1579   find our machine account via the serverReference attribute in the
1580   server DN
1581  */
1582 int samdb_server_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1583 {
1584         struct ldb_dn *server_dn;
1585         int ret;
1586
1587         server_dn = samdb_server_dn(ldb, mem_ctx);
1588         if (server_dn == NULL) {
1589                 return LDB_ERR_NO_SUCH_OBJECT;
1590         }
1591
1592         ret = samdb_reference_dn(ldb, mem_ctx, server_dn, "serverReference", dn);
1593         talloc_free(server_dn);
1594
1595         return ret;
1596 }
1597
1598 /*
1599   find the RID Manager$ DN via the rIDManagerReference attribute in the
1600   base DN
1601  */
1602 int samdb_rid_manager_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1603 {
1604         return samdb_reference_dn(ldb, mem_ctx, ldb_get_default_basedn(ldb),
1605                                   "rIDManagerReference", dn);
1606 }
1607
1608 /*
1609   find the RID Set DN via the rIDSetReferences attribute in our
1610   machine account DN
1611  */
1612 int samdb_rid_set_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1613 {
1614         struct ldb_dn *server_ref_dn;
1615         int ret;
1616
1617         ret = samdb_server_reference_dn(ldb, mem_ctx, &server_ref_dn);
1618         if (ret != LDB_SUCCESS) {
1619                 return ret;
1620         }
1621         ret = samdb_reference_dn(ldb, mem_ctx, server_ref_dn, "rIDSetReferences", dn);
1622         talloc_free(server_ref_dn);
1623         return ret;
1624 }
1625
1626 const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1627 {
1628         const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb,
1629                                                                             mem_ctx));
1630
1631         if (val == NULL) {
1632                 return NULL;
1633         }
1634
1635         return (const char *) val->data;
1636 }
1637
1638 /*
1639  * Finds the client site by using the client's IP address.
1640  * The "subnet_name" returns the name of the subnet if parameter != NULL
1641  */
1642 const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1643                                    const char *ip_address, char **subnet_name)
1644 {
1645         const char *attrs[] = { "cn", "siteObject", NULL };
1646         struct ldb_dn *sites_container_dn, *subnets_dn, *sites_dn;
1647         struct ldb_result *res;
1648         const struct ldb_val *val;
1649         const char *site_name = NULL, *l_subnet_name = NULL;
1650         const char *allow_list[2] = { NULL, NULL };
1651         unsigned int i, count;
1652         int cnt, ret;
1653
1654         /*
1655          * if we don't have a client ip e.g. ncalrpc
1656          * the server site is the client site
1657          */
1658         if (ip_address == NULL) {
1659                 return samdb_server_site_name(ldb, mem_ctx);
1660         }
1661
1662         sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
1663         if (sites_container_dn == NULL) {
1664                 return NULL;
1665         }
1666
1667         subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
1668         if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
1669                 talloc_free(sites_container_dn);
1670                 talloc_free(subnets_dn);
1671                 return NULL;
1672         }
1673
1674         ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
1675                          attrs, NULL);
1676         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1677                 count = 0;
1678         } else if (ret != LDB_SUCCESS) {
1679                 talloc_free(sites_container_dn);
1680                 talloc_free(subnets_dn);
1681                 return NULL;
1682         } else {
1683                 count = res->count;
1684         }
1685
1686         for (i = 0; i < count; i++) {
1687                 l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
1688                                                             NULL);
1689
1690                 allow_list[0] = l_subnet_name;
1691
1692                 if (allow_access(mem_ctx, NULL, allow_list, "", ip_address)) {
1693                         sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
1694                                                            res->msgs[i],
1695                                                            "siteObject");
1696                         if (sites_dn == NULL) {
1697                                 /* No reference, maybe another subnet matches */
1698                                 continue;
1699                         }
1700
1701                         /* "val" cannot be NULL here since "sites_dn" != NULL */
1702                         val = ldb_dn_get_rdn_val(sites_dn);
1703                         site_name = talloc_strdup(mem_ctx,
1704                                                   (const char *) val->data);
1705
1706                         talloc_free(sites_dn);
1707
1708                         break;
1709                 }
1710         }
1711
1712         if (site_name == NULL) {
1713                 /* This is the Windows Server fallback rule: when no subnet
1714                  * exists and we have only one site available then use it (it
1715                  * is for sure the same as our server site). If more sites do
1716                  * exist then we don't know which one to use and set the site
1717                  * name to "". */
1718                 cnt = samdb_search_count(ldb, sites_container_dn,
1719                                          "(objectClass=site)");
1720                 if (cnt == 1) {
1721                         site_name = samdb_server_site_name(ldb, mem_ctx);
1722                 } else {
1723                         site_name = talloc_strdup(mem_ctx, "");
1724                 }
1725                 l_subnet_name = NULL;
1726         }
1727
1728         if (subnet_name != NULL) {
1729                 *subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
1730         }
1731
1732         talloc_free(sites_container_dn);
1733         talloc_free(subnets_dn);
1734         talloc_free(res);
1735
1736         return site_name;
1737 }
1738
1739 /*
1740   work out if we are the PDC for the domain of the current open ldb
1741 */
1742 bool samdb_is_pdc(struct ldb_context *ldb)
1743 {
1744         const char *dom_attrs[] = { "fSMORoleOwner", NULL };
1745         int ret;
1746         struct ldb_result *dom_res;
1747         TALLOC_CTX *tmp_ctx;
1748         bool is_pdc;
1749         struct ldb_dn *pdc;
1750
1751         tmp_ctx = talloc_new(ldb);
1752         if (tmp_ctx == NULL) {
1753                 DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
1754                 return false;
1755         }
1756
1757         ret = ldb_search(ldb, tmp_ctx, &dom_res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, dom_attrs, NULL);
1758         if (ret) {
1759                 DEBUG(1,("Searching for fSMORoleOwner in %s failed: %s\n", 
1760                          ldb_dn_get_linearized(ldb_get_default_basedn(ldb)), 
1761                          ldb_errstring(ldb)));
1762                 goto failed;
1763         }
1764         if (dom_res->count != 1) {
1765                 goto failed;
1766         }
1767
1768         pdc = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, dom_res->msgs[0], "fSMORoleOwner");
1769
1770         if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc) == 0) {
1771                 is_pdc = true;
1772         } else {
1773                 is_pdc = false;
1774         }
1775
1776         talloc_free(tmp_ctx);
1777
1778         return is_pdc;
1779
1780 failed:
1781         DEBUG(1,("Failed to find if we are the PDC for this ldb\n"));
1782         talloc_free(tmp_ctx);
1783         return false;
1784 }
1785
1786 /*
1787   work out if we are a Global Catalog server for the domain of the current open ldb
1788 */
1789 bool samdb_is_gc(struct ldb_context *ldb)
1790 {
1791         const char *attrs[] = { "options", NULL };
1792         int ret, options;
1793         struct ldb_result *res;
1794         TALLOC_CTX *tmp_ctx;
1795
1796         tmp_ctx = talloc_new(ldb);
1797         if (tmp_ctx == NULL) {
1798                 DEBUG(1, ("talloc_new failed in samdb_is_pdc"));
1799                 return false;
1800         }
1801
1802         /* Query cn=ntds settings,.... */
1803         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
1804         if (ret) {
1805                 talloc_free(tmp_ctx);
1806                 return false;
1807         }
1808         if (res->count != 1) {
1809                 talloc_free(tmp_ctx);
1810                 return false;
1811         }
1812
1813         options = ldb_msg_find_attr_as_int(res->msgs[0], "options", 0);
1814         talloc_free(tmp_ctx);
1815
1816         /* if options attribute has the 0x00000001 flag set, then enable the global catlog */
1817         if (options & 0x000000001) {
1818                 return true;
1819         }
1820         return false;
1821 }
1822
1823 /* Find a domain object in the parents of a particular DN.  */
1824 int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
1825                                    struct ldb_dn **parent_dn, const char **errstring)
1826 {
1827         TALLOC_CTX *local_ctx;
1828         struct ldb_dn *sdn = dn;
1829         struct ldb_result *res = NULL;
1830         int ret = 0;
1831         const char *attrs[] = { NULL };
1832
1833         local_ctx = talloc_new(mem_ctx);
1834         if (local_ctx == NULL) return LDB_ERR_OPERATIONS_ERROR;
1835
1836         while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
1837                 ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
1838                                  "(|(objectClass=domain)(objectClass=builtinDomain))");
1839                 if (ret == LDB_SUCCESS) {
1840                         if (res->count == 1) {
1841                                 break;
1842                         }
1843                 } else {
1844                         break;
1845                 }
1846         }
1847
1848         if (ret != LDB_SUCCESS) {
1849                 *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
1850                                              ldb_dn_get_linearized(dn),
1851                                              ldb_dn_get_linearized(sdn),
1852                                              ldb_errstring(ldb));
1853                 talloc_free(local_ctx);
1854                 return ret;
1855         }
1856         if (res->count != 1) {
1857                 *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
1858                                              ldb_dn_get_linearized(dn));
1859                 DEBUG(0,(__location__ ": %s\n", *errstring));
1860                 talloc_free(local_ctx);
1861                 return LDB_ERR_CONSTRAINT_VIOLATION;
1862         }
1863
1864         *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
1865         talloc_free(local_ctx);
1866         return ret;
1867 }
1868
1869
1870 /*
1871  * Performs checks on a user password (plaintext UNIX format - attribute
1872  * "password"). The remaining parameters have to be extracted from the domain
1873  * object in the AD.
1874  *
1875  * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
1876  */
1877 enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *password,
1878                                                 const uint32_t pwdProperties,
1879                                                 const uint32_t minPwdLength)
1880 {
1881         /* checks if the "minPwdLength" property is satisfied */
1882         if (minPwdLength > password->length)
1883                 return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
1884
1885         /* checks the password complexity */
1886         if (((pwdProperties & DOMAIN_PASSWORD_COMPLEX) != 0)
1887                         && (password->data != NULL)
1888                         && (!check_password_quality((const char *) password->data)))
1889                 return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
1890
1891         return SAMR_VALIDATION_STATUS_SUCCESS;
1892 }
1893
1894 /*
1895  * Callback for "samdb_set_password" password change
1896  */
1897 int samdb_set_password_callback(struct ldb_request *req, struct ldb_reply *ares)
1898 {
1899         int ret;
1900
1901         if (!ares) {
1902                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1903         }
1904
1905         if (ares->error != LDB_SUCCESS) {
1906                 ret = ares->error;
1907                 req->context = talloc_steal(req,
1908                                             ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
1909                 talloc_free(ares);
1910                 return ldb_request_done(req, ret);
1911         }
1912
1913         if (ares->type != LDB_REPLY_DONE) {
1914                 talloc_free(ares);
1915                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1916         }
1917
1918         req->context = talloc_steal(req,
1919                                     ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
1920         talloc_free(ares);
1921         return ldb_request_done(req, LDB_SUCCESS);
1922 }
1923
1924 /*
1925  * Sets the user password using plaintext UTF16 (attribute "new_password") or
1926  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
1927  * as parameter if it's a user change or not ("userChange"). The "rejectReason"
1928  * gives some more informations if the changed failed.
1929  *
1930  * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
1931  *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
1932  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION
1933  */
1934 NTSTATUS samdb_set_password(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1935                             struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
1936                             const DATA_BLOB *new_password,
1937                             struct samr_Password *lmNewHash,
1938                             struct samr_Password *ntNewHash,
1939                             bool user_change,
1940                             enum samPwdChangeReason *reject_reason,
1941                             struct samr_DomInfo1 **_dominfo)
1942 {
1943         struct ldb_message *msg;
1944         struct ldb_message_element *el;
1945         struct ldb_request *req;
1946         struct dsdb_control_password_change_status *pwd_stat = NULL;
1947         int ret;
1948         NTSTATUS status;
1949
1950 #define CHECK_RET(x) \
1951         if (x != LDB_SUCCESS) { \
1952                 talloc_free(msg); \
1953                 return NT_STATUS_NO_MEMORY; \
1954         }
1955
1956         msg = ldb_msg_new(mem_ctx);
1957         if (msg == NULL) {
1958                 return NT_STATUS_NO_MEMORY;
1959         }
1960         msg->dn = user_dn;
1961         if ((new_password != NULL)
1962                         && ((lmNewHash == NULL) && (ntNewHash == NULL))) {
1963                 /* we have the password as plaintext UTF16 */
1964                 CHECK_RET(samdb_msg_add_value(ldb, mem_ctx, msg,
1965                         "clearTextPassword", new_password));
1966                 el = ldb_msg_find_element(msg, "clearTextPassword");
1967                 el->flags = LDB_FLAG_MOD_REPLACE;
1968         } else if ((new_password == NULL)
1969                         && ((lmNewHash != NULL) || (ntNewHash != NULL))) {
1970                 /* we have a password as LM and/or NT hash */
1971                 if (lmNewHash != NULL) {
1972                         CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
1973                                 "dBCSPwd", lmNewHash));
1974                         el = ldb_msg_find_element(msg, "dBCSPwd");
1975                         el->flags = LDB_FLAG_MOD_REPLACE;
1976                 }
1977                 if (ntNewHash != NULL) {
1978                         CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
1979                                 "unicodePwd", ntNewHash));
1980                         el = ldb_msg_find_element(msg, "unicodePwd");
1981                         el->flags = LDB_FLAG_MOD_REPLACE;
1982                 }
1983         } else {
1984                 /* the password wasn't specified correctly */
1985                 talloc_free(msg);
1986                 return NT_STATUS_INVALID_PARAMETER;
1987         }
1988
1989         /* build modify request */
1990         ret = ldb_build_mod_req(&req, ldb, mem_ctx, msg, NULL, NULL,
1991                                 samdb_set_password_callback, NULL);
1992         if (ret != LDB_SUCCESS) {
1993                 talloc_free(msg);
1994                 return NT_STATUS_NO_MEMORY;
1995         }
1996
1997         if (user_change) {
1998                 /* a user password change and we've checked already the old
1999                  * password somewhere else (callers responsability) */
2000                 ret = ldb_request_add_control(req,
2001                                               DSDB_CONTROL_PASSWORD_CHANGE_OLD_PW_CHECKED_OID,
2002                                               true, NULL);
2003                 if (ret != LDB_SUCCESS) {
2004                         talloc_free(req);
2005                         talloc_free(msg);
2006                         return NT_STATUS_NO_MEMORY;
2007                 }
2008         }
2009         ret = ldb_request_add_control(req,
2010                                       DSDB_CONTROL_PASSWORD_HASH_VALUES_OID,
2011                                       true, NULL);
2012         if (ret != LDB_SUCCESS) {
2013                 talloc_free(req);
2014                 talloc_free(msg);
2015                 return NT_STATUS_NO_MEMORY;
2016         }
2017         ret = ldb_request_add_control(req,
2018                                       DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2019                                       true, NULL);
2020         if (ret != LDB_SUCCESS) {
2021                 talloc_free(req);
2022                 talloc_free(msg);
2023                 return NT_STATUS_NO_MEMORY;
2024         }
2025
2026         ret = dsdb_autotransaction_request(ldb, req);
2027
2028         if (req->context != NULL) {
2029                 pwd_stat = talloc_steal(mem_ctx,
2030                                         ((struct ldb_control *)req->context)->data);
2031         }
2032
2033         talloc_free(req);
2034         talloc_free(msg);
2035
2036         /* Sets the domain info (if requested) */
2037         if (_dominfo != NULL) {
2038                 struct samr_DomInfo1 *dominfo;
2039
2040                 dominfo = talloc_zero(mem_ctx, struct samr_DomInfo1);
2041                 if (dominfo == NULL) {
2042                         return NT_STATUS_NO_MEMORY;
2043                 }
2044
2045                 if (pwd_stat != NULL) {
2046                         dominfo->min_password_length     = pwd_stat->domain_data.minPwdLength;
2047                         dominfo->password_properties     = pwd_stat->domain_data.pwdProperties;
2048                         dominfo->password_history_length = pwd_stat->domain_data.pwdHistoryLength;
2049                         dominfo->max_password_age        = pwd_stat->domain_data.maxPwdAge;
2050                         dominfo->min_password_age        = pwd_stat->domain_data.minPwdAge;
2051                 }
2052
2053                 *_dominfo = dominfo;
2054         }
2055
2056         if (reject_reason != NULL) {
2057                 if (pwd_stat != NULL) {
2058                         *reject_reason = pwd_stat->reject_reason;
2059                 } else {
2060                         *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2061                 }
2062         }
2063
2064         if (pwd_stat != NULL) {
2065                 talloc_free(pwd_stat);
2066         }
2067
2068         /* TODO: Error results taken from "password_hash" module. Are they
2069            correct? */
2070         if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
2071                 status = NT_STATUS_WRONG_PASSWORD;
2072         } else if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
2073                 status = NT_STATUS_PASSWORD_RESTRICTION;
2074         } else if (ret != LDB_SUCCESS) {
2075                 status = NT_STATUS_UNSUCCESSFUL;
2076         } else {
2077                 status = NT_STATUS_OK;
2078         }
2079
2080         return status;
2081 }
2082
2083 /*
2084  * Sets the user password using plaintext UTF16 (attribute "new_password") or
2085  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
2086  * as parameter if it's a user change or not ("userChange"). The "rejectReason"
2087  * gives some more informations if the changed failed.
2088  *
2089  * This wrapper function for "samdb_set_password" takes a SID as input rather
2090  * than a user DN.
2091  *
2092  * This call encapsulates a new LDB transaction for changing the password;
2093  * therefore the user hasn't to start a new one.
2094  *
2095  * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
2096  *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2097  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION
2098  */
2099 NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2100                                 const struct dom_sid *user_sid,
2101                                 const DATA_BLOB *new_password,
2102                                 struct samr_Password *lmNewHash, 
2103                                 struct samr_Password *ntNewHash,
2104                                 bool user_change,
2105                                 enum samPwdChangeReason *reject_reason,
2106                                 struct samr_DomInfo1 **_dominfo) 
2107 {
2108         NTSTATUS nt_status;
2109         struct ldb_dn *user_dn;
2110         int ret;
2111
2112         ret = ldb_transaction_start(ldb);
2113         if (ret != LDB_SUCCESS) {
2114                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
2115                 return NT_STATUS_TRANSACTION_ABORTED;
2116         }
2117
2118         user_dn = samdb_search_dn(ldb, mem_ctx, NULL,
2119                                   "(&(objectSid=%s)(objectClass=user))", 
2120                                   ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
2121         if (!user_dn) {
2122                 ldb_transaction_cancel(ldb);
2123                 DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n",
2124                           dom_sid_string(mem_ctx, user_sid)));
2125                 return NT_STATUS_NO_SUCH_USER;
2126         }
2127
2128         nt_status = samdb_set_password(ldb, mem_ctx,
2129                                        user_dn, NULL,
2130                                        new_password,
2131                                        lmNewHash, ntNewHash,
2132                                        user_change,
2133                                        reject_reason, _dominfo);
2134         if (!NT_STATUS_IS_OK(nt_status)) {
2135                 ldb_transaction_cancel(ldb);
2136                 talloc_free(user_dn);
2137                 return nt_status;
2138         }
2139
2140         ret = ldb_transaction_commit(ldb);
2141         if (ret != LDB_SUCCESS) {
2142                 DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
2143                          ldb_dn_get_linearized(user_dn),
2144                          ldb_errstring(ldb)));
2145                 talloc_free(user_dn);
2146                 return NT_STATUS_TRANSACTION_ABORTED;
2147         }
2148
2149         talloc_free(user_dn);
2150         return NT_STATUS_OK;
2151 }
2152
2153
2154 NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 
2155                                                  struct dom_sid *sid, struct ldb_dn **ret_dn) 
2156 {
2157         struct ldb_message *msg;
2158         struct ldb_dn *basedn;
2159         char *sidstr;
2160         int ret;
2161
2162         sidstr = dom_sid_string(mem_ctx, sid);
2163         NT_STATUS_HAVE_NO_MEMORY(sidstr);
2164
2165         /* We might have to create a ForeignSecurityPrincipal, even if this user
2166          * is in our own domain */
2167
2168         msg = ldb_msg_new(sidstr);
2169         if (msg == NULL) {
2170                 talloc_free(sidstr);
2171                 return NT_STATUS_NO_MEMORY;
2172         }
2173
2174         ret = dsdb_wellknown_dn(sam_ctx, sidstr,
2175                                 ldb_get_default_basedn(sam_ctx),
2176                                 DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER,
2177                                 &basedn);
2178         if (ret != LDB_SUCCESS) {
2179                 DEBUG(0, ("Failed to find DN for "
2180                           "ForeignSecurityPrincipal container - %s\n", ldb_errstring(sam_ctx)));
2181                 talloc_free(sidstr);
2182                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2183         }
2184
2185         /* add core elements to the ldb_message for the alias */
2186         msg->dn = basedn;
2187         if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr)) {
2188                 talloc_free(sidstr);
2189                 return NT_STATUS_NO_MEMORY;
2190         }
2191
2192         samdb_msg_add_string(sam_ctx, msg, msg,
2193                              "objectClass",
2194                              "foreignSecurityPrincipal");
2195
2196         /* create the alias */
2197         ret = ldb_add(sam_ctx, msg);
2198         if (ret != LDB_SUCCESS) {
2199                 DEBUG(0,("Failed to create foreignSecurityPrincipal "
2200                          "record %s: %s\n", 
2201                          ldb_dn_get_linearized(msg->dn),
2202                          ldb_errstring(sam_ctx)));
2203                 talloc_free(sidstr);
2204                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2205         }
2206
2207         *ret_dn = talloc_steal(mem_ctx, msg->dn);
2208         talloc_free(sidstr);
2209
2210         return NT_STATUS_OK;
2211 }
2212
2213
2214 /*
2215   Find the DN of a domain, assuming it to be a dotted.dns name
2216 */
2217
2218 struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain) 
2219 {
2220         unsigned int i;
2221         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2222         const char *binary_encoded;
2223         const char **split_realm;
2224         struct ldb_dn *dn;
2225
2226         if (!tmp_ctx) {
2227                 return NULL;
2228         }
2229
2230         split_realm = (const char **)str_list_make(tmp_ctx, dns_domain, ".");
2231         if (!split_realm) {
2232                 talloc_free(tmp_ctx);
2233                 return NULL;
2234         }
2235         dn = ldb_dn_new(mem_ctx, ldb, NULL);
2236         for (i=0; split_realm[i]; i++) {
2237                 binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
2238                 if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
2239                         DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
2240                                   binary_encoded, ldb_dn_get_linearized(dn)));
2241                         talloc_free(tmp_ctx);
2242                         return NULL;
2243                 }
2244         }
2245         if (!ldb_dn_validate(dn)) {
2246                 DEBUG(2, ("Failed to validated DN %s\n",
2247                           ldb_dn_get_linearized(dn)));
2248                 talloc_free(tmp_ctx);
2249                 return NULL;
2250         }
2251         talloc_free(tmp_ctx);
2252         return dn;
2253 }
2254
2255 /*
2256   Find the DN of a domain, be it the netbios or DNS name 
2257 */
2258 struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, 
2259                                   const char *domain_name) 
2260 {
2261         const char * const domain_ref_attrs[] = {
2262                 "ncName", NULL
2263         };
2264         const char * const domain_ref2_attrs[] = {
2265                 NULL
2266         };
2267         struct ldb_result *res_domain_ref;
2268         char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
2269         /* find the domain's DN */
2270         int ret_domain = ldb_search(ldb, mem_ctx,
2271                                             &res_domain_ref, 
2272                                             samdb_partitions_dn(ldb, mem_ctx), 
2273                                             LDB_SCOPE_ONELEVEL, 
2274                                             domain_ref_attrs,
2275                                             "(&(nETBIOSName=%s)(objectclass=crossRef))", 
2276                                             escaped_domain);
2277         if (ret_domain != 0) {
2278                 return NULL;
2279         }
2280
2281         if (res_domain_ref->count == 0) {
2282                 ret_domain = ldb_search(ldb, mem_ctx,
2283                                                 &res_domain_ref, 
2284                                                 samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
2285                                                 LDB_SCOPE_BASE,
2286                                                 domain_ref2_attrs,
2287                                                 "(objectclass=domain)");
2288                 if (ret_domain != 0) {
2289                         return NULL;
2290                 }
2291
2292                 if (res_domain_ref->count == 1) {
2293                         return res_domain_ref->msgs[0]->dn;
2294                 }
2295                 return NULL;
2296         }
2297
2298         if (res_domain_ref->count > 1) {
2299                 DEBUG(0,("Found %d records matching domain [%s]\n", 
2300                          ret_domain, domain_name));
2301                 return NULL;
2302         }
2303
2304         return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
2305
2306 }
2307
2308
2309 /*
2310   use a GUID to find a DN
2311  */
2312 int dsdb_find_dn_by_guid(struct ldb_context *ldb, 
2313                          TALLOC_CTX *mem_ctx,
2314                          const struct GUID *guid, struct ldb_dn **dn)
2315 {
2316         int ret;
2317         struct ldb_result *res;
2318         const char *attrs[] = { NULL };
2319         char *guid_str = GUID_string(mem_ctx, guid);
2320
2321         if (!guid_str) {
2322                 return LDB_ERR_OPERATIONS_ERROR;
2323         }
2324
2325         ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
2326                           DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
2327                           DSDB_SEARCH_SHOW_EXTENDED_DN |
2328                           DSDB_SEARCH_ONE_ONLY,
2329                           "objectGUID=%s", guid_str);
2330         talloc_free(guid_str);
2331         if (ret != LDB_SUCCESS) {
2332                 return ret;
2333         }
2334
2335         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
2336         talloc_free(res);
2337
2338         return LDB_SUCCESS;
2339 }
2340
2341 /*
2342   use a DN to find a GUID with a given attribute name
2343  */
2344 int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
2345                               struct ldb_dn *dn, const char *attribute,
2346                               struct GUID *guid)
2347 {
2348         int ret;
2349         struct ldb_result *res;
2350         const char *attrs[2];
2351         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
2352
2353         attrs[0] = attribute;
2354         attrs[1] = NULL;
2355
2356         ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
2357         if (ret != LDB_SUCCESS) {
2358                 talloc_free(tmp_ctx);
2359                 return ret;
2360         }
2361         if (res->count < 1) {
2362                 talloc_free(tmp_ctx);
2363                 return LDB_ERR_NO_SUCH_OBJECT;
2364         }
2365         *guid = samdb_result_guid(res->msgs[0], attribute);
2366         talloc_free(tmp_ctx);
2367         return LDB_SUCCESS;
2368 }
2369
2370 /*
2371   use a DN to find a GUID
2372  */
2373 int dsdb_find_guid_by_dn(struct ldb_context *ldb,
2374                          struct ldb_dn *dn, struct GUID *guid)
2375 {
2376         return dsdb_find_guid_attr_by_dn(ldb, dn, "objectGUID", guid);
2377 }
2378
2379
2380
2381 /*
2382  adds the given GUID to the given ldb_message. This value is added
2383  for the given attr_name (may be either "objectGUID" or "parentGUID").
2384  */
2385 int dsdb_msg_add_guid(struct ldb_message *msg,
2386                 struct GUID *guid,
2387                 const char *attr_name)
2388 {
2389         int ret;
2390         struct ldb_val v;
2391         NTSTATUS status;
2392         TALLOC_CTX *tmp_ctx =  talloc_init("dsdb_msg_add_guid");
2393
2394         status = GUID_to_ndr_blob(guid, tmp_ctx, &v);
2395         if (!NT_STATUS_IS_OK(status)) {
2396                 ret = LDB_ERR_OPERATIONS_ERROR;
2397                 goto done;
2398         }
2399
2400         ret = ldb_msg_add_steal_value(msg, attr_name, &v);
2401         if (ret != LDB_SUCCESS) {
2402                 DEBUG(4,(__location__ ": Failed to add %s to the message\n",
2403                                          attr_name));
2404                 goto done;
2405         }
2406
2407         ret = LDB_SUCCESS;
2408
2409 done:
2410         talloc_free(tmp_ctx);
2411         return ret;
2412
2413 }
2414
2415
2416 /*
2417   use a DN to find a SID
2418  */
2419 int dsdb_find_sid_by_dn(struct ldb_context *ldb, 
2420                         struct ldb_dn *dn, struct dom_sid *sid)
2421 {
2422         int ret;
2423         struct ldb_result *res;
2424         const char *attrs[] = { "objectSID", NULL };
2425         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
2426         struct dom_sid *s;
2427
2428         ZERO_STRUCTP(sid);
2429
2430         ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
2431         if (ret != LDB_SUCCESS) {
2432                 talloc_free(tmp_ctx);
2433                 return ret;
2434         }
2435         if (res->count < 1) {
2436                 talloc_free(tmp_ctx);
2437                 return LDB_ERR_NO_SUCH_OBJECT;
2438         }
2439         s = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSID");
2440         if (s == NULL) {
2441                 talloc_free(tmp_ctx);
2442                 return LDB_ERR_NO_SUCH_OBJECT;
2443         }
2444         *sid = *s;
2445         talloc_free(tmp_ctx);
2446         return LDB_SUCCESS;
2447 }
2448
2449
2450 /*
2451   load a repsFromTo blob list for a given partition GUID
2452   attr must be "repsFrom" or "repsTo"
2453  */
2454 WERROR dsdb_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
2455                      const char *attr, struct repsFromToBlob **r, uint32_t *count)
2456 {
2457         const char *attrs[] = { attr, NULL };
2458         struct ldb_result *res = NULL;
2459         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2460         unsigned int i;
2461         struct ldb_message_element *el;
2462
2463         *r = NULL;
2464         *count = 0;
2465
2466         if (ldb_search(sam_ctx, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL) != LDB_SUCCESS ||
2467             res->count < 1) {
2468                 DEBUG(0,("dsdb_loadreps: failed to read partition object\n"));
2469                 talloc_free(tmp_ctx);
2470                 return WERR_DS_DRA_INTERNAL_ERROR;
2471         }
2472
2473         el = ldb_msg_find_element(res->msgs[0], attr);
2474         if (el == NULL) {
2475                 /* it's OK to be empty */
2476                 talloc_free(tmp_ctx);
2477                 return WERR_OK;
2478         }
2479
2480         *count = el->num_values;
2481         *r = talloc_array(mem_ctx, struct repsFromToBlob, *count);
2482         if (*r == NULL) {
2483                 talloc_free(tmp_ctx);
2484                 return WERR_DS_DRA_INTERNAL_ERROR;
2485         }
2486
2487         for (i=0; i<(*count); i++) {
2488                 enum ndr_err_code ndr_err;
2489                 ndr_err = ndr_pull_struct_blob(&el->values[i], 
2490                                                mem_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")),
2491                                                &(*r)[i], 
2492                                                (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
2493                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2494                         talloc_free(tmp_ctx);
2495                         return WERR_DS_DRA_INTERNAL_ERROR;
2496                 }
2497         }
2498
2499         talloc_free(tmp_ctx);
2500         
2501         return WERR_OK;
2502 }
2503
2504 /*
2505   save the repsFromTo blob list for a given partition GUID
2506   attr must be "repsFrom" or "repsTo"
2507  */
2508 WERROR dsdb_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
2509                      const char *attr, struct repsFromToBlob *r, uint32_t count)
2510 {
2511         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2512         struct ldb_message *msg;
2513         struct ldb_message_element *el;
2514         unsigned int i;
2515
2516         msg = ldb_msg_new(tmp_ctx);
2517         msg->dn = dn;
2518         if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_REPLACE, &el) != LDB_SUCCESS) {
2519                 goto failed;
2520         }
2521
2522         el->values = talloc_array(msg, struct ldb_val, count);
2523         if (!el->values) {
2524                 goto failed;
2525         }
2526
2527         for (i=0; i<count; i++) {
2528                 struct ldb_val v;
2529                 enum ndr_err_code ndr_err;
2530
2531                 ndr_err = ndr_push_struct_blob(&v, tmp_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")),
2532                                                &r[i], 
2533                                                (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
2534                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2535                         goto failed;
2536                 }
2537
2538                 el->num_values++;
2539                 el->values[i] = v;
2540         }
2541
2542         if (ldb_modify(sam_ctx, msg) != LDB_SUCCESS) {
2543                 DEBUG(0,("Failed to store %s - %s\n", attr, ldb_errstring(sam_ctx)));
2544                 goto failed;
2545         }
2546
2547         talloc_free(tmp_ctx);
2548         
2549         return WERR_OK;
2550
2551 failed:
2552         talloc_free(tmp_ctx);
2553         return WERR_DS_DRA_INTERNAL_ERROR;
2554 }
2555
2556
2557 /*
2558   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
2559   object for a partition
2560  */
2561 int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
2562                                 uint64_t *uSN, uint64_t *urgent_uSN)
2563 {
2564         struct ldb_request *req;
2565         int ret;
2566         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
2567         struct dsdb_control_current_partition *p_ctrl;
2568         struct ldb_result *res;
2569
2570         res = talloc_zero(tmp_ctx, struct ldb_result);
2571         if (!res) {
2572                 talloc_free(tmp_ctx);
2573                 return LDB_ERR_OPERATIONS_ERROR;
2574         }
2575
2576         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
2577                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
2578                                    LDB_SCOPE_BASE,
2579                                    NULL, NULL,
2580                                    NULL,
2581                                    res, ldb_search_default_callback,
2582                                    NULL);
2583         if (ret != LDB_SUCCESS) {
2584                 talloc_free(tmp_ctx);
2585                 return ret;
2586         }
2587
2588         p_ctrl = talloc(req, struct dsdb_control_current_partition);
2589         if (p_ctrl == NULL) {
2590                 talloc_free(res);
2591                 return LDB_ERR_OPERATIONS_ERROR;
2592         }
2593         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
2594         p_ctrl->dn = dn;
2595         
2596
2597         ret = ldb_request_add_control(req,
2598                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
2599                                       false, p_ctrl);
2600         if (ret != LDB_SUCCESS) {
2601                 talloc_free(tmp_ctx);
2602                 return ret;
2603         }
2604         
2605         /* Run the new request */
2606         ret = ldb_request(ldb, req);
2607         
2608         if (ret == LDB_SUCCESS) {
2609                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2610         }
2611
2612         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2613                 /* it hasn't been created yet, which means
2614                    an implicit value of zero */
2615                 *uSN = 0;
2616                 talloc_free(tmp_ctx);
2617                 return LDB_SUCCESS;
2618         }
2619
2620         if (ret != LDB_SUCCESS) {
2621                 talloc_free(tmp_ctx);
2622                 return ret;
2623         }
2624
2625         if (res->count < 1) {
2626                 *uSN = 0;
2627                 if (urgent_uSN) {
2628                         *urgent_uSN = 0;
2629                 }
2630         } else {
2631                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
2632                 if (urgent_uSN) {
2633                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
2634                 }
2635         }
2636
2637         talloc_free(tmp_ctx);
2638
2639         return LDB_SUCCESS;     
2640 }
2641
2642 int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
2643                                                    const struct drsuapi_DsReplicaCursor2 *c2)
2644 {
2645         return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
2646 }
2647
2648 int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
2649                                     const struct drsuapi_DsReplicaCursor *c2)
2650 {
2651         return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
2652 }
2653
2654
2655 /*
2656   see if a computer identified by its invocationId is a RODC
2657 */
2658 int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
2659 {
2660         /* 1) find the DN for this servers NTDSDSA object
2661            2) search for the msDS-isRODC attribute
2662            3) if not present then not a RODC
2663            4) if present and TRUE then is a RODC
2664         */
2665         struct ldb_dn *config_dn;
2666         const char *attrs[] = { "msDS-isRODC", NULL };
2667         int ret;
2668         struct ldb_result *res;
2669         TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
2670
2671         config_dn = ldb_get_config_basedn(sam_ctx);
2672         if (!config_dn) {
2673                 talloc_free(tmp_ctx);
2674                 return LDB_ERR_OPERATIONS_ERROR;
2675         }
2676
2677         ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
2678                           DSDB_SEARCH_ONE_ONLY, "objectGUID=%s", GUID_string(tmp_ctx, objectGUID));
2679
2680         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2681                 *is_rodc = false;
2682                 talloc_free(tmp_ctx);
2683                 return LDB_SUCCESS;
2684         }
2685
2686         if (ret != LDB_SUCCESS) {
2687                 DEBUG(1,(("Failed to find our own NTDS Settings object by objectGUID=%s!\n"),
2688                          GUID_string(tmp_ctx, objectGUID)));
2689                 *is_rodc = false;
2690                 talloc_free(tmp_ctx);
2691                 return ret;
2692         }
2693
2694         ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
2695         *is_rodc = (ret == 1);
2696
2697         talloc_free(tmp_ctx);
2698         return LDB_SUCCESS;
2699 }
2700
2701
2702 /*
2703   see if we are a RODC
2704 */
2705 int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
2706 {
2707         const struct GUID *objectGUID;
2708         int ret;
2709         bool *cached;
2710
2711         /* see if we have a cached copy */
2712         cached = (bool *)ldb_get_opaque(sam_ctx, "cache.am_rodc");
2713         if (cached) {
2714                 *am_rodc = *cached;
2715                 return LDB_SUCCESS;
2716         }
2717
2718         objectGUID = samdb_ntds_objectGUID(sam_ctx);
2719         if (!objectGUID) {
2720                 return LDB_ERR_OPERATIONS_ERROR;
2721         }
2722
2723         ret = samdb_is_rodc(sam_ctx, objectGUID, am_rodc);
2724         if (ret != LDB_SUCCESS) {
2725                 return ret;
2726         }
2727
2728         cached = talloc(sam_ctx, bool);
2729         if (cached == NULL) {
2730                 return LDB_ERR_OPERATIONS_ERROR;
2731         }
2732         *cached = *am_rodc;
2733
2734         ret = ldb_set_opaque(sam_ctx, "cache.am_rodc", cached);
2735         if (ret != LDB_SUCCESS) {
2736                 talloc_free(cached);
2737                 return LDB_ERR_OPERATIONS_ERROR;
2738         }
2739
2740         return LDB_SUCCESS;
2741 }
2742
2743
2744
2745 /*
2746   return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1 
2747
2748   flags are DS_NTDS_OPTION_*
2749 */
2750 int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
2751 {
2752         TALLOC_CTX *tmp_ctx;
2753         const char *attrs[] = { "options", NULL };
2754         int ret;
2755         struct ldb_result *res;
2756
2757         tmp_ctx = talloc_new(ldb);
2758         if (tmp_ctx == NULL) {
2759                 goto failed;
2760         }
2761
2762         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
2763         if (ret) {
2764                 goto failed;
2765         }
2766
2767         if (res->count != 1) {
2768                 goto failed;
2769         }
2770
2771         *options = samdb_result_uint(res->msgs[0], "options", 0);
2772
2773         talloc_free(tmp_ctx);
2774
2775         return LDB_SUCCESS;
2776
2777 failed:
2778         DEBUG(1,("Failed to find our own NTDS Settings options in the ldb!\n"));
2779         talloc_free(tmp_ctx);
2780         return LDB_ERR_NO_SUCH_OBJECT;
2781 }
2782
2783 const char* samdb_ntds_object_category(TALLOC_CTX *tmp_ctx, struct ldb_context *ldb)
2784 {
2785         const char *attrs[] = { "objectCategory", NULL };
2786         int ret;
2787         struct ldb_result *res;
2788
2789         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
2790         if (ret) {
2791                 goto failed;
2792         }
2793
2794         if (res->count != 1) {
2795                 goto failed;
2796         }
2797
2798         return samdb_result_string(res->msgs[0], "objectCategory", NULL);
2799
2800 failed:
2801         DEBUG(1,("Failed to find our own NTDS Settings objectCategory in the ldb!\n"));
2802         return NULL;
2803 }
2804
2805 /*
2806  * Function which generates a "lDAPDisplayName" attribute from a "CN" one.
2807  * Algorithm implemented according to MS-ADTS 3.1.1.2.3.4
2808  */
2809 const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn)
2810 {
2811         char **tokens, *ret;
2812         size_t i;
2813
2814         tokens = str_list_make(mem_ctx, cn, " -_");
2815         if (tokens == NULL)
2816                 return NULL;
2817
2818         /* "tolower()" and "toupper()" should also work properly on 0x00 */
2819         tokens[0][0] = tolower(tokens[0][0]);
2820         for (i = 1; i < str_list_length((const char **)tokens); i++)
2821                 tokens[i][0] = toupper(tokens[i][0]);
2822
2823         ret = talloc_strdup(mem_ctx, tokens[0]);
2824         for (i = 1; i < str_list_length((const char **)tokens); i++)
2825                 ret = talloc_asprintf_append_buffer(ret, "%s", tokens[i]);
2826
2827         talloc_free(tokens);
2828
2829         return ret;
2830 }
2831
2832 /*
2833   return domain functional level
2834   returns DS_DOMAIN_FUNCTION_*
2835  */
2836 int dsdb_functional_level(struct ldb_context *ldb)
2837 {
2838         int *domainFunctionality =
2839                 talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
2840         if (!domainFunctionality) {
2841                 DEBUG(0,(__location__ ": WARNING: domainFunctionality not setup\n"));
2842                 return DS_DOMAIN_FUNCTION_2000;
2843         }
2844         return *domainFunctionality;
2845 }
2846
2847 /*
2848   set a GUID in an extended DN structure
2849  */
2850 int dsdb_set_extended_dn_guid(struct ldb_dn *dn, const struct GUID *guid, const char *component_name)
2851 {
2852         struct ldb_val v;
2853         NTSTATUS status;
2854         int ret;
2855
2856         status = GUID_to_ndr_blob(guid, dn, &v);
2857         if (!NT_STATUS_IS_OK(status)) {
2858                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
2859         }
2860
2861         ret = ldb_dn_set_extended_component(dn, component_name, &v);
2862         data_blob_free(&v);
2863         return ret;
2864 }
2865
2866 /*
2867   return a GUID from a extended DN structure
2868  */
2869 NTSTATUS dsdb_get_extended_dn_guid(struct ldb_dn *dn, struct GUID *guid, const char *component_name)
2870 {
2871         const struct ldb_val *v;
2872
2873         v = ldb_dn_get_extended_component(dn, component_name);
2874         if (v == NULL) {
2875                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2876         }
2877
2878         return GUID_from_ndr_blob(v, guid);
2879 }
2880
2881 /*
2882   return a uint64_t from a extended DN structure
2883  */
2884 NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const char *component_name)
2885 {
2886         const struct ldb_val *v;
2887         char *s;
2888
2889         v = ldb_dn_get_extended_component(dn, component_name);
2890         if (v == NULL) {
2891                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2892         }
2893         s = talloc_strndup(dn, (const char *)v->data, v->length);
2894         NT_STATUS_HAVE_NO_MEMORY(s);
2895
2896         *val = strtoull(s, NULL, 0);
2897
2898         talloc_free(s);
2899         return NT_STATUS_OK;
2900 }
2901
2902 /*
2903   return a NTTIME from a extended DN structure
2904  */
2905 NTSTATUS dsdb_get_extended_dn_nttime(struct ldb_dn *dn, NTTIME *nttime, const char *component_name)
2906 {
2907         return dsdb_get_extended_dn_uint64(dn, nttime, component_name);
2908 }
2909
2910 /*
2911   return a uint32_t from a extended DN structure
2912  */
2913 NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const char *component_name)
2914 {
2915         const struct ldb_val *v;
2916         char *s;
2917
2918         v = ldb_dn_get_extended_component(dn, component_name);
2919         if (v == NULL) {
2920                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2921         }
2922
2923         s = talloc_strndup(dn, (const char *)v->data, v->length);
2924         NT_STATUS_HAVE_NO_MEMORY(s);
2925
2926         *val = strtoul(s, NULL, 0);
2927
2928         talloc_free(s);
2929         return NT_STATUS_OK;
2930 }
2931
2932 /*
2933   return a dom_sid from a extended DN structure
2934  */
2935 NTSTATUS dsdb_get_extended_dn_sid(struct ldb_dn *dn, struct dom_sid *sid, const char *component_name)
2936 {
2937         const struct ldb_val *sid_blob;
2938         struct TALLOC_CTX *tmp_ctx;
2939         enum ndr_err_code ndr_err;
2940
2941         sid_blob = ldb_dn_get_extended_component(dn, "SID");
2942         if (!sid_blob) {
2943                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2944         }
2945
2946         tmp_ctx = talloc_new(NULL);
2947
2948         ndr_err = ndr_pull_struct_blob_all(sid_blob, tmp_ctx, NULL, sid,
2949                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
2950         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2951                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2952                 talloc_free(tmp_ctx);
2953                 return status;
2954         }
2955
2956         talloc_free(tmp_ctx);
2957         return NT_STATUS_OK;
2958 }
2959
2960
2961 /*
2962   return RMD_FLAGS directly from a ldb_dn
2963   returns 0 if not found
2964  */
2965 uint32_t dsdb_dn_rmd_flags(struct ldb_dn *dn)
2966 {
2967         const struct ldb_val *v;
2968         char buf[32];
2969         v = ldb_dn_get_extended_component(dn, "RMD_FLAGS");
2970         if (!v || v->length > sizeof(buf)-1) return 0;
2971         strncpy(buf, (const char *)v->data, v->length);
2972         buf[v->length] = 0;
2973         return strtoul(buf, NULL, 10);
2974 }
2975
2976 /*
2977   return RMD_FLAGS directly from a ldb_val for a DN
2978   returns 0 if RMD_FLAGS is not found
2979  */
2980 uint32_t dsdb_dn_val_rmd_flags(struct ldb_val *val)
2981 {
2982         const char *p;
2983         uint32_t flags;
2984         char *end;
2985
2986         if (val->length < 13) {
2987                 return 0;
2988         }
2989         p = memmem(val->data, val->length-2, "<RMD_FLAGS=", 11);
2990         if (!p) {
2991                 return 0;
2992         }
2993         flags = strtoul(p+11, &end, 10);
2994         if (!end || *end != '>') {
2995                 /* it must end in a > */
2996                 return 0;
2997         }
2998         return flags;
2999 }
3000
3001 /*
3002   return true if a ldb_val containing a DN in storage form is deleted
3003  */
3004 bool dsdb_dn_is_deleted_val(struct ldb_val *val)
3005 {
3006         return (dsdb_dn_val_rmd_flags(val) & DSDB_RMD_FLAG_DELETED) != 0;
3007 }
3008
3009 /*
3010   return true if a ldb_val containing a DN in storage form is
3011   in the upgraded w2k3 linked attribute format
3012  */
3013 bool dsdb_dn_is_upgraded_link_val(struct ldb_val *val)
3014 {
3015         return memmem(val->data, val->length, "<RMD_ADDTIME=", 13) != NULL;
3016 }
3017
3018 /*
3019   return a DN for a wellknown GUID
3020  */
3021 int dsdb_wellknown_dn(struct ldb_context *samdb, TALLOC_CTX *mem_ctx,
3022                       struct ldb_dn *nc_root, const char *wk_guid,
3023                       struct ldb_dn **wkguid_dn)
3024 {
3025         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3026         const char *attrs[] = { NULL };
3027         int ret;
3028         struct ldb_dn *dn;
3029         struct ldb_result *res;
3030
3031         /* construct the magic WKGUID DN */
3032         dn = ldb_dn_new_fmt(tmp_ctx, samdb, "<WKGUID=%s,%s>",
3033                             wk_guid, ldb_dn_get_linearized(nc_root));
3034         if (!wkguid_dn) {
3035                 talloc_free(tmp_ctx);
3036                 return LDB_ERR_OPERATIONS_ERROR;
3037         }
3038
3039         ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs, DSDB_SEARCH_SHOW_DELETED);
3040         if (ret != LDB_SUCCESS) {
3041                 talloc_free(tmp_ctx);
3042                 return ret;
3043         }
3044
3045         (*wkguid_dn) = talloc_steal(mem_ctx, res->msgs[0]->dn);
3046         talloc_free(tmp_ctx);
3047         return LDB_SUCCESS;
3048 }
3049
3050
3051 static int dsdb_dn_compare_ptrs(struct ldb_dn **dn1, struct ldb_dn **dn2)
3052 {
3053         return ldb_dn_compare(*dn1, *dn2);
3054 }
3055
3056 /*
3057   find a NC root given a DN within the NC
3058  */
3059 int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3060                       struct ldb_dn **nc_root)
3061 {
3062         const char *root_attrs[] = { "namingContexts", NULL };
3063         TALLOC_CTX *tmp_ctx;
3064         int ret;
3065         struct ldb_message_element *el;
3066         struct ldb_result *root_res;
3067         int i;
3068         struct ldb_dn **nc_dns;
3069
3070         tmp_ctx = talloc_new(samdb);
3071         if (tmp_ctx == NULL) {
3072                 return LDB_ERR_OPERATIONS_ERROR;
3073         }
3074
3075         ret = ldb_search(samdb, tmp_ctx, &root_res,
3076                          ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
3077         if (ret) {
3078                 DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
3079                 talloc_free(tmp_ctx);
3080                 return ret;
3081        }
3082
3083        el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
3084        if (!el) {
3085                DEBUG(1,("Finding namingContexts element in root_res failed: %s\n",
3086                         ldb_errstring(samdb)));
3087                talloc_free(tmp_ctx);
3088                return LDB_ERR_NO_SUCH_ATTRIBUTE;
3089        }
3090
3091        nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
3092        if (!nc_dns) {
3093                talloc_free(tmp_ctx);
3094                return LDB_ERR_OPERATIONS_ERROR;
3095        }
3096
3097        for (i=0; i<el->num_values; i++) {
3098                nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
3099                if (nc_dns[i] == NULL) {
3100                        talloc_free(tmp_ctx);
3101                        return LDB_ERR_OPERATIONS_ERROR;
3102                }
3103        }
3104
3105        TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);
3106
3107        for (i=0; i<el->num_values; i++) {
3108                if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
3109                        (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
3110                        talloc_free(tmp_ctx);
3111                        return LDB_SUCCESS;
3112                }
3113        }
3114
3115        talloc_free(tmp_ctx);
3116        return LDB_ERR_NO_SUCH_OBJECT;
3117 }
3118
3119
3120 /*
3121   find the deleted objects DN for any object, by looking for the NC
3122   root, then looking up the wellknown GUID
3123  */
3124 int dsdb_get_deleted_objects_dn(struct ldb_context *ldb,
3125                                 TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
3126                                 struct ldb_dn **do_dn)
3127 {
3128         struct ldb_dn *nc_root;
3129         int ret;
3130
3131         ret = dsdb_find_nc_root(ldb, mem_ctx, obj_dn, &nc_root);
3132         if (ret != LDB_SUCCESS) {
3133                 return ret;
3134         }
3135
3136         ret = dsdb_wellknown_dn(ldb, mem_ctx, nc_root, DS_GUID_DELETED_OBJECTS_CONTAINER, do_dn);
3137         talloc_free(nc_root);
3138         return ret;
3139 }
3140
3141 /*
3142   return the tombstoneLifetime, in days
3143  */
3144 int dsdb_tombstone_lifetime(struct ldb_context *ldb, uint32_t *lifetime)
3145 {
3146         struct ldb_dn *dn;
3147         dn = ldb_get_config_basedn(ldb);
3148         if (!dn) {
3149                 return LDB_ERR_NO_SUCH_OBJECT;
3150         }
3151         dn = ldb_dn_copy(ldb, dn);
3152         if (!dn) {
3153                 return LDB_ERR_OPERATIONS_ERROR;
3154         }
3155         /* see MS-ADTS section 7.1.1.2.4.1.1. There doesn't appear to
3156          be a wellknown GUID for this */
3157         if (!ldb_dn_add_child_fmt(dn, "CN=Directory Service,CN=Windows NT,CN=Services")) {
3158                 talloc_free(dn);
3159                 return LDB_ERR_OPERATIONS_ERROR;
3160         }
3161
3162         *lifetime = samdb_search_uint(ldb, dn, 180, dn, "tombstoneLifetime", "objectClass=nTDSService");
3163         talloc_free(dn);
3164         return LDB_SUCCESS;
3165 }
3166
3167 /*
3168   compare a ldb_val to a string case insensitively
3169  */
3170 int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
3171 {
3172         size_t len = strlen(s);
3173         int ret;
3174         if (len > v->length) return 1;
3175         ret = strncasecmp(s, (const char *)v->data, v->length);
3176         if (ret != 0) return ret;
3177         if (v->length > len && v->data[len] != 0) {
3178                 return -1;
3179         }
3180         return 0;
3181 }
3182
3183
3184 /*
3185   load the UDV for a partition in v2 format
3186   The list is returned sorted, and with our local cursor added
3187  */
3188 int dsdb_load_udv_v2(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
3189                      struct drsuapi_DsReplicaCursor2 **cursors, uint32_t *count)
3190 {
3191         static const char *attrs[] = { "replUpToDateVector", NULL };
3192         struct ldb_result *r;
3193         const struct ldb_val *ouv_value;
3194         unsigned int i;
3195         int ret;
3196         uint64_t highest_usn;
3197         const struct GUID *our_invocation_id;
3198         struct timeval now = timeval_current();
3199
3200         ret = ldb_search(samdb, mem_ctx, &r, dn, LDB_SCOPE_BASE, attrs, NULL);
3201         if (ret != LDB_SUCCESS) {
3202                 return ret;
3203         }
3204
3205         ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
3206         if (ouv_value) {
3207                 enum ndr_err_code ndr_err;
3208                 struct replUpToDateVectorBlob ouv;
3209
3210                 ndr_err = ndr_pull_struct_blob(ouv_value, r,
3211                                                lp_iconv_convenience(ldb_get_opaque(samdb, "loadparm")), &ouv,
3212                                                (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
3213                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3214                         talloc_free(r);
3215                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
3216                 }
3217                 if (ouv.version != 2) {
3218                         /* we always store as version 2, and
3219                          * replUpToDateVector is not replicated
3220                          */
3221                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
3222                 }
3223
3224                 *count = ouv.ctr.ctr2.count;
3225                 *cursors = talloc_steal(mem_ctx, ouv.ctr.ctr2.cursors);
3226         } else {
3227                 *count = 0;
3228                 *cursors = NULL;
3229         }
3230
3231         talloc_free(r);
3232
3233         our_invocation_id = samdb_ntds_invocation_id(samdb);
3234         if (!our_invocation_id) {
3235                 DEBUG(0,(__location__ ": No invocationID on samdb - %s\n", ldb_errstring(samdb)));
3236                 talloc_free(*cursors);
3237                 return LDB_ERR_OPERATIONS_ERROR;
3238         }
3239
3240         ret = dsdb_load_partition_usn(samdb, dn, &highest_usn, NULL);
3241         if (ret != LDB_SUCCESS) {
3242                 /* nothing to add - this can happen after a vampire */
3243                 TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
3244                 return LDB_SUCCESS;
3245         }
3246
3247         for (i=0; i<*count; i++) {
3248                 if (GUID_equal(our_invocation_id, &(*cursors)[i].source_dsa_invocation_id)) {
3249                         (*cursors)[i].highest_usn = highest_usn;
3250                         (*cursors)[i].last_sync_success = timeval_to_nttime(&now);
3251                         TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
3252                         return LDB_SUCCESS;
3253                 }
3254         }
3255
3256         (*cursors) = talloc_realloc(mem_ctx, *cursors, struct drsuapi_DsReplicaCursor2, (*count)+1);
3257         if (! *cursors) {
3258                 return LDB_ERR_OPERATIONS_ERROR;
3259         }
3260
3261         (*cursors)[*count].source_dsa_invocation_id = *our_invocation_id;
3262         (*cursors)[*count].highest_usn = highest_usn;
3263         (*cursors)[*count].last_sync_success = timeval_to_nttime(&now);
3264         (*count)++;
3265
3266         TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
3267
3268         return LDB_SUCCESS;
3269 }
3270
3271 /*
3272   load the UDV for a partition in version 1 format
3273   The list is returned sorted, and with our local cursor added
3274  */
3275 int dsdb_load_udv_v1(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
3276                      struct drsuapi_DsReplicaCursor **cursors, uint32_t *count)
3277 {
3278         struct drsuapi_DsReplicaCursor2 *v2;
3279         unsigned int i;
3280         int ret;
3281
3282         ret = dsdb_load_udv_v2(samdb, dn, mem_ctx, &v2, count);
3283         if (ret != LDB_SUCCESS) {
3284                 return ret;
3285         }
3286
3287         if (*count == 0) {
3288                 talloc_free(v2);
3289                 *cursors = NULL;
3290                 return LDB_SUCCESS;
3291         }
3292
3293         *cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, *count);
3294         if (*cursors == NULL) {
3295                 talloc_free(v2);
3296                 return LDB_ERR_OPERATIONS_ERROR;
3297         }
3298
3299         for (i=0; i<*count; i++) {
3300                 (*cursors)[i].source_dsa_invocation_id = v2[i].source_dsa_invocation_id;
3301                 (*cursors)[i].highest_usn = v2[i].highest_usn;
3302         }
3303         talloc_free(v2);
3304         return LDB_SUCCESS;
3305 }
3306
3307 /*
3308   add a set of controls to a ldb_request structure based on a set of
3309   flags. See util.h for a list of available flags
3310  */
3311 int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
3312 {
3313         int ret;
3314         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
3315                 struct ldb_search_options_control *options;
3316                 /* Using the phantom root control allows us to search all partitions */
3317                 options = talloc(req, struct ldb_search_options_control);
3318                 if (options == NULL) {
3319                         return LDB_ERR_OPERATIONS_ERROR;
3320                 }
3321                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
3322
3323                 ret = ldb_request_add_control(req,
3324                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
3325                                               true, options);
3326                 if (ret != LDB_SUCCESS) {
3327                         return ret;
3328                 }
3329         }
3330
3331         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
3332                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
3333                 if (ret != LDB_SUCCESS) {
3334                         return ret;
3335                 }
3336         }
3337
3338         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
3339                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
3340                 if (ret != LDB_SUCCESS) {
3341                         return ret;
3342                 }
3343         }
3344
3345         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
3346                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
3347                 if (!extended_ctrl) {
3348                         return LDB_ERR_OPERATIONS_ERROR;
3349                 }
3350                 extended_ctrl->type = 1;
3351
3352                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
3353                 if (ret != LDB_SUCCESS) {
3354                         return ret;
3355                 }
3356         }
3357
3358         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
3359                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
3360                 if (ret != LDB_SUCCESS) {
3361                         return ret;
3362                 }
3363         }
3364
3365         if (dsdb_flags & DSDB_MODIFY_RELAX) {
3366                 ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
3367                 if (ret != LDB_SUCCESS) {
3368                         return ret;
3369                 }
3370         }
3371
3372         if (dsdb_flags & DSDB_MODIFY_PERMISSIVE) {
3373                 ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID, false, NULL);
3374                 if (ret != LDB_SUCCESS) {
3375                         return ret;
3376                 }
3377         }
3378
3379         if (dsdb_flags & DSDB_FLAG_AS_SYSTEM) {
3380                 ret = ldb_request_add_control(req, LDB_CONTROL_AS_SYSTEM_OID, false, NULL);
3381                 if (ret != LDB_SUCCESS) {
3382                         return ret;
3383                 }
3384         }
3385
3386         return LDB_SUCCESS;
3387 }
3388
3389 /*
3390   a modify with a set of controls
3391 */
3392 int dsdb_modify(struct ldb_context *ldb, const struct ldb_message *message,
3393                 uint32_t dsdb_flags)
3394 {
3395         struct ldb_request *req;
3396         int ret;
3397
3398         ret = ldb_build_mod_req(&req, ldb, ldb,
3399                                 message,
3400                                 NULL,
3401                                 NULL,
3402                                 ldb_op_default_callback,
3403                                 NULL);
3404
3405         if (ret != LDB_SUCCESS) return ret;
3406
3407         ret = dsdb_request_add_controls(req, dsdb_flags);
3408         if (ret != LDB_SUCCESS) {
3409                 talloc_free(req);
3410                 return ret;
3411         }
3412
3413         ret = dsdb_autotransaction_request(ldb, req);
3414
3415         talloc_free(req);
3416         return ret;
3417 }
3418
3419 /*
3420   like dsdb_modify() but set all the element flags to
3421   LDB_FLAG_MOD_REPLACE
3422  */
3423 int dsdb_replace(struct ldb_context *ldb, struct ldb_message *msg, uint32_t dsdb_flags)
3424 {
3425         unsigned int i;
3426
3427         /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
3428         for (i=0;i<msg->num_elements;i++) {
3429                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
3430         }
3431
3432         return dsdb_modify(ldb, msg, dsdb_flags);
3433 }
3434
3435
3436 /*
3437   search for attrs on one DN, allowing for dsdb_flags controls
3438  */
3439 int dsdb_search_dn(struct ldb_context *ldb,
3440                    TALLOC_CTX *mem_ctx,
3441                    struct ldb_result **_res,
3442                    struct ldb_dn *basedn,
3443                    const char * const *attrs,
3444                    uint32_t dsdb_flags)
3445 {
3446         int ret;
3447         struct ldb_request *req;
3448         struct ldb_result *res;
3449
3450         res = talloc_zero(mem_ctx, struct ldb_result);
3451         if (!res) {
3452                 return LDB_ERR_OPERATIONS_ERROR;
3453         }
3454
3455         ret = ldb_build_search_req(&req, ldb, res,
3456                                    basedn,
3457                                    LDB_SCOPE_BASE,
3458                                    NULL,
3459                                    attrs,
3460                                    NULL,
3461                                    res,
3462                                    ldb_search_default_callback,
3463                                    NULL);
3464         if (ret != LDB_SUCCESS) {
3465                 talloc_free(res);
3466                 return ret;
3467         }
3468
3469         ret = dsdb_request_add_controls(req, dsdb_flags);
3470         if (ret != LDB_SUCCESS) {
3471                 talloc_free(res);
3472                 return ret;
3473         }
3474
3475         ret = ldb_request(ldb, req);
3476         if (ret == LDB_SUCCESS) {
3477                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
3478         }
3479
3480         talloc_free(req);
3481         if (ret != LDB_SUCCESS) {
3482                 talloc_free(res);
3483                 return ret;
3484         }
3485
3486         *_res = res;
3487         return LDB_SUCCESS;
3488 }
3489
3490 /*
3491   general search with dsdb_flags for controls
3492  */
3493 int dsdb_search(struct ldb_context *ldb,
3494                 TALLOC_CTX *mem_ctx,
3495                 struct ldb_result **_res,
3496                 struct ldb_dn *basedn,
3497                 enum ldb_scope scope,
3498                 const char * const *attrs,
3499                 uint32_t dsdb_flags,
3500                 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
3501 {
3502         int ret;
3503         struct ldb_request *req;
3504         struct ldb_result *res;
3505         va_list ap;
3506         char *expression = NULL;
3507         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3508
3509         res = talloc_zero(tmp_ctx, struct ldb_result);
3510         if (!res) {
3511                 talloc_free(tmp_ctx);
3512                 return LDB_ERR_OPERATIONS_ERROR;
3513         }
3514
3515         if (exp_fmt) {
3516                 va_start(ap, exp_fmt);
3517                 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
3518                 va_end(ap);
3519
3520                 if (!expression) {
3521                         talloc_free(tmp_ctx);
3522                         return LDB_ERR_OPERATIONS_ERROR;
3523                 }
3524         }
3525
3526         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
3527                                    basedn,
3528                                    scope,
3529                                    expression,
3530                                    attrs,
3531                                    NULL,
3532                                    res,
3533                                    ldb_search_default_callback,
3534                                    NULL);
3535         if (ret != LDB_SUCCESS) {
3536                 talloc_free(tmp_ctx);
3537                 return ret;
3538         }
3539
3540         ret = dsdb_request_add_controls(req, dsdb_flags);
3541         if (ret != LDB_SUCCESS) {
3542                 talloc_free(tmp_ctx);
3543                 return ret;
3544         }
3545
3546         ret = ldb_request(ldb, req);
3547         if (ret == LDB_SUCCESS) {
3548                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
3549         }
3550
3551         if (ret != LDB_SUCCESS) {
3552                 talloc_free(tmp_ctx);
3553                 return ret;
3554         }
3555
3556         if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
3557                 if (res->count == 0) {
3558                         talloc_free(tmp_ctx);
3559                         return LDB_ERR_NO_SUCH_OBJECT;
3560                 }
3561                 if (res->count != 1) {
3562                         talloc_free(tmp_ctx);
3563                         return LDB_ERR_CONSTRAINT_VIOLATION;
3564                 }
3565         }
3566
3567         *_res = talloc_steal(mem_ctx, res);
3568         talloc_free(tmp_ctx);
3569
3570         return LDB_SUCCESS;
3571 }
3572
3573
3574 /*
3575   general search with dsdb_flags for controls
3576   returns exactly 1 record or an error
3577  */
3578 int dsdb_search_one(struct ldb_context *ldb,
3579                     TALLOC_CTX *mem_ctx,
3580                     struct ldb_message **msg,
3581                     struct ldb_dn *basedn,
3582                     enum ldb_scope scope,
3583                     const char * const *attrs,
3584                     uint32_t dsdb_flags,
3585                     const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
3586 {
3587         int ret;
3588         struct ldb_result *res;
3589         va_list ap;
3590         char *expression = NULL;
3591         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3592
3593         dsdb_flags |= DSDB_SEARCH_ONE_ONLY;
3594
3595         res = talloc_zero(tmp_ctx, struct ldb_result);
3596         if (!res) {
3597                 talloc_free(tmp_ctx);
3598                 return LDB_ERR_OPERATIONS_ERROR;
3599         }
3600
3601         if (exp_fmt) {
3602                 va_start(ap, exp_fmt);
3603                 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
3604                 va_end(ap);
3605
3606                 if (!expression) {
3607                         talloc_free(tmp_ctx);
3608                         return LDB_ERR_OPERATIONS_ERROR;
3609                 }
3610         }
3611
3612         ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
3613                           dsdb_flags, "%s", expression);
3614         if (ret != LDB_SUCCESS) {
3615                 talloc_free(tmp_ctx);
3616                 return ret;
3617         }
3618
3619         *msg = talloc_steal(mem_ctx, res->msgs[0]);
3620         talloc_free(tmp_ctx);
3621
3622         return LDB_SUCCESS;
3623 }
3624
3625 /* returns back the forest DNS name */
3626 const char *samdb_forest_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
3627 {
3628         const char *forest_name = ldb_dn_canonical_string(mem_ctx,
3629                                                           ldb_get_root_basedn(ldb));
3630         char *p;
3631
3632         if (forest_name == NULL) {
3633                 return NULL;
3634         }
3635
3636         p = strchr(forest_name, '/');
3637         if (p) {
3638                 *p = '\0';
3639         }
3640
3641         return forest_name;
3642 }
3643
3644 /*
3645    validate that an DSA GUID belongs to the specified user sid.
3646    The user SID must be a domain controller account (either RODC or
3647    RWDC)
3648  */
3649 int dsdb_validate_dsa_guid(struct ldb_context *ldb,
3650                            const struct GUID *dsa_guid,
3651                            const struct dom_sid *sid)
3652 {
3653         /* strategy:
3654             - find DN of record with the DSA GUID in the
3655               configuration partition (objectGUID)
3656             - remove "NTDS Settings" component from DN
3657             - do a base search on that DN for serverReference with
3658               extended-dn enabled
3659             - extract objectSID from resulting serverReference
3660               attribute
3661             - check this sid matches the sid argument
3662         */
3663         struct ldb_dn *config_dn;
3664         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3665         struct ldb_message *msg;
3666         const char *attrs1[] = { NULL };
3667         const char *attrs2[] = { "serverReference", NULL };
3668         int ret;
3669         struct ldb_dn *dn, *account_dn;
3670         struct dom_sid sid2;
3671         NTSTATUS status;
3672
3673         config_dn = ldb_get_config_basedn(ldb);
3674
3675         ret = dsdb_search_one(ldb, tmp_ctx, &msg, config_dn, LDB_SCOPE_SUBTREE,
3676                               attrs1, 0, "(&(objectGUID=%s)(objectClass=nTDSDSA))", GUID_string(tmp_ctx, dsa_guid));
3677         if (ret != LDB_SUCCESS) {
3678                 DEBUG(1,(__location__ ": Failed to find DSA objectGUID %s for sid %s\n",
3679                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
3680                 talloc_free(tmp_ctx);
3681                 return LDB_ERR_OPERATIONS_ERROR;
3682         }
3683         dn = msg->dn;
3684
3685         if (!ldb_dn_remove_child_components(dn, 1)) {
3686                 talloc_free(tmp_ctx);
3687                 return LDB_ERR_OPERATIONS_ERROR;
3688         }
3689
3690         ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE,
3691                               attrs2, DSDB_SEARCH_SHOW_EXTENDED_DN,
3692                               "(objectClass=server)");
3693         if (ret != LDB_SUCCESS) {
3694                 DEBUG(1,(__location__ ": Failed to find server record for DSA with objectGUID %s, sid %s\n",
3695                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
3696                 talloc_free(tmp_ctx);
3697                 return LDB_ERR_OPERATIONS_ERROR;
3698         }
3699
3700         account_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, msg, "serverReference");
3701         if (account_dn == NULL) {
3702                 DEBUG(1,(__location__ ": Failed to find account_dn for DSA with objectGUID %s, sid %s\n",
3703                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
3704                 talloc_free(tmp_ctx);
3705                 return LDB_ERR_OPERATIONS_ERROR;
3706         }
3707
3708         status = dsdb_get_extended_dn_sid(account_dn, &sid2, "SID");
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 DEBUG(1,(__location__ ": Failed to find SID for DSA with objectGUID %s, sid %s\n",
3711                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
3712                 talloc_free(tmp_ctx);
3713                 return LDB_ERR_OPERATIONS_ERROR;
3714         }
3715
3716         if (!dom_sid_equal(sid, &sid2)) {
3717                 /* someone is trying to spoof another account */
3718                 DEBUG(0,(__location__ ": Bad DSA objectGUID %s for sid %s - expected sid %s\n",
3719                          GUID_string(tmp_ctx, dsa_guid),
3720                          dom_sid_string(tmp_ctx, sid),
3721                          dom_sid_string(tmp_ctx, &sid2)));
3722                 talloc_free(tmp_ctx);
3723                 return LDB_ERR_OPERATIONS_ERROR;
3724         }
3725
3726         talloc_free(tmp_ctx);
3727         return LDB_SUCCESS;
3728 }
3729
3730 const char *rodc_fas_list[] = {"ms-PKI-DPAPIMasterKeys",
3731                                "ms-PKI-AccountCredentials",
3732                                "ms-PKI-RoamingTimeStamp",
3733                                "ms-FVE-KeyPackage",
3734                                "ms-FVE-RecoveryGuid",
3735                                "ms-FVE-RecoveryInformation",
3736                                "ms-FVE-RecoveryPassword",
3737                                "ms-FVE-VolumeGuid",
3738                                "ms-TPM-OwnerInformation",
3739                                NULL};
3740 /*
3741   check if the attribute belongs to the RODC filtered attribute set
3742 */
3743 bool dsdb_attr_in_rodc_fas(uint32_t replica_flags, const struct dsdb_attribute *sa)
3744 {
3745         int rodc_filtered_flags = SEARCH_FLAG_RODC_ATTRIBUTE | SEARCH_FLAG_CONFIDENTIAL;
3746         bool drs_write_replica = ((replica_flags & DRSUAPI_DRS_WRIT_REP) == 0);
3747
3748         if (drs_write_replica && (sa->searchFlags & rodc_filtered_flags)) {
3749                 return true;
3750         }
3751         if (drs_write_replica && is_attr_in_list(rodc_fas_list, sa->cn)) {
3752                 return true;
3753         }
3754         return false;
3755 }