s4-dsdb: Add missing header file for write() and close()
[gd/samba-autobuild/.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_module.h"
28 #include "ldb_errors.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../lib/crypto/crypto.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "libcli/security/security.h"
33 #include "librpc/gen_ndr/ndr_security.h"
34 #include "librpc/gen_ndr/ndr_misc.h"
35 #include "../libds/common/flags.h"
36 #include "dsdb/common/proto.h"
37 #include "libcli/ldap/ldap_ndr.h"
38 #include "param/param.h"
39 #include "libcli/auth/libcli_auth.h"
40 #include "librpc/gen_ndr/ndr_drsblobs.h"
41 #include "system/locale.h"
42 #include "system/filesys.h"
43 #include "lib/util/tsort.h"
44 #include "dsdb/common/util.h"
45 #include "lib/socket/socket.h"
46 #include "librpc/gen_ndr/irpc.h"
47 #include "libds/common/flag_mapping.h"
48 #include "../lib/util/util_runcmd.h"
49
50 /*
51   search the sam for the specified attributes in a specific domain, filter on
52   objectSid being in domain_sid.
53 */
54 int samdb_search_domain(struct ldb_context *sam_ldb,
55                         TALLOC_CTX *mem_ctx, 
56                         struct ldb_dn *basedn,
57                         struct ldb_message ***res,
58                         const char * const *attrs,
59                         const struct dom_sid *domain_sid,
60                         const char *format, ...)  _PRINTF_ATTRIBUTE(7,8)
61 {
62         va_list ap;
63         int i, count;
64
65         va_start(ap, format);
66         count = gendb_search_v(sam_ldb, mem_ctx, basedn,
67                                res, attrs, format, ap);
68         va_end(ap);
69
70         i=0;
71
72         while (i<count) {
73                 struct dom_sid *entry_sid;
74
75                 entry_sid = samdb_result_dom_sid(mem_ctx, (*res)[i], "objectSid");
76
77                 if ((entry_sid == NULL) ||
78                     (!dom_sid_in_domain(domain_sid, entry_sid))) {
79                         /* Delete that entry from the result set */
80                         (*res)[i] = (*res)[count-1];
81                         count -= 1;
82                         talloc_free(entry_sid);
83                         continue;
84                 }
85                 talloc_free(entry_sid);
86                 i += 1;
87         }
88
89         return count;
90 }
91
92 /*
93   search the sam for a single string attribute in exactly 1 record
94 */
95 const char *samdb_search_string_v(struct ldb_context *sam_ldb,
96                                   TALLOC_CTX *mem_ctx,
97                                   struct ldb_dn *basedn,
98                                   const char *attr_name,
99                                   const char *format, va_list ap) _PRINTF_ATTRIBUTE(5,0)
100 {
101         int count;
102         const char *attrs[2] = { NULL, NULL };
103         struct ldb_message **res = NULL;
104
105         attrs[0] = attr_name;
106
107         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
108         if (count > 1) {                
109                 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
110                          attr_name, format, count));
111         }
112         if (count != 1) {
113                 talloc_free(res);
114                 return NULL;
115         }
116
117         return ldb_msg_find_attr_as_string(res[0], attr_name, NULL);
118 }
119
120 /*
121   search the sam for a single string attribute in exactly 1 record
122 */
123 const char *samdb_search_string(struct ldb_context *sam_ldb,
124                                 TALLOC_CTX *mem_ctx,
125                                 struct ldb_dn *basedn,
126                                 const char *attr_name,
127                                 const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
128 {
129         va_list ap;
130         const char *str;
131
132         va_start(ap, format);
133         str = samdb_search_string_v(sam_ldb, mem_ctx, basedn, attr_name, format, ap);
134         va_end(ap);
135
136         return str;
137 }
138
139 struct ldb_dn *samdb_search_dn(struct ldb_context *sam_ldb,
140                                TALLOC_CTX *mem_ctx,
141                                struct ldb_dn *basedn,
142                                const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
143 {
144         va_list ap;
145         struct ldb_dn *ret;
146         struct ldb_message **res = NULL;
147         int count;
148
149         va_start(ap, format);
150         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, NULL, format, ap);
151         va_end(ap);
152
153         if (count != 1) return NULL;
154
155         ret = talloc_steal(mem_ctx, res[0]->dn);
156         talloc_free(res);
157
158         return ret;
159 }
160
161 /*
162   search the sam for a dom_sid attribute in exactly 1 record
163 */
164 struct dom_sid *samdb_search_dom_sid(struct ldb_context *sam_ldb,
165                                      TALLOC_CTX *mem_ctx,
166                                      struct ldb_dn *basedn,
167                                      const char *attr_name,
168                                      const char *format, ...) _PRINTF_ATTRIBUTE(5,6)
169 {
170         va_list ap;
171         int count;
172         struct ldb_message **res;
173         const char *attrs[2] = { NULL, NULL };
174         struct dom_sid *sid;
175
176         attrs[0] = attr_name;
177
178         va_start(ap, format);
179         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
180         va_end(ap);
181         if (count > 1) {                
182                 DEBUG(1,("samdb: search for %s %s not single valued (count=%d)\n", 
183                          attr_name, format, count));
184         }
185         if (count != 1) {
186                 talloc_free(res);
187                 return NULL;
188         }
189         sid = samdb_result_dom_sid(mem_ctx, res[0], attr_name);
190         talloc_free(res);
191         return sid;     
192 }
193
194 /*
195   return the count of the number of records in the sam matching the query
196 */
197 int samdb_search_count(struct ldb_context *sam_ldb,
198                        TALLOC_CTX *mem_ctx,
199                        struct ldb_dn *basedn,
200                        const char *format, ...) _PRINTF_ATTRIBUTE(4,5)
201 {
202         va_list ap;
203         const char *attrs[] = { NULL };
204         int ret;
205
206         va_start(ap, format);
207         ret = gendb_search_v(sam_ldb, mem_ctx, basedn, NULL, attrs, format, ap);
208         va_end(ap);
209
210         return ret;
211 }
212
213
214 /*
215   search the sam for a single integer attribute in exactly 1 record
216 */
217 unsigned int samdb_search_uint(struct ldb_context *sam_ldb,
218                          TALLOC_CTX *mem_ctx,
219                          unsigned int default_value,
220                          struct ldb_dn *basedn,
221                          const char *attr_name,
222                          const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
223 {
224         va_list ap;
225         int count;
226         struct ldb_message **res;
227         const char *attrs[2] = { NULL, NULL };
228
229         attrs[0] = attr_name;
230
231         va_start(ap, format);
232         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
233         va_end(ap);
234
235         if (count != 1) {
236                 return default_value;
237         }
238
239         return ldb_msg_find_attr_as_uint(res[0], attr_name, default_value);
240 }
241
242 /*
243   search the sam for a single signed 64 bit integer attribute in exactly 1 record
244 */
245 int64_t samdb_search_int64(struct ldb_context *sam_ldb,
246                            TALLOC_CTX *mem_ctx,
247                            int64_t default_value,
248                            struct ldb_dn *basedn,
249                            const char *attr_name,
250                            const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
251 {
252         va_list ap;
253         int count;
254         struct ldb_message **res;
255         const char *attrs[2] = { NULL, NULL };
256
257         attrs[0] = attr_name;
258
259         va_start(ap, format);
260         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
261         va_end(ap);
262
263         if (count != 1) {
264                 return default_value;
265         }
266
267         return ldb_msg_find_attr_as_int64(res[0], attr_name, default_value);
268 }
269
270 /*
271   search the sam for multipe records each giving a single string attribute
272   return the number of matches, or -1 on error
273 */
274 int samdb_search_string_multiple(struct ldb_context *sam_ldb,
275                                  TALLOC_CTX *mem_ctx,
276                                  struct ldb_dn *basedn,
277                                  const char ***strs,
278                                  const char *attr_name,
279                                  const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
280 {
281         va_list ap;
282         int count, i;
283         const char *attrs[2] = { NULL, NULL };
284         struct ldb_message **res = NULL;
285
286         attrs[0] = attr_name;
287
288         va_start(ap, format);
289         count = gendb_search_v(sam_ldb, mem_ctx, basedn, &res, attrs, format, ap);
290         va_end(ap);
291
292         if (count <= 0) {
293                 return count;
294         }
295
296         /* make sure its single valued */
297         for (i=0;i<count;i++) {
298                 if (res[i]->num_elements != 1) {
299                         DEBUG(1,("samdb: search for %s %s not single valued\n", 
300                                  attr_name, format));
301                         talloc_free(res);
302                         return -1;
303                 }
304         }
305
306         *strs = talloc_array(mem_ctx, const char *, count+1);
307         if (! *strs) {
308                 talloc_free(res);
309                 return -1;
310         }
311
312         for (i=0;i<count;i++) {
313                 (*strs)[i] = ldb_msg_find_attr_as_string(res[i], attr_name, NULL);
314         }
315         (*strs)[count] = NULL;
316
317         return count;
318 }
319
320 struct ldb_dn *samdb_result_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
321                                const char *attr, struct ldb_dn *default_value)
322 {
323         struct ldb_dn *ret_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, msg, attr);
324         if (!ret_dn) {
325                 return default_value;
326         }
327         return ret_dn;
328 }
329
330 /*
331   pull a rid from a objectSid in a result set. 
332 */
333 uint32_t samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
334                                    const char *attr, uint32_t default_value)
335 {
336         struct dom_sid *sid;
337         uint32_t rid;
338
339         sid = samdb_result_dom_sid(mem_ctx, msg, attr);
340         if (sid == NULL) {
341                 return default_value;
342         }
343         rid = sid->sub_auths[sid->num_auths-1];
344         talloc_free(sid);
345         return rid;
346 }
347
348 /*
349   pull a dom_sid structure from a objectSid in a result set. 
350 */
351 struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
352                                      const char *attr)
353 {
354         bool ok;
355         const struct ldb_val *v;
356         struct dom_sid *sid;
357         v = ldb_msg_find_ldb_val(msg, attr);
358         if (v == NULL) {
359                 return NULL;
360         }
361         sid = talloc(mem_ctx, struct dom_sid);
362         if (sid == NULL) {
363                 return NULL;
364         }
365         ok = sid_parse(v->data, v->length, sid);
366         if (!ok) {
367                 talloc_free(sid);
368                 return NULL;
369         }
370         return sid;
371 }
372
373 /*
374   pull a guid structure from a objectGUID in a result set. 
375 */
376 struct GUID samdb_result_guid(const struct ldb_message *msg, const char *attr)
377 {
378         const struct ldb_val *v;
379         struct GUID guid;
380         NTSTATUS status;
381
382         v = ldb_msg_find_ldb_val(msg, attr);
383         if (!v) return GUID_zero();
384
385         status = GUID_from_ndr_blob(v, &guid);
386         if (!NT_STATUS_IS_OK(status)) {
387                 return GUID_zero();
388         }
389
390         return guid;
391 }
392
393 /*
394   pull a sid prefix from a objectSid in a result set. 
395   this is used to find the domain sid for a user
396 */
397 struct dom_sid *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, 
398                                         const char *attr)
399 {
400         struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
401         if (!sid || sid->num_auths < 1) return NULL;
402         sid->num_auths--;
403         return sid;
404 }
405
406 /*
407   pull a NTTIME in a result set. 
408 */
409 NTTIME samdb_result_nttime(const struct ldb_message *msg, const char *attr,
410                            NTTIME default_value)
411 {
412         return ldb_msg_find_attr_as_uint64(msg, attr, default_value);
413 }
414
415 /*
416  * Windows stores 0 for lastLogoff.
417  * But when a MS DC return the lastLogoff (as Logoff Time)
418  * it returns 0x7FFFFFFFFFFFFFFF, not returning this value in this case
419  * cause windows 2008 and newer version to fail for SMB requests
420  */
421 NTTIME samdb_result_last_logoff(const struct ldb_message *msg)
422 {
423         NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "lastLogoff",0);
424
425         if (ret == 0)
426                 ret = 0x7FFFFFFFFFFFFFFFULL;
427
428         return ret;
429 }
430
431 /*
432  * Windows uses both 0 and 9223372036854775807 (0x7FFFFFFFFFFFFFFFULL) to
433  * indicate an account doesn't expire.
434  *
435  * When Windows initially creates an account, it sets
436  * accountExpires = 9223372036854775807 (0x7FFFFFFFFFFFFFFF).  However,
437  * when changing from an account having a specific expiration date to
438  * that account never expiring, it sets accountExpires = 0.
439  *
440  * Consolidate that logic here to allow clearer logic for account expiry in
441  * the rest of the code.
442  */
443 NTTIME samdb_result_account_expires(const struct ldb_message *msg)
444 {
445         NTTIME ret = ldb_msg_find_attr_as_uint64(msg, "accountExpires",
446                                                  0);
447
448         if (ret == 0)
449                 ret = 0x7FFFFFFFFFFFFFFFULL;
450
451         return ret;
452 }
453
454 /*
455   construct the allow_password_change field from the PwdLastSet attribute and the 
456   domain password settings
457 */
458 NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb, 
459                                           TALLOC_CTX *mem_ctx, 
460                                           struct ldb_dn *domain_dn, 
461                                           struct ldb_message *msg, 
462                                           const char *attr)
463 {
464         uint64_t attr_time = ldb_msg_find_attr_as_uint64(msg, attr, 0);
465         int64_t minPwdAge;
466
467         if (attr_time == 0) {
468                 return 0;
469         }
470
471         minPwdAge = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn, "minPwdAge", NULL);
472
473         /* yes, this is a -= not a += as minPwdAge is stored as the negative
474            of the number of 100-nano-seconds */
475         attr_time -= minPwdAge;
476
477         return attr_time;
478 }
479
480 /*
481   pull a samr_Password structutre from a result set. 
482 */
483 struct samr_Password *samdb_result_hash(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, const char *attr)
484 {
485         struct samr_Password *hash = NULL;
486         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
487         if (val && (val->length >= sizeof(hash->hash))) {
488                 hash = talloc(mem_ctx, struct samr_Password);
489                 memcpy(hash->hash, val->data, MIN(val->length, sizeof(hash->hash)));
490         }
491         return hash;
492 }
493
494 /*
495   pull an array of samr_Password structures from a result set.
496 */
497 unsigned int samdb_result_hashes(TALLOC_CTX *mem_ctx, const struct ldb_message *msg,
498                            const char *attr, struct samr_Password **hashes)
499 {
500         unsigned int count, i;
501         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
502
503         *hashes = NULL;
504         if (!val) {
505                 return 0;
506         }
507         count = val->length / 16;
508         if (count == 0) {
509                 return 0;
510         }
511
512         *hashes = talloc_array(mem_ctx, struct samr_Password, count);
513         if (! *hashes) {
514                 return 0;
515         }
516
517         for (i=0;i<count;i++) {
518                 memcpy((*hashes)[i].hash, (i*16)+(char *)val->data, 16);
519         }
520
521         return count;
522 }
523
524 NTSTATUS samdb_result_passwords_from_history(TALLOC_CTX *mem_ctx,
525                                              struct loadparm_context *lp_ctx,
526                                              struct ldb_message *msg,
527                                              unsigned int idx,
528                                              struct samr_Password **lm_pwd,
529                                              struct samr_Password **nt_pwd)
530 {
531         struct samr_Password *lmPwdHash, *ntPwdHash;
532
533         if (nt_pwd) {
534                 unsigned int num_nt;
535                 num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHistory", &ntPwdHash);
536                 if (num_nt <= idx) {
537                         *nt_pwd = NULL;
538                 } else {
539                         *nt_pwd = &ntPwdHash[idx];
540                 }
541         }
542         if (lm_pwd) {
543                 /* Ensure that if we have turned off LM
544                  * authentication, that we never use the LM hash, even
545                  * if we store it */
546                 if (lpcfg_lanman_auth(lp_ctx)) {
547                         unsigned int num_lm;
548                         num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHistory", &lmPwdHash);
549                         if (num_lm <= idx) {
550                                 *lm_pwd = NULL;
551                         } else {
552                                 *lm_pwd = &lmPwdHash[idx];
553                         }
554                 } else {
555                         *lm_pwd = NULL;
556                 }
557         }
558         return NT_STATUS_OK;
559 }
560
561 NTSTATUS samdb_result_passwords_no_lockout(TALLOC_CTX *mem_ctx,
562                                            struct loadparm_context *lp_ctx,
563                                            const struct ldb_message *msg,
564                                            struct samr_Password **lm_pwd,
565                                            struct samr_Password **nt_pwd)
566 {
567         struct samr_Password *lmPwdHash, *ntPwdHash;
568
569         if (nt_pwd) {
570                 unsigned int num_nt;
571                 num_nt = samdb_result_hashes(mem_ctx, msg, "unicodePwd", &ntPwdHash);
572                 if (num_nt == 0) {
573                         *nt_pwd = NULL;
574                 } else if (num_nt > 1) {
575                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
576                 } else {
577                         *nt_pwd = &ntPwdHash[0];
578                 }
579         }
580         if (lm_pwd) {
581                 /* Ensure that if we have turned off LM
582                  * authentication, that we never use the LM hash, even
583                  * if we store it */
584                 if (lpcfg_lanman_auth(lp_ctx)) {
585                         unsigned int num_lm;
586                         num_lm = samdb_result_hashes(mem_ctx, msg, "dBCSPwd", &lmPwdHash);
587                         if (num_lm == 0) {
588                                 *lm_pwd = NULL;
589                         } else if (num_lm > 1) {
590                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
591                         } else {
592                                 *lm_pwd = &lmPwdHash[0];
593                         }
594                 } else {
595                         *lm_pwd = NULL;
596                 }
597         }
598         return NT_STATUS_OK;
599 }
600
601 NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx,
602                                 struct loadparm_context *lp_ctx,
603                                 const struct ldb_message *msg,
604                                 struct samr_Password **lm_pwd,
605                                 struct samr_Password **nt_pwd)
606 {
607         uint16_t acct_flags;
608
609         acct_flags = samdb_result_acct_flags(msg,
610                                              "msDS-User-Account-Control-Computed");
611         /* Quit if the account was locked out. */
612         if (acct_flags & ACB_AUTOLOCK) {
613                 DEBUG(3,("samdb_result_passwords: Account for user %s was locked out.\n",
614                          ldb_dn_get_linearized(msg->dn)));
615                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
616         }
617
618         return samdb_result_passwords_no_lockout(mem_ctx, lp_ctx, msg,
619                                                  lm_pwd, nt_pwd);
620 }
621
622 /*
623   pull a samr_LogonHours structutre from a result set. 
624 */
625 struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *attr)
626 {
627         struct samr_LogonHours hours;
628         size_t units_per_week = 168;
629         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
630
631         ZERO_STRUCT(hours);
632
633         if (val) {
634                 units_per_week = val->length * 8;
635         }
636
637         hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week/8);
638         if (!hours.bits) {
639                 return hours;
640         }
641         hours.units_per_week = units_per_week;
642         memset(hours.bits, 0xFF, units_per_week/8);
643         if (val) {
644                 memcpy(hours.bits, val->data, val->length);
645         }
646
647         return hours;
648 }
649
650 /*
651   pull a set of account_flags from a result set. 
652
653   Naturally, this requires that userAccountControl and
654   (if not null) the attributes 'attr' be already
655   included in msg
656 */
657 uint32_t samdb_result_acct_flags(const struct ldb_message *msg, const char *attr)
658 {
659         uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
660         uint32_t attr_flags = 0;
661         uint32_t acct_flags = ds_uf2acb(userAccountControl);
662         if (attr) {
663                 attr_flags = ldb_msg_find_attr_as_uint(msg, attr, UF_ACCOUNTDISABLE);
664                 if (attr_flags == UF_ACCOUNTDISABLE) {
665                         DEBUG(0, ("Attribute %s not found, disabling account %s!\n", attr,
666                                   ldb_dn_get_linearized(msg->dn)));
667                 }
668                 acct_flags |= ds_uf2acb(attr_flags);
669         }
670
671         return acct_flags;
672 }
673
674 NTSTATUS samdb_result_parameters(TALLOC_CTX *mem_ctx,
675                                  struct ldb_message *msg,
676                                  const char *attr,
677                                  struct lsa_BinaryString *s)
678 {
679         int i;
680         const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr);
681
682         ZERO_STRUCTP(s);
683
684         if (!val) {
685                 return NT_STATUS_OK;
686         }
687
688         if ((val->length % 2) != 0) {
689                 /*
690                  * If the on-disk data is not even in length, we know
691                  * it is corrupt, and can not be safely pushed.  We
692                  * would either truncate, send either a un-initilaised
693                  * byte or send a forced zero byte
694                  */
695                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
696         }
697
698         s->array = talloc_array(mem_ctx, uint16_t, val->length/2);
699         if (!s->array) {
700                 return NT_STATUS_NO_MEMORY;
701         }
702         s->length = s->size = val->length;
703
704         /* The on-disk format is the 'network' format, being UTF16LE (sort of) */
705         for (i = 0; i < s->length / 2; i++) {
706                 s->array[i] = SVAL(val->data, i * 2);
707         }
708
709         return NT_STATUS_OK;
710 }
711
712 /* Find an attribute, with a particular value */
713
714 /* The current callers of this function expect a very specific
715  * behaviour: In particular, objectClass subclass equivilance is not
716  * wanted.  This means that we should not lookup the schema for the
717  * comparison function */
718 struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb, 
719                                                  const struct ldb_message *msg, 
720                                                  const char *name, const char *value)
721 {
722         unsigned int i;
723         struct ldb_message_element *el = ldb_msg_find_element(msg, name);
724
725         if (!el) {
726                 return NULL;
727         }
728
729         for (i=0;i<el->num_values;i++) {
730                 if (ldb_attr_cmp(value, (char *)el->values[i].data) == 0) {
731                         return el;
732                 }
733         }
734
735         return NULL;
736 }
737
738 static int samdb_find_or_add_attribute_ex(struct ldb_context *ldb,
739                                           struct ldb_message *msg,
740                                           const char *name,
741                                           const char *set_value,
742                                           bool *added)
743 {
744         int ret;
745         struct ldb_message_element *el;
746
747         el = ldb_msg_find_element(msg, name);
748         if (el) {
749                 if (added != NULL) {
750                         *added = false;
751                 }
752
753                 return LDB_SUCCESS;
754         }
755
756         ret = ldb_msg_add_string(msg, name, set_value);
757         if (ret != LDB_SUCCESS) {
758                 return ret;
759         }
760         msg->elements[msg->num_elements - 1].flags = LDB_FLAG_MOD_ADD;
761         if (added != NULL) {
762                 *added = true;
763         }
764         return LDB_SUCCESS;
765 }
766
767 int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
768 {
769         return samdb_find_or_add_attribute_ex(ldb, msg, name, set_value, NULL);
770 }
771
772 /*
773   add a dom_sid element to a message
774 */
775 int samdb_msg_add_dom_sid(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
776                           const char *attr_name, const struct dom_sid *sid)
777 {
778         struct ldb_val v;
779         enum ndr_err_code ndr_err;
780
781         ndr_err = ndr_push_struct_blob(&v, mem_ctx, 
782                                        sid,
783                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
784         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
785                 return ldb_operr(sam_ldb);
786         }
787         return ldb_msg_add_value(msg, attr_name, &v, NULL);
788 }
789
790
791 /*
792   add a delete element operation to a message
793 */
794 int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
795                          const char *attr_name)
796 {
797         /* we use an empty replace rather than a delete, as it allows for 
798            dsdb_replace() to be used everywhere */
799         return ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
800 }
801
802 /*
803   add an add attribute value to a message or enhance an existing attribute
804   which has the same name and the add flag set.
805 */
806 int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
807                          struct ldb_message *msg, const char *attr_name,
808                          const char *value)
809 {
810         struct ldb_message_element *el;
811         struct ldb_val val, *vals;
812         char *v;
813         unsigned int i;
814         bool found = false;
815         int ret;
816
817         v = talloc_strdup(mem_ctx, value);
818         if (v == NULL) {
819                 return ldb_oom(sam_ldb);
820         }
821
822         val.data = (uint8_t *) v;
823         val.length = strlen(v);
824
825         if (val.length == 0) {
826                 /* allow empty strings as non-existent attributes */
827                 return LDB_SUCCESS;
828         }
829
830         for (i = 0; i < msg->num_elements; i++) {
831                 el = &msg->elements[i];
832                 if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
833                     (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD)) {
834                         found = true;
835                         break;
836                 }
837         }
838         if (!found) {
839                 ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_ADD,
840                                         &el);
841                 if (ret != LDB_SUCCESS) {
842                         return ret;
843                 }
844         }
845
846         vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
847                               el->num_values + 1);
848         if (vals == NULL) {
849                 return ldb_oom(sam_ldb);
850         }
851         el->values = vals;
852         el->values[el->num_values] = val;
853         ++(el->num_values);
854
855         return LDB_SUCCESS;
856 }
857
858 /*
859   add a delete attribute value to a message or enhance an existing attribute
860   which has the same name and the delete flag set.
861 */
862 int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
863                          struct ldb_message *msg, const char *attr_name,
864                          const char *value)
865 {
866         struct ldb_message_element *el;
867         struct ldb_val val, *vals;
868         char *v;
869         unsigned int i;
870         bool found = false;
871         int ret;
872
873         v = talloc_strdup(mem_ctx, value);
874         if (v == NULL) {
875                 return ldb_oom(sam_ldb);
876         }
877
878         val.data = (uint8_t *) v;
879         val.length = strlen(v);
880
881         if (val.length == 0) {
882                 /* allow empty strings as non-existent attributes */
883                 return LDB_SUCCESS;
884         }
885
886         for (i = 0; i < msg->num_elements; i++) {
887                 el = &msg->elements[i];
888                 if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
889                     (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
890                         found = true;
891                         break;
892                 }
893         }
894         if (!found) {
895                 ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_DELETE,
896                                         &el);
897                 if (ret != LDB_SUCCESS) {
898                         return ret;
899                 }
900         }
901
902         vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
903                               el->num_values + 1);
904         if (vals == NULL) {
905                 return ldb_oom(sam_ldb);
906         }
907         el->values = vals;
908         el->values[el->num_values] = val;
909         ++(el->num_values);
910
911         return LDB_SUCCESS;
912 }
913
914 /*
915   add a int element to a message
916 */
917 int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
918                        const char *attr_name, int v)
919 {
920         const char *s = talloc_asprintf(mem_ctx, "%d", v);
921         if (s == NULL) {
922                 return ldb_oom(sam_ldb);
923         }
924         return ldb_msg_add_string(msg, attr_name, s);
925 }
926
927 /*
928  * Add an unsigned int element to a message
929  *
930  * The issue here is that we have not yet first cast to int32_t explicitly,
931  * before we cast to an signed int to printf() into the %d or cast to a
932  * int64_t before we then cast to a long long to printf into a %lld.
933  *
934  * There are *no* unsigned integers in Active Directory LDAP, even the RID
935  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
936  * (See the schema, and the syntax definitions in schema_syntax.c).
937  *
938  */
939 int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
940                        const char *attr_name, unsigned int v)
941 {
942         return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
943 }
944
945 /*
946   add a (signed) int64_t element to a message
947 */
948 int samdb_msg_add_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
949                         const char *attr_name, int64_t v)
950 {
951         const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
952         if (s == NULL) {
953                 return ldb_oom(sam_ldb);
954         }
955         return ldb_msg_add_string(msg, attr_name, s);
956 }
957
958 /*
959  * Add an unsigned int64_t (uint64_t) element to a message
960  *
961  * The issue here is that we have not yet first cast to int32_t explicitly,
962  * before we cast to an signed int to printf() into the %d or cast to a
963  * int64_t before we then cast to a long long to printf into a %lld.
964  *
965  * There are *no* unsigned integers in Active Directory LDAP, even the RID
966  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
967  * (See the schema, and the syntax definitions in schema_syntax.c).
968  *
969  */
970 int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
971                         const char *attr_name, uint64_t v)
972 {
973         return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
974 }
975
976 /*
977   add a samr_Password element to a message
978 */
979 int samdb_msg_add_hash(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
980                        const char *attr_name, const struct samr_Password *hash)
981 {
982         struct ldb_val val;
983         val.data = talloc_memdup(mem_ctx, hash->hash, 16);
984         if (!val.data) {
985                 return ldb_oom(sam_ldb);
986         }
987         val.length = 16;
988         return ldb_msg_add_value(msg, attr_name, &val, NULL);
989 }
990
991 /*
992   add a samr_Password array to a message
993 */
994 int samdb_msg_add_hashes(struct ldb_context *ldb,
995                          TALLOC_CTX *mem_ctx, struct ldb_message *msg,
996                          const char *attr_name, struct samr_Password *hashes,
997                          unsigned int count)
998 {
999         struct ldb_val val;
1000         unsigned int i;
1001         val.data = talloc_array_size(mem_ctx, 16, count);
1002         val.length = count*16;
1003         if (!val.data) {
1004                 return ldb_oom(ldb);
1005         }
1006         for (i=0;i<count;i++) {
1007                 memcpy(i*16 + (char *)val.data, hashes[i].hash, 16);
1008         }
1009         return ldb_msg_add_value(msg, attr_name, &val, NULL);
1010 }
1011
1012 /*
1013   add a acct_flags element to a message
1014 */
1015 int samdb_msg_add_acct_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1016                              const char *attr_name, uint32_t v)
1017 {
1018         return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, ds_acb2uf(v));
1019 }
1020
1021 /*
1022   add a logon_hours element to a message
1023 */
1024 int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1025                               const char *attr_name, struct samr_LogonHours *hours)
1026 {
1027         struct ldb_val val;
1028         val.length = hours->units_per_week / 8;
1029         val.data = hours->bits;
1030         return ldb_msg_add_value(msg, attr_name, &val, NULL);
1031 }
1032
1033 /*
1034   add a parameters element to a message
1035 */
1036 int samdb_msg_add_parameters(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1037                              const char *attr_name, struct lsa_BinaryString *parameters)
1038 {
1039         int i;
1040         struct ldb_val val;
1041         if ((parameters->length % 2) != 0) {
1042                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1043         }
1044
1045         val.data = talloc_array(mem_ctx, uint8_t, parameters->length);
1046         if (val.data == NULL) {
1047                 return LDB_ERR_OPERATIONS_ERROR;
1048         }
1049         val.length = parameters->length;
1050         for (i = 0; i < parameters->length / 2; i++) {
1051                 /*
1052                  * The on-disk format needs to be in the 'network'
1053                  * format, parmeters->array is a uint16_t array of
1054                  * length parameters->length / 2
1055                  */
1056                 SSVAL(val.data, i * 2, parameters->array[i]);
1057         }
1058         return ldb_msg_add_steal_value(msg, attr_name, &val);
1059 }
1060
1061 /*
1062  * Sets an unsigned int element in a message
1063  *
1064  * The issue here is that we have not yet first cast to int32_t explicitly,
1065  * before we cast to an signed int to printf() into the %d or cast to a
1066  * int64_t before we then cast to a long long to printf into a %lld.
1067  *
1068  * There are *no* unsigned integers in Active Directory LDAP, even the RID
1069  * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1070  * (See the schema, and the syntax definitions in schema_syntax.c).
1071  *
1072  */
1073 int samdb_msg_set_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
1074                        struct ldb_message *msg, const char *attr_name,
1075                        unsigned int v)
1076 {
1077         struct ldb_message_element *el;
1078
1079         el = ldb_msg_find_element(msg, attr_name);
1080         if (el) {
1081                 el->num_values = 0;
1082         }
1083         return samdb_msg_add_uint(sam_ldb, mem_ctx, msg, attr_name, v);
1084 }
1085
1086 /*
1087  * Handle ldb_request in transaction
1088  */
1089 int dsdb_autotransaction_request(struct ldb_context *sam_ldb,
1090                                  struct ldb_request *req)
1091 {
1092         int ret;
1093
1094         ret = ldb_transaction_start(sam_ldb);
1095         if (ret != LDB_SUCCESS) {
1096                 return ret;
1097         }
1098
1099         ret = ldb_request(sam_ldb, req);
1100         if (ret == LDB_SUCCESS) {
1101                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1102         }
1103
1104         if (ret == LDB_SUCCESS) {
1105                 return ldb_transaction_commit(sam_ldb);
1106         }
1107         ldb_transaction_cancel(sam_ldb);
1108
1109         return ret;
1110 }
1111
1112 /*
1113   return a default security descriptor
1114 */
1115 struct security_descriptor *samdb_default_security_descriptor(TALLOC_CTX *mem_ctx)
1116 {
1117         struct security_descriptor *sd;
1118
1119         sd = security_descriptor_initialise(mem_ctx);
1120
1121         return sd;
1122 }
1123
1124 struct ldb_dn *samdb_aggregate_schema_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx) 
1125 {
1126         struct ldb_dn *schema_dn = ldb_get_schema_basedn(sam_ctx);
1127         struct ldb_dn *aggregate_dn;
1128         if (!schema_dn) {
1129                 return NULL;
1130         }
1131
1132         aggregate_dn = ldb_dn_copy(mem_ctx, schema_dn);
1133         if (!aggregate_dn) {
1134                 return NULL;
1135         }
1136         if (!ldb_dn_add_child_fmt(aggregate_dn, "CN=Aggregate")) {
1137                 return NULL;
1138         }
1139         return aggregate_dn;
1140 }
1141
1142 struct ldb_dn *samdb_partitions_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1143 {
1144         struct ldb_dn *new_dn;
1145
1146         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1147         if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Partitions")) {
1148                 talloc_free(new_dn);
1149                 return NULL;
1150         }
1151         return new_dn;
1152 }
1153
1154 struct ldb_dn *samdb_infrastructure_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1155 {
1156        struct ldb_dn *new_dn;
1157
1158        new_dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(sam_ctx));
1159        if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Infrastructure")) {
1160                talloc_free(new_dn);
1161                return NULL;
1162        }
1163        return new_dn;
1164 }
1165
1166 struct ldb_dn *samdb_sites_dn(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx)
1167 {
1168         struct ldb_dn *new_dn;
1169
1170         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(sam_ctx));
1171         if ( ! ldb_dn_add_child_fmt(new_dn, "CN=Sites")) {
1172                 talloc_free(new_dn);
1173                 return NULL;
1174         }
1175         return new_dn;
1176 }
1177
1178 /*
1179   work out the domain sid for the current open ldb
1180 */
1181 const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
1182 {
1183         TALLOC_CTX *tmp_ctx;
1184         const struct dom_sid *domain_sid;
1185         const char *attrs[] = {
1186                 "objectSid",
1187                 NULL
1188         };
1189         struct ldb_result *res;
1190         int ret;
1191
1192         /* see if we have a cached copy */
1193         domain_sid = (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1194         if (domain_sid) {
1195                 return domain_sid;
1196         }
1197
1198         tmp_ctx = talloc_new(ldb);
1199         if (tmp_ctx == NULL) {
1200                 goto failed;
1201         }
1202
1203         ret = ldb_search(ldb, tmp_ctx, &res, ldb_get_default_basedn(ldb), LDB_SCOPE_BASE, attrs, "objectSid=*");
1204
1205         if (ret != LDB_SUCCESS) {
1206                 goto failed;
1207         }
1208
1209         if (res->count != 1) {
1210                 goto failed;
1211         }
1212
1213         domain_sid = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
1214         if (domain_sid == NULL) {
1215                 goto failed;
1216         }
1217
1218         /* cache the domain_sid in the ldb */
1219         if (ldb_set_opaque(ldb, "cache.domain_sid", discard_const_p(struct dom_sid, domain_sid)) != LDB_SUCCESS) {
1220                 goto failed;
1221         }
1222
1223         talloc_steal(ldb, domain_sid);
1224         talloc_free(tmp_ctx);
1225
1226         return domain_sid;
1227
1228 failed:
1229         talloc_free(tmp_ctx);
1230         return NULL;
1231 }
1232
1233 /*
1234   get domain sid from cache
1235 */
1236 const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
1237 {
1238         return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
1239 }
1240
1241 bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
1242 {
1243         TALLOC_CTX *tmp_ctx;
1244         struct dom_sid *dom_sid_new;
1245         struct dom_sid *dom_sid_old;
1246
1247         /* see if we have a cached copy */
1248         dom_sid_old = talloc_get_type(ldb_get_opaque(ldb, 
1249                                                      "cache.domain_sid"), struct dom_sid);
1250
1251         tmp_ctx = talloc_new(ldb);
1252         if (tmp_ctx == NULL) {
1253                 goto failed;
1254         }
1255
1256         dom_sid_new = dom_sid_dup(tmp_ctx, dom_sid_in);
1257         if (!dom_sid_new) {
1258                 goto failed;
1259         }
1260
1261         /* cache the domain_sid in the ldb */
1262         if (ldb_set_opaque(ldb, "cache.domain_sid", dom_sid_new) != LDB_SUCCESS) {
1263                 goto failed;
1264         }
1265
1266         talloc_steal(ldb, dom_sid_new);
1267         talloc_free(tmp_ctx);
1268         talloc_free(dom_sid_old);
1269
1270         return true;
1271
1272 failed:
1273         DEBUG(1,("Failed to set our own cached domain SID in the ldb!\n"));
1274         talloc_free(tmp_ctx);
1275         return false;
1276 }
1277
1278 bool samdb_set_ntds_settings_dn(struct ldb_context *ldb, struct ldb_dn *ntds_settings_dn_in)
1279 {
1280         TALLOC_CTX *tmp_ctx;
1281         struct ldb_dn *ntds_settings_dn_new;
1282         struct ldb_dn *ntds_settings_dn_old;
1283
1284         /* see if we have a forced copy from provision */
1285         ntds_settings_dn_old = talloc_get_type(ldb_get_opaque(ldb, 
1286                                                               "forced.ntds_settings_dn"), struct ldb_dn);
1287
1288         tmp_ctx = talloc_new(ldb);
1289         if (tmp_ctx == NULL) {
1290                 goto failed;
1291         }
1292
1293         ntds_settings_dn_new = ldb_dn_copy(tmp_ctx, ntds_settings_dn_in);
1294         if (!ntds_settings_dn_new) {
1295                 goto failed;
1296         }
1297
1298         /* set the DN in the ldb to avoid lookups during provision */
1299         if (ldb_set_opaque(ldb, "forced.ntds_settings_dn", ntds_settings_dn_new) != LDB_SUCCESS) {
1300                 goto failed;
1301         }
1302
1303         talloc_steal(ldb, ntds_settings_dn_new);
1304         talloc_free(tmp_ctx);
1305         talloc_free(ntds_settings_dn_old);
1306
1307         return true;
1308
1309 failed:
1310         DEBUG(1,("Failed to set our NTDS Settings DN in the ldb!\n"));
1311         talloc_free(tmp_ctx);
1312         return false;
1313 }
1314
1315 /*
1316   work out the ntds settings dn for the current open ldb
1317 */
1318 struct ldb_dn *samdb_ntds_settings_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1319 {
1320         TALLOC_CTX *tmp_ctx;
1321         const char *root_attrs[] = { "dsServiceName", NULL };
1322         int ret;
1323         struct ldb_result *root_res;
1324         struct ldb_dn *settings_dn;
1325
1326         /* see if we have a cached copy */
1327         settings_dn = (struct ldb_dn *)ldb_get_opaque(ldb, "forced.ntds_settings_dn");
1328         if (settings_dn) {
1329                 return ldb_dn_copy(mem_ctx, settings_dn);
1330         }
1331
1332         tmp_ctx = talloc_new(mem_ctx);
1333         if (tmp_ctx == NULL) {
1334                 goto failed;
1335         }
1336
1337         ret = ldb_search(ldb, tmp_ctx, &root_res, ldb_dn_new(tmp_ctx, ldb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
1338         if (ret != LDB_SUCCESS) {
1339                 DEBUG(1,("Searching for dsServiceName in rootDSE failed: %s\n", 
1340                          ldb_errstring(ldb)));
1341                 goto failed;
1342         }
1343
1344         if (root_res->count != 1) {
1345                 goto failed;
1346         }
1347
1348         settings_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, root_res->msgs[0], "dsServiceName");
1349
1350         /* note that we do not cache the DN here, as that would mean
1351          * we could not handle server renames at runtime. Only
1352          * provision sets up forced.ntds_settings_dn */
1353
1354         talloc_steal(mem_ctx, settings_dn);
1355         talloc_free(tmp_ctx);
1356
1357         return settings_dn;
1358
1359 failed:
1360         DEBUG(1,("Failed to find our own NTDS Settings DN in the ldb!\n"));
1361         talloc_free(tmp_ctx);
1362         return NULL;
1363 }
1364
1365 /*
1366   work out the ntds settings invocationId for the current open ldb
1367 */
1368 const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
1369 {
1370         TALLOC_CTX *tmp_ctx;
1371         const char *attrs[] = { "invocationId", NULL };
1372         int ret;
1373         struct ldb_result *res;
1374         struct GUID *invocation_id;
1375
1376         /* see if we have a cached copy */
1377         invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
1378         if (invocation_id) {
1379                 SMB_ASSERT(!GUID_all_zero(invocation_id));
1380                 return invocation_id;
1381         }
1382
1383         tmp_ctx = talloc_new(ldb);
1384         if (tmp_ctx == NULL) {
1385                 goto failed;
1386         }
1387
1388         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
1389         if (ret) {
1390                 goto failed;
1391         }
1392
1393         if (res->count != 1) {
1394                 goto failed;
1395         }
1396
1397         invocation_id = talloc(tmp_ctx, struct GUID);
1398         if (!invocation_id) {
1399                 goto failed;
1400         }
1401
1402         *invocation_id = samdb_result_guid(res->msgs[0], "invocationId");
1403         if (GUID_all_zero(invocation_id)) {
1404                 if (ldb_msg_find_ldb_val(res->msgs[0], "invocationId")) {
1405                         DEBUG(0, ("Failed to find our own NTDS Settings invocationId in the ldb!\n"));  
1406                 } else {
1407                         DEBUG(0, ("Failed to find parse own NTDS Settings invocationId from the ldb!\n"));
1408                 }
1409                 goto failed;
1410         }
1411
1412         /* cache the domain_sid in the ldb */
1413         if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id) != LDB_SUCCESS) {
1414                 goto failed;
1415         }
1416
1417         talloc_steal(ldb, invocation_id);
1418         talloc_free(tmp_ctx);
1419
1420         return invocation_id;
1421
1422 failed:
1423         DEBUG(1,("Failed to find our own NTDS Settings invocationId in the ldb!\n"));
1424         talloc_free(tmp_ctx);
1425         return NULL;
1426 }
1427
1428 bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *invocation_id_in)
1429 {
1430         TALLOC_CTX *tmp_ctx;
1431         struct GUID *invocation_id_new;
1432         struct GUID *invocation_id_old;
1433
1434         /* see if we have a cached copy */
1435         invocation_id_old = (struct GUID *)ldb_get_opaque(ldb, 
1436                                                          "cache.invocation_id");
1437
1438         tmp_ctx = talloc_new(ldb);
1439         if (tmp_ctx == NULL) {
1440                 goto failed;
1441         }
1442
1443         invocation_id_new = talloc(tmp_ctx, struct GUID);
1444         if (!invocation_id_new) {
1445                 goto failed;
1446         }
1447
1448         SMB_ASSERT(!GUID_all_zero(invocation_id_in));
1449         *invocation_id_new = *invocation_id_in;
1450
1451         /* cache the domain_sid in the ldb */
1452         if (ldb_set_opaque(ldb, "cache.invocation_id", invocation_id_new) != LDB_SUCCESS) {
1453                 goto failed;
1454         }
1455
1456         talloc_steal(ldb, invocation_id_new);
1457         talloc_free(tmp_ctx);
1458         talloc_free(invocation_id_old);
1459
1460         return true;
1461
1462 failed:
1463         DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
1464         talloc_free(tmp_ctx);
1465         return false;
1466 }
1467
1468 /*
1469   work out the ntds settings objectGUID for the current open ldb
1470 */
1471 const struct GUID *samdb_ntds_objectGUID(struct ldb_context *ldb)
1472 {
1473         TALLOC_CTX *tmp_ctx;
1474         const char *attrs[] = { "objectGUID", NULL };
1475         int ret;
1476         struct ldb_result *res;
1477         struct GUID *ntds_guid;
1478
1479         /* see if we have a cached copy */
1480         ntds_guid = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
1481         if (ntds_guid) {
1482                 return ntds_guid;
1483         }
1484
1485         tmp_ctx = talloc_new(ldb);
1486         if (tmp_ctx == NULL) {
1487                 goto failed;
1488         }
1489
1490         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
1491         if (ret) {
1492                 goto failed;
1493         }
1494
1495         if (res->count != 1) {
1496                 goto failed;
1497         }
1498
1499         ntds_guid = talloc(tmp_ctx, struct GUID);
1500         if (!ntds_guid) {
1501                 goto failed;
1502         }
1503
1504         *ntds_guid = samdb_result_guid(res->msgs[0], "objectGUID");
1505
1506         /* cache the domain_sid in the ldb */
1507         if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid) != LDB_SUCCESS) {
1508                 goto failed;
1509         }
1510
1511         talloc_steal(ldb, ntds_guid);
1512         talloc_free(tmp_ctx);
1513
1514         return ntds_guid;
1515
1516 failed:
1517         DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
1518         talloc_free(tmp_ctx);
1519         return NULL;
1520 }
1521
1522 bool samdb_set_ntds_objectGUID(struct ldb_context *ldb, const struct GUID *ntds_guid_in)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         struct GUID *ntds_guid_new;
1526         struct GUID *ntds_guid_old;
1527
1528         /* see if we have a cached copy */
1529         ntds_guid_old = (struct GUID *)ldb_get_opaque(ldb, "cache.ntds_guid");
1530
1531         tmp_ctx = talloc_new(ldb);
1532         if (tmp_ctx == NULL) {
1533                 goto failed;
1534         }
1535
1536         ntds_guid_new = talloc(tmp_ctx, struct GUID);
1537         if (!ntds_guid_new) {
1538                 goto failed;
1539         }
1540
1541         *ntds_guid_new = *ntds_guid_in;
1542
1543         /* cache the domain_sid in the ldb */
1544         if (ldb_set_opaque(ldb, "cache.ntds_guid", ntds_guid_new) != LDB_SUCCESS) {
1545                 goto failed;
1546         }
1547
1548         talloc_steal(ldb, ntds_guid_new);
1549         talloc_free(tmp_ctx);
1550         talloc_free(ntds_guid_old);
1551
1552         return true;
1553
1554 failed:
1555         DEBUG(1,("Failed to set our own cached invocationId in the ldb!\n"));
1556         talloc_free(tmp_ctx);
1557         return false;
1558 }
1559
1560 /*
1561   work out the server dn for the current open ldb
1562 */
1563 struct ldb_dn *samdb_server_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1564 {
1565         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1566         struct ldb_dn *dn;
1567         if (!tmp_ctx) {
1568                 return NULL;
1569         }
1570         dn = ldb_dn_get_parent(mem_ctx, samdb_ntds_settings_dn(ldb, tmp_ctx));
1571         talloc_free(tmp_ctx);
1572         return dn;
1573         
1574 }
1575
1576 /*
1577   work out the server dn for the current open ldb
1578 */
1579 struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1580 {
1581         struct ldb_dn *server_dn;
1582         struct ldb_dn *servers_dn;
1583         struct ldb_dn *server_site_dn;
1584
1585         /* TODO: there must be a saner way to do this!! */
1586         server_dn = samdb_server_dn(ldb, mem_ctx);
1587         if (!server_dn) return NULL;
1588
1589         servers_dn = ldb_dn_get_parent(mem_ctx, server_dn);
1590         talloc_free(server_dn);
1591         if (!servers_dn) return NULL;
1592
1593         server_site_dn = ldb_dn_get_parent(mem_ctx, servers_dn);
1594         talloc_free(servers_dn);
1595
1596         return server_site_dn;
1597 }
1598
1599 /*
1600   find the site name from a computers DN record
1601  */
1602 int samdb_find_site_for_computer(struct ldb_context *ldb,
1603                                  TALLOC_CTX *mem_ctx, struct ldb_dn *computer_dn,
1604                                  const char **site_name)
1605 {
1606         int ret;
1607         struct ldb_dn *dn;
1608         const struct ldb_val *rdn_val;
1609
1610         *site_name = NULL;
1611
1612         ret = samdb_reference_dn(ldb, mem_ctx, computer_dn, "serverReferenceBL", &dn);
1613         if (ret != LDB_SUCCESS) {
1614                 return ret;
1615         }
1616
1617         if (!ldb_dn_remove_child_components(dn, 2)) {
1618                 talloc_free(dn);
1619                 return LDB_ERR_INVALID_DN_SYNTAX;
1620         }
1621
1622         rdn_val = ldb_dn_get_rdn_val(dn);
1623         if (rdn_val == NULL) {
1624                 return LDB_ERR_OPERATIONS_ERROR;
1625         }
1626
1627         (*site_name) = talloc_strndup(mem_ctx, (const char *)rdn_val->data, rdn_val->length);
1628         talloc_free(dn);
1629         if (!*site_name) {
1630                 return LDB_ERR_OPERATIONS_ERROR;
1631         }
1632         return LDB_SUCCESS;
1633 }
1634
1635 /*
1636   find the NTDS GUID from a computers DN record
1637  */
1638 int samdb_find_ntdsguid_for_computer(struct ldb_context *ldb, struct ldb_dn *computer_dn,
1639                                      struct GUID *ntds_guid)
1640 {
1641         int ret;
1642         struct ldb_dn *dn;
1643
1644         *ntds_guid = GUID_zero();
1645
1646         ret = samdb_reference_dn(ldb, ldb, computer_dn, "serverReferenceBL", &dn);
1647         if (ret != LDB_SUCCESS) {
1648                 return ret;
1649         }
1650
1651         if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
1652                 talloc_free(dn);
1653                 return LDB_ERR_OPERATIONS_ERROR;
1654         }
1655
1656         ret = dsdb_find_guid_by_dn(ldb, dn, ntds_guid);
1657         talloc_free(dn);
1658         return ret;
1659 }
1660
1661 /*
1662   find a 'reference' DN that points at another object
1663   (eg. serverReference, rIDManagerReference etc)
1664  */
1665 int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
1666                        const char *attribute, struct ldb_dn **dn)
1667 {
1668         const char *attrs[2];
1669         struct ldb_result *res;
1670         int ret;
1671
1672         attrs[0] = attribute;
1673         attrs[1] = NULL;
1674
1675         ret = dsdb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, DSDB_SEARCH_ONE_ONLY|DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
1676         if (ret != LDB_SUCCESS) {
1677                 ldb_asprintf_errstring(ldb, "Cannot find DN %s to get attribute %s for reference dn: %s",
1678                                        ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb));
1679                 return ret;
1680         }
1681
1682         *dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
1683         if (!*dn) {
1684                 if (!ldb_msg_find_element(res->msgs[0], attribute)) {
1685                         ldb_asprintf_errstring(ldb, "Cannot find attribute %s of %s to calculate reference dn", attribute,
1686                                                ldb_dn_get_linearized(base));
1687                 } else {
1688                         ldb_asprintf_errstring(ldb, "Cannot interpret attribute %s of %s as a dn", attribute,
1689                                                ldb_dn_get_linearized(base));
1690                 }
1691                 talloc_free(res);
1692                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
1693         }
1694
1695         talloc_free(res);
1696         return LDB_SUCCESS;
1697 }
1698
1699 /*
1700   find if a DN (must have GUID component!) is our ntdsDsa
1701  */
1702 int samdb_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *dn, bool *is_ntdsa)
1703 {
1704         NTSTATUS status;
1705         struct GUID dn_guid;
1706         const struct GUID *our_ntds_guid;
1707         status = dsdb_get_extended_dn_guid(dn, &dn_guid, "GUID");
1708         if (!NT_STATUS_IS_OK(status)) {
1709                 return LDB_ERR_OPERATIONS_ERROR;
1710         }
1711
1712         our_ntds_guid = samdb_ntds_objectGUID(ldb);
1713         if (!our_ntds_guid) {
1714                 DEBUG(0, ("Failed to find our NTDS Settings GUID for comparison with %s - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
1715                 return LDB_ERR_OPERATIONS_ERROR;
1716         }
1717
1718         *is_ntdsa = GUID_equal(&dn_guid, our_ntds_guid);
1719         return LDB_SUCCESS;
1720 }
1721
1722 /*
1723   find a 'reference' DN that points at another object and indicate if it is our ntdsDsa
1724  */
1725 int samdb_reference_dn_is_our_ntdsa(struct ldb_context *ldb, struct ldb_dn *base,
1726                                     const char *attribute, bool *is_ntdsa)
1727 {
1728         int ret;
1729         struct ldb_dn *referenced_dn;
1730         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1731         if (tmp_ctx == NULL) {
1732                 return LDB_ERR_OPERATIONS_ERROR;
1733         }
1734         ret = samdb_reference_dn(ldb, tmp_ctx, base, attribute, &referenced_dn);
1735         if (ret != LDB_SUCCESS) {
1736                 DEBUG(0, ("Failed to find object %s for attribute %s - %s\n", ldb_dn_get_linearized(base), attribute, ldb_errstring(ldb)));
1737                 return ret;
1738         }
1739
1740         ret = samdb_dn_is_our_ntdsa(ldb, referenced_dn, is_ntdsa);
1741         
1742         talloc_free(tmp_ctx);
1743         return ret;
1744 }
1745
1746 /*
1747   find our machine account via the serverReference attribute in the
1748   server DN
1749  */
1750 int samdb_server_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1751 {
1752         struct ldb_dn *server_dn;
1753         int ret;
1754
1755         server_dn = samdb_server_dn(ldb, mem_ctx);
1756         if (server_dn == NULL) {
1757                 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
1758         }
1759
1760         ret = samdb_reference_dn(ldb, mem_ctx, server_dn, "serverReference", dn);
1761         talloc_free(server_dn);
1762
1763         return ret;
1764 }
1765
1766 /*
1767   find the RID Manager$ DN via the rIDManagerReference attribute in the
1768   base DN
1769  */
1770 int samdb_rid_manager_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1771 {
1772         return samdb_reference_dn(ldb, mem_ctx, ldb_get_default_basedn(ldb),
1773                                   "rIDManagerReference", dn);
1774 }
1775
1776 /*
1777   find the RID Set DN via the rIDSetReferences attribute in our
1778   machine account DN
1779  */
1780 int samdb_rid_set_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
1781 {
1782         struct ldb_dn *server_ref_dn;
1783         int ret;
1784
1785         ret = samdb_server_reference_dn(ldb, mem_ctx, &server_ref_dn);
1786         if (ret != LDB_SUCCESS) {
1787                 return ret;
1788         }
1789         ret = samdb_reference_dn(ldb, mem_ctx, server_ref_dn, "rIDSetReferences", dn);
1790         talloc_free(server_ref_dn);
1791         return ret;
1792 }
1793
1794 const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
1795 {
1796         const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb,
1797                                                                             mem_ctx));
1798
1799         if (val == NULL) {
1800                 return NULL;
1801         }
1802
1803         return (const char *) val->data;
1804 }
1805
1806 /*
1807  * Finds the client site by using the client's IP address.
1808  * The "subnet_name" returns the name of the subnet if parameter != NULL
1809  */
1810 const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1811                                    const char *ip_address, char **subnet_name)
1812 {
1813         const char *attrs[] = { "cn", "siteObject", NULL };
1814         struct ldb_dn *sites_container_dn, *subnets_dn, *sites_dn;
1815         struct ldb_result *res;
1816         const struct ldb_val *val;
1817         const char *site_name = NULL, *l_subnet_name = NULL;
1818         const char *allow_list[2] = { NULL, NULL };
1819         unsigned int i, count;
1820         int cnt, ret;
1821
1822         /*
1823          * if we don't have a client ip e.g. ncalrpc
1824          * the server site is the client site
1825          */
1826         if (ip_address == NULL) {
1827                 return samdb_server_site_name(ldb, mem_ctx);
1828         }
1829
1830         sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
1831         if (sites_container_dn == NULL) {
1832                 return NULL;
1833         }
1834
1835         subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
1836         if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
1837                 talloc_free(sites_container_dn);
1838                 talloc_free(subnets_dn);
1839                 return NULL;
1840         }
1841
1842         ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
1843                          attrs, NULL);
1844         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1845                 count = 0;
1846         } else if (ret != LDB_SUCCESS) {
1847                 talloc_free(sites_container_dn);
1848                 talloc_free(subnets_dn);
1849                 return NULL;
1850         } else {
1851                 count = res->count;
1852         }
1853
1854         for (i = 0; i < count; i++) {
1855                 l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
1856                                                             NULL);
1857
1858                 allow_list[0] = l_subnet_name;
1859
1860                 if (socket_allow_access(mem_ctx, NULL, allow_list, "", ip_address)) {
1861                         sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
1862                                                            res->msgs[i],
1863                                                            "siteObject");
1864                         if (sites_dn == NULL) {
1865                                 /* No reference, maybe another subnet matches */
1866                                 continue;
1867                         }
1868
1869                         /* "val" cannot be NULL here since "sites_dn" != NULL */
1870                         val = ldb_dn_get_rdn_val(sites_dn);
1871                         site_name = talloc_strdup(mem_ctx,
1872                                                   (const char *) val->data);
1873
1874                         talloc_free(sites_dn);
1875
1876                         break;
1877                 }
1878         }
1879
1880         if (site_name == NULL) {
1881                 /* This is the Windows Server fallback rule: when no subnet
1882                  * exists and we have only one site available then use it (it
1883                  * is for sure the same as our server site). If more sites do
1884                  * exist then we don't know which one to use and set the site
1885                  * name to "". */
1886                 cnt = samdb_search_count(ldb, mem_ctx, sites_container_dn,
1887                                          "(objectClass=site)");
1888                 if (cnt == 1) {
1889                         site_name = samdb_server_site_name(ldb, mem_ctx);
1890                 } else {
1891                         site_name = talloc_strdup(mem_ctx, "");
1892                 }
1893                 l_subnet_name = NULL;
1894         }
1895
1896         if (subnet_name != NULL) {
1897                 *subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
1898         }
1899
1900         talloc_free(sites_container_dn);
1901         talloc_free(subnets_dn);
1902         talloc_free(res);
1903
1904         return site_name;
1905 }
1906
1907 /*
1908   work out if we are the PDC for the domain of the current open ldb
1909 */
1910 bool samdb_is_pdc(struct ldb_context *ldb)
1911 {
1912         int ret;
1913         bool is_pdc;
1914
1915         ret = samdb_reference_dn_is_our_ntdsa(ldb, ldb_get_default_basedn(ldb), "fsmoRoleOwner", 
1916                                               &is_pdc);
1917         if (ret != LDB_SUCCESS) {
1918                 DEBUG(1,("Failed to find if we are the PDC for this ldb: Searching for fSMORoleOwner in %s failed: %s\n", 
1919                          ldb_dn_get_linearized(ldb_get_default_basedn(ldb)), 
1920                          ldb_errstring(ldb)));
1921                 return false;
1922         }
1923
1924         return is_pdc;
1925 }
1926
1927 /*
1928   work out if we are a Global Catalog server for the domain of the current open ldb
1929 */
1930 bool samdb_is_gc(struct ldb_context *ldb)
1931 {
1932         uint32_t options;
1933         if (samdb_ntds_options(ldb, &options) != LDB_SUCCESS) {
1934                 return false;
1935         }
1936         return (options & DS_NTDSDSA_OPT_IS_GC) != 0;
1937 }
1938
1939 /* Find a domain object in the parents of a particular DN.  */
1940 int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
1941                                    struct ldb_dn **parent_dn, const char **errstring)
1942 {
1943         TALLOC_CTX *local_ctx;
1944         struct ldb_dn *sdn = dn;
1945         struct ldb_result *res = NULL;
1946         int ret = LDB_SUCCESS;
1947         const char *attrs[] = { NULL };
1948
1949         local_ctx = talloc_new(mem_ctx);
1950         if (local_ctx == NULL) return ldb_oom(ldb);
1951
1952         while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
1953                 ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
1954                                  "(|(objectClass=domain)(objectClass=builtinDomain))");
1955                 if (ret == LDB_SUCCESS) {
1956                         if (res->count == 1) {
1957                                 break;
1958                         }
1959                 } else {
1960                         break;
1961                 }
1962         }
1963
1964         if (ret != LDB_SUCCESS) {
1965                 *errstring = talloc_asprintf(mem_ctx, "Error searching for parent domain of %s, failed searching for %s: %s",
1966                                              ldb_dn_get_linearized(dn),
1967                                              ldb_dn_get_linearized(sdn),
1968                                              ldb_errstring(ldb));
1969                 talloc_free(local_ctx);
1970                 return ret;
1971         }
1972         if (res->count != 1) {
1973                 *errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
1974                                              ldb_dn_get_linearized(dn));
1975                 DEBUG(0,(__location__ ": %s\n", *errstring));
1976                 talloc_free(local_ctx);
1977                 return LDB_ERR_CONSTRAINT_VIOLATION;
1978         }
1979
1980         *parent_dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
1981         talloc_free(local_ctx);
1982         return ret;
1983 }
1984
1985 static void pwd_timeout_debug(struct tevent_context *unused1,
1986                               struct tevent_timer *unused2,
1987                               struct timeval unused3,
1988                               void *unused4)
1989 {
1990         DEBUG(0, ("WARNING: check_password_complexity: password script "
1991                   "took more than 1 second to run\n"));
1992 }
1993
1994
1995 /*
1996  * Performs checks on a user password (plaintext UNIX format - attribute
1997  * "password"). The remaining parameters have to be extracted from the domain
1998  * object in the AD.
1999  *
2000  * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
2001  */
2002 enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
2003                                                 struct loadparm_context *lp_ctx,
2004                                                 const DATA_BLOB *utf8_blob,
2005                                                 const uint32_t pwdProperties,
2006                                                 const uint32_t minPwdLength)
2007 {
2008         const char *utf8_pw = (const char *)utf8_blob->data;
2009         size_t utf8_len = strlen_m(utf8_pw);
2010         char *password_script = NULL;
2011
2012         /* checks if the "minPwdLength" property is satisfied */
2013         if (minPwdLength > utf8_len) {
2014                 return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
2015         }
2016
2017         /* checks the password complexity */
2018         if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) {
2019                 return SAMR_VALIDATION_STATUS_SUCCESS;
2020         }
2021
2022         if (utf8_len == 0) {
2023                 return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2024         }
2025
2026         password_script = lpcfg_check_password_script(lp_ctx, mem_ctx);
2027         if (password_script != NULL && *password_script != '\0') {
2028                 int check_ret = 0;
2029                 int error = 0;
2030                 struct tevent_context *event_ctx = NULL;
2031                 struct tevent_req *req = NULL;
2032                 struct samba_runcmd_state *run_cmd = NULL;
2033                 const char * const cmd[4] = {
2034                         "/bin/sh", "-c",
2035                         password_script,
2036                         NULL
2037                 };
2038
2039                 event_ctx = tevent_context_init(mem_ctx);
2040                 if (event_ctx == NULL) {
2041                         TALLOC_FREE(password_script);
2042                         return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2043                 }
2044
2045                 /* Gives a warning after 1 second, terminates after 10 */
2046                 tevent_add_timer(event_ctx, event_ctx,
2047                                  tevent_timeval_current_ofs(1, 0),
2048                                  pwd_timeout_debug, NULL);
2049
2050                 req = samba_runcmd_send(event_ctx, event_ctx,
2051                                         tevent_timeval_current_ofs(10, 0),
2052                                         100, 100, cmd, NULL);
2053                 run_cmd = tevent_req_data(req, struct samba_runcmd_state);
2054                 if (write(run_cmd->fd_stdin, utf8_pw, utf8_len) != utf8_len) {
2055                         TALLOC_FREE(password_script);
2056                         TALLOC_FREE(event_ctx);
2057                         return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2058                 }
2059
2060                 close(run_cmd->fd_stdin);
2061                 run_cmd->fd_stdin = -1;
2062
2063                 if (!tevent_req_poll(req, event_ctx)) {
2064                         TALLOC_FREE(password_script);
2065                         TALLOC_FREE(event_ctx);
2066                         return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2067                 }
2068
2069                 check_ret = samba_runcmd_recv(req, &error);
2070                 TALLOC_FREE(event_ctx);
2071
2072                 if (error == ETIMEDOUT) {
2073                         DEBUG(0, ("check_password_complexity: check password script took too long!\n"));
2074                         TALLOC_FREE(password_script);
2075                         return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
2076                 } else {
2077                         DEBUG(5,("check_password_complexity: check password script (%s) "
2078                                  "returned [%d]\n", password_script, check_ret));
2079
2080                         if (check_ret != 0) {
2081                                 DEBUG(1,("check_password_complexity: "
2082                                          "check password script said new password is not good "
2083                                          "enough!\n"));
2084                                 TALLOC_FREE(password_script);
2085                                 return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2086                         }
2087                 }
2088
2089                 TALLOC_FREE(password_script);
2090                 return SAMR_VALIDATION_STATUS_SUCCESS;
2091         }
2092
2093         TALLOC_FREE(password_script);
2094
2095         if (!check_password_quality(utf8_pw)) {
2096                 return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
2097         }
2098
2099         return SAMR_VALIDATION_STATUS_SUCCESS;
2100 }
2101
2102 /*
2103  * Callback for "samdb_set_password" password change
2104  */
2105 int samdb_set_password_callback(struct ldb_request *req, struct ldb_reply *ares)
2106 {
2107         int ret;
2108
2109         if (!ares) {
2110                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2111         }
2112
2113         if (ares->error != LDB_SUCCESS) {
2114                 ret = ares->error;
2115                 req->context = talloc_steal(req,
2116                                             ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2117                 talloc_free(ares);
2118                 return ldb_request_done(req, ret);
2119         }
2120
2121         if (ares->type != LDB_REPLY_DONE) {
2122                 talloc_free(ares);
2123                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2124         }
2125
2126         req->context = talloc_steal(req,
2127                                     ldb_reply_get_control(ares, DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID));
2128         talloc_free(ares);
2129         return ldb_request_done(req, LDB_SUCCESS);
2130 }
2131
2132 /*
2133  * Sets the user password using plaintext UTF16 (attribute "new_password") or
2134  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
2135  * the old LM and/or NT hash (attributes "lmOldHash"/"ntOldHash") if it is a
2136  * user change or not. The "rejectReason" gives some more information if the
2137  * change failed.
2138  *
2139  * Results: NT_STATUS_OK, NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2140  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION
2141  */
2142 static NTSTATUS samdb_set_password_internal(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2143                             struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
2144                             const DATA_BLOB *new_password,
2145                             const struct samr_Password *lmNewHash,
2146                             const struct samr_Password *ntNewHash,
2147                             const struct samr_Password *lmOldHash,
2148                             const struct samr_Password *ntOldHash,
2149                             enum samPwdChangeReason *reject_reason,
2150                             struct samr_DomInfo1 **_dominfo,
2151                             bool permit_interdomain_trust)
2152 {
2153         struct ldb_message *msg;
2154         struct ldb_message_element *el;
2155         struct ldb_request *req;
2156         struct dsdb_control_password_change_status *pwd_stat = NULL;
2157         int ret;
2158         bool hash_values = false;
2159         NTSTATUS status = NT_STATUS_OK;
2160
2161 #define CHECK_RET(x) \
2162         if (x != LDB_SUCCESS) { \
2163                 talloc_free(msg); \
2164                 return NT_STATUS_NO_MEMORY; \
2165         }
2166
2167         msg = ldb_msg_new(mem_ctx);
2168         if (msg == NULL) {
2169                 return NT_STATUS_NO_MEMORY;
2170         }
2171         msg->dn = user_dn;
2172         if ((new_password != NULL)
2173                         && ((lmNewHash == NULL) && (ntNewHash == NULL))) {
2174                 /* we have the password as plaintext UTF16 */
2175                 CHECK_RET(ldb_msg_add_value(msg, "clearTextPassword",
2176                                             new_password, NULL));
2177                 el = ldb_msg_find_element(msg, "clearTextPassword");
2178                 el->flags = LDB_FLAG_MOD_REPLACE;
2179         } else if ((new_password == NULL)
2180                         && ((lmNewHash != NULL) || (ntNewHash != NULL))) {
2181                 /* we have a password as LM and/or NT hash */
2182                 if (lmNewHash != NULL) {
2183                         CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
2184                                 "dBCSPwd", lmNewHash));
2185                         el = ldb_msg_find_element(msg, "dBCSPwd");
2186                         el->flags = LDB_FLAG_MOD_REPLACE;
2187                 }
2188                 if (ntNewHash != NULL) {
2189                         CHECK_RET(samdb_msg_add_hash(ldb, mem_ctx, msg,
2190                                 "unicodePwd", ntNewHash));
2191                         el = ldb_msg_find_element(msg, "unicodePwd");
2192                         el->flags = LDB_FLAG_MOD_REPLACE;
2193                 }
2194                 hash_values = true;
2195         } else {
2196                 /* the password wasn't specified correctly */
2197                 talloc_free(msg);
2198                 return NT_STATUS_INVALID_PARAMETER;
2199         }
2200
2201         /* build modify request */
2202         ret = ldb_build_mod_req(&req, ldb, mem_ctx, msg, NULL, NULL,
2203                                 samdb_set_password_callback, NULL);
2204         if (ret != LDB_SUCCESS) {
2205                 talloc_free(msg);
2206                 return NT_STATUS_NO_MEMORY;
2207         }
2208
2209         /* A password change operation */
2210         if ((ntOldHash != NULL) || (lmOldHash != NULL)) {
2211                 struct dsdb_control_password_change *change;
2212
2213                 change = talloc(req, struct dsdb_control_password_change);
2214                 if (change == NULL) {
2215                         talloc_free(req);
2216                         talloc_free(msg);
2217                         return NT_STATUS_NO_MEMORY;
2218                 }
2219
2220                 change->old_nt_pwd_hash = ntOldHash;
2221                 change->old_lm_pwd_hash = lmOldHash;
2222
2223                 ret = ldb_request_add_control(req,
2224                                               DSDB_CONTROL_PASSWORD_CHANGE_OID,
2225                                               true, change);
2226                 if (ret != LDB_SUCCESS) {
2227                         talloc_free(req);
2228                         talloc_free(msg);
2229                         return NT_STATUS_NO_MEMORY;
2230                 }
2231         }
2232         if (hash_values) {
2233                 ret = ldb_request_add_control(req,
2234                                               DSDB_CONTROL_PASSWORD_HASH_VALUES_OID,
2235                                               true, NULL);
2236                 if (ret != LDB_SUCCESS) {
2237                         talloc_free(req);
2238                         talloc_free(msg);
2239                         return NT_STATUS_NO_MEMORY;
2240                 }
2241         }
2242         if (permit_interdomain_trust) {
2243                 ret = ldb_request_add_control(req,
2244                                               DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
2245                                               false, NULL);
2246                 if (ret != LDB_SUCCESS) {
2247                         talloc_free(req);
2248                         talloc_free(msg);
2249                         return NT_STATUS_NO_MEMORY;
2250                 }
2251         }
2252         ret = ldb_request_add_control(req,
2253                                       DSDB_CONTROL_PASSWORD_CHANGE_STATUS_OID,
2254                                       true, NULL);
2255         if (ret != LDB_SUCCESS) {
2256                 talloc_free(req);
2257                 talloc_free(msg);
2258                 return NT_STATUS_NO_MEMORY;
2259         }
2260
2261         ret = dsdb_autotransaction_request(ldb, req);
2262
2263         if (req->context != NULL) {
2264                 struct ldb_control *control = talloc_get_type_abort(req->context,
2265                                                                     struct ldb_control);
2266                 pwd_stat = talloc_get_type_abort(control->data,
2267                                                  struct dsdb_control_password_change_status);
2268                 talloc_steal(mem_ctx, pwd_stat);
2269         }
2270
2271         talloc_free(req);
2272         talloc_free(msg);
2273
2274         /* Sets the domain info (if requested) */
2275         if (_dominfo != NULL) {
2276                 struct samr_DomInfo1 *dominfo;
2277
2278                 dominfo = talloc_zero(mem_ctx, struct samr_DomInfo1);
2279                 if (dominfo == NULL) {
2280                         return NT_STATUS_NO_MEMORY;
2281                 }
2282
2283                 if (pwd_stat != NULL) {
2284                         dominfo->min_password_length     = pwd_stat->domain_data.minPwdLength;
2285                         dominfo->password_properties     = pwd_stat->domain_data.pwdProperties;
2286                         dominfo->password_history_length = pwd_stat->domain_data.pwdHistoryLength;
2287                         dominfo->max_password_age        = pwd_stat->domain_data.maxPwdAge;
2288                         dominfo->min_password_age        = pwd_stat->domain_data.minPwdAge;
2289                 }
2290
2291                 *_dominfo = dominfo;
2292         }
2293
2294         if (reject_reason != NULL) {
2295                 if (pwd_stat != NULL) {
2296                         *reject_reason = pwd_stat->reject_reason;
2297                 } else {
2298                         *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
2299                 }
2300         }
2301
2302         if (pwd_stat != NULL) {
2303                 talloc_free(pwd_stat);
2304         }
2305
2306         if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
2307                 const char *errmsg = ldb_errstring(ldb);
2308                 char *endptr = NULL;
2309                 WERROR werr = WERR_GENERAL_FAILURE;
2310                 status = NT_STATUS_UNSUCCESSFUL;
2311                 if (errmsg != NULL) {
2312                         werr = W_ERROR(strtol(errmsg, &endptr, 16));
2313                         DBG_WARNING("%s\n", errmsg);
2314                 }
2315                 if (endptr != errmsg) {
2316                         if (W_ERROR_EQUAL(werr, WERR_INVALID_PASSWORD)) {
2317                                 status = NT_STATUS_WRONG_PASSWORD;
2318                         }
2319                         if (W_ERROR_EQUAL(werr, WERR_PASSWORD_RESTRICTION)) {
2320                                 status = NT_STATUS_PASSWORD_RESTRICTION;
2321                         }
2322                 }
2323         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2324                 /* don't let the caller know if an account doesn't exist */
2325                 status = NT_STATUS_WRONG_PASSWORD;
2326         } else if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
2327                 status = NT_STATUS_ACCESS_DENIED;
2328         } else if (ret != LDB_SUCCESS) {
2329                 DEBUG(1, ("Failed to set password on %s: %s\n",
2330                           ldb_dn_get_linearized(msg->dn),
2331                           ldb_errstring(ldb)));
2332                 status = NT_STATUS_UNSUCCESSFUL;
2333         }
2334
2335         return status;
2336 }
2337
2338 NTSTATUS samdb_set_password(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2339                             struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
2340                             const DATA_BLOB *new_password,
2341                             const struct samr_Password *lmNewHash,
2342                             const struct samr_Password *ntNewHash,
2343                             const struct samr_Password *lmOldHash,
2344                             const struct samr_Password *ntOldHash,
2345                             enum samPwdChangeReason *reject_reason,
2346                             struct samr_DomInfo1 **_dominfo)
2347 {
2348         return samdb_set_password_internal(ldb, mem_ctx,
2349                             user_dn, domain_dn,
2350                             new_password,
2351                             lmNewHash, ntNewHash,
2352                             lmOldHash, ntOldHash,
2353                             reject_reason, _dominfo,
2354                             false); /* reject trusts */
2355 }
2356
2357 /*
2358  * Sets the user password using plaintext UTF16 (attribute "new_password") or
2359  * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
2360  * the old LM and/or NT hash (attributes "lmOldHash"/"ntOldHash") if it is a
2361  * user change or not. The "rejectReason" gives some more information if the
2362  * change failed.
2363  *
2364  * This wrapper function for "samdb_set_password" takes a SID as input rather
2365  * than a user DN.
2366  *
2367  * This call encapsulates a new LDB transaction for changing the password;
2368  * therefore the user hasn't to start a new one.
2369  *
2370  * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
2371  *   NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
2372  *   NT_STATUS_WRONG_PASSWORD, NT_STATUS_PASSWORD_RESTRICTION,
2373  *   NT_STATUS_TRANSACTION_ABORTED, NT_STATUS_NO_SUCH_USER
2374  */
2375 NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
2376                                 const struct dom_sid *user_sid,
2377                                 const uint32_t *new_version, /* optional for trusts */
2378                                 const DATA_BLOB *new_password,
2379                                 const struct samr_Password *lmNewHash,
2380                                 const struct samr_Password *ntNewHash,
2381                                 const struct samr_Password *lmOldHash,
2382                                 const struct samr_Password *ntOldHash,
2383                                 enum samPwdChangeReason *reject_reason,
2384                                 struct samr_DomInfo1 **_dominfo) 
2385 {
2386         TALLOC_CTX *frame = talloc_stackframe();
2387         NTSTATUS nt_status;
2388         const char * const user_attrs[] = {
2389                 "userAccountControl",
2390                 "sAMAccountName",
2391                 NULL
2392         };
2393         struct ldb_message *user_msg = NULL;
2394         int ret;
2395         uint32_t uac = 0;
2396
2397         ret = ldb_transaction_start(ldb);
2398         if (ret != LDB_SUCCESS) {
2399                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
2400                 TALLOC_FREE(frame);
2401                 return NT_STATUS_TRANSACTION_ABORTED;
2402         }
2403
2404         ret = dsdb_search_one(ldb, frame, &user_msg, ldb_get_default_basedn(ldb),
2405                               LDB_SCOPE_SUBTREE, user_attrs, 0,
2406                               "(&(objectSid=%s)(objectClass=user))",
2407                               ldap_encode_ndr_dom_sid(frame, user_sid));
2408         if (ret != LDB_SUCCESS) {
2409                 ldb_transaction_cancel(ldb);
2410                 DEBUG(3, ("samdb_set_password_sid: SID[%s] not found in samdb %s - %s, "
2411                           "returning NO_SUCH_USER\n",
2412                           dom_sid_string(frame, user_sid),
2413                           ldb_strerror(ret), ldb_errstring(ldb)));
2414                 TALLOC_FREE(frame);
2415                 return NT_STATUS_NO_SUCH_USER;
2416         }
2417
2418         uac = ldb_msg_find_attr_as_uint(user_msg, "userAccountControl", 0);
2419         if (!(uac & UF_ACCOUNT_TYPE_MASK)) {
2420                 ldb_transaction_cancel(ldb);
2421                 DEBUG(1, ("samdb_set_password_sid: invalid "
2422                           "userAccountControl[0x%08X] for SID[%s] DN[%s], "
2423                           "returning NO_SUCH_USER\n",
2424                           (unsigned)uac, dom_sid_string(frame, user_sid),
2425                           ldb_dn_get_linearized(user_msg->dn)));
2426                 TALLOC_FREE(frame);
2427                 return NT_STATUS_NO_SUCH_USER;
2428         }
2429
2430         if (uac & UF_INTERDOMAIN_TRUST_ACCOUNT) {
2431                 const char * const tdo_attrs[] = {
2432                         "trustAuthIncoming",
2433                         "trustDirection",
2434                         NULL
2435                 };
2436                 struct ldb_message *tdo_msg = NULL;
2437                 const char *account_name = NULL;
2438                 uint32_t trust_direction;
2439                 uint32_t i;
2440                 const struct ldb_val *old_val = NULL;
2441                 struct trustAuthInOutBlob old_blob = {};
2442                 uint32_t old_version = 0;
2443                 struct AuthenticationInformation *old_version_a = NULL;
2444                 uint32_t _new_version = 0;
2445                 struct trustAuthInOutBlob new_blob = {};
2446                 struct ldb_val new_val = {};
2447                 struct timeval tv = timeval_current();
2448                 NTTIME now = timeval_to_nttime(&tv);
2449                 enum ndr_err_code ndr_err;
2450
2451                 if (new_password == NULL && ntNewHash == NULL) {
2452                         ldb_transaction_cancel(ldb);
2453                         DEBUG(1, ("samdb_set_password_sid: "
2454                                   "no new password provided "
2455                                   "sAMAccountName for SID[%s] DN[%s], "
2456                                   "returning INVALID_PARAMETER\n",
2457                                   dom_sid_string(frame, user_sid),
2458                                   ldb_dn_get_linearized(user_msg->dn)));
2459                         TALLOC_FREE(frame);
2460                         return NT_STATUS_INVALID_PARAMETER;
2461                 }
2462
2463                 if (new_password != NULL && ntNewHash != NULL) {
2464                         ldb_transaction_cancel(ldb);
2465                         DEBUG(1, ("samdb_set_password_sid: "
2466                                   "two new passwords provided "
2467                                   "sAMAccountName for SID[%s] DN[%s], "
2468                                   "returning INVALID_PARAMETER\n",
2469                                   dom_sid_string(frame, user_sid),
2470                                   ldb_dn_get_linearized(user_msg->dn)));
2471                         TALLOC_FREE(frame);
2472                         return NT_STATUS_INVALID_PARAMETER;
2473                 }
2474
2475                 if (new_password != NULL && (new_password->length % 2)) {
2476                         ldb_transaction_cancel(ldb);
2477                         DEBUG(2, ("samdb_set_password_sid: "
2478                                   "invalid utf16 length (%zu) "
2479                                   "sAMAccountName for SID[%s] DN[%s], "
2480                                   "returning WRONG_PASSWORD\n",
2481                                   new_password->length,
2482                                   dom_sid_string(frame, user_sid),
2483                                   ldb_dn_get_linearized(user_msg->dn)));
2484                         TALLOC_FREE(frame);
2485                         return NT_STATUS_WRONG_PASSWORD;
2486                 }
2487
2488                 if (new_password != NULL && new_password->length >= 500) {
2489                         ldb_transaction_cancel(ldb);
2490                         DEBUG(2, ("samdb_set_password_sid: "
2491                                   "utf16 password too long (%zu) "
2492                                   "sAMAccountName for SID[%s] DN[%s], "
2493                                   "returning WRONG_PASSWORD\n",
2494                                   new_password->length,
2495                                   dom_sid_string(frame, user_sid),
2496                                   ldb_dn_get_linearized(user_msg->dn)));
2497                         TALLOC_FREE(frame);
2498                         return NT_STATUS_WRONG_PASSWORD;
2499                 }
2500
2501                 account_name = ldb_msg_find_attr_as_string(user_msg,
2502                                                         "sAMAccountName", NULL);
2503                 if (account_name == NULL) {
2504                         ldb_transaction_cancel(ldb);
2505                         DEBUG(1, ("samdb_set_password_sid: missing "
2506                                   "sAMAccountName for SID[%s] DN[%s], "
2507                                   "returning NO_SUCH_USER\n",
2508                                   dom_sid_string(frame, user_sid),
2509                                   ldb_dn_get_linearized(user_msg->dn)));
2510                         TALLOC_FREE(frame);
2511                         return NT_STATUS_NO_SUCH_USER;
2512                 }
2513
2514                 nt_status = dsdb_trust_search_tdo_by_type(ldb,
2515                                                           SEC_CHAN_DOMAIN,
2516                                                           account_name,
2517                                                           tdo_attrs,
2518                                                           frame, &tdo_msg);
2519                 if (!NT_STATUS_IS_OK(nt_status)) {
2520                         ldb_transaction_cancel(ldb);
2521                         DEBUG(1, ("samdb_set_password_sid: dsdb_trust_search_tdo "
2522                                   "failed(%s) for sAMAccountName[%s] SID[%s] DN[%s], "
2523                                   "returning INTERNAL_DB_CORRUPTION\n",
2524                                   nt_errstr(nt_status), account_name,
2525                                   dom_sid_string(frame, user_sid),
2526                                   ldb_dn_get_linearized(user_msg->dn)));
2527                         TALLOC_FREE(frame);
2528                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2529                 }
2530
2531                 trust_direction = ldb_msg_find_attr_as_int(tdo_msg,
2532                                                            "trustDirection", 0);
2533                 if (!(trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2534                         ldb_transaction_cancel(ldb);
2535                         DEBUG(1, ("samdb_set_password_sid: direction[0x%08X] is "
2536                                   "not inbound for sAMAccountName[%s] "
2537                                   "DN[%s] TDO[%s], "
2538                                   "returning INTERNAL_DB_CORRUPTION\n",
2539                                   (unsigned)trust_direction,
2540                                   account_name,
2541                                   ldb_dn_get_linearized(user_msg->dn),
2542                                   ldb_dn_get_linearized(tdo_msg->dn)));
2543                         TALLOC_FREE(frame);
2544                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2545                 }
2546
2547                 old_val = ldb_msg_find_ldb_val(tdo_msg, "trustAuthIncoming");
2548                 if (old_val != NULL) {
2549                         ndr_err = ndr_pull_struct_blob(old_val, frame, &old_blob,
2550                                         (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2551                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2552                                 ldb_transaction_cancel(ldb);
2553                                 DEBUG(1, ("samdb_set_password_sid: "
2554                                           "failed(%s) to parse "
2555                                           "trustAuthOutgoing sAMAccountName[%s] "
2556                                           "DN[%s] TDO[%s], "
2557                                           "returning INTERNAL_DB_CORRUPTION\n",
2558                                           ndr_map_error2string(ndr_err),
2559                                           account_name,
2560                                           ldb_dn_get_linearized(user_msg->dn),
2561                                           ldb_dn_get_linearized(tdo_msg->dn)));
2562
2563                                 TALLOC_FREE(frame);
2564                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2565                         }
2566                 }
2567
2568                 for (i = old_blob.current.count; i > 0; i--) {
2569                         struct AuthenticationInformation *a =
2570                                 &old_blob.current.array[i - 1];
2571
2572                         switch (a->AuthType) {
2573                         case TRUST_AUTH_TYPE_NONE:
2574                                 if (i == old_blob.current.count) {
2575                                         /*
2576                                          * remove TRUST_AUTH_TYPE_NONE at the
2577                                          * end
2578                                          */
2579                                         old_blob.current.count--;
2580                                 }
2581                                 break;
2582
2583                         case TRUST_AUTH_TYPE_VERSION:
2584                                 old_version_a = a;
2585                                 old_version = a->AuthInfo.version.version;
2586                                 break;
2587
2588                         case TRUST_AUTH_TYPE_CLEAR:
2589                                 break;
2590
2591                         case TRUST_AUTH_TYPE_NT4OWF:
2592                                 break;
2593                         }
2594                 }
2595
2596                 if (new_version == NULL) {
2597                         _new_version = 0;
2598                         new_version = &_new_version;
2599                 }
2600
2601                 if (old_version_a != NULL && *new_version != (old_version + 1)) {
2602                         old_version_a->LastUpdateTime = now;
2603                         old_version_a->AuthType = TRUST_AUTH_TYPE_NONE;
2604                 }
2605
2606                 new_blob.count = MAX(old_blob.current.count, 2);
2607                 new_blob.current.array = talloc_zero_array(frame,
2608                                                 struct AuthenticationInformation,
2609                                                 new_blob.count);
2610                 if (new_blob.current.array == NULL) {
2611                         ldb_transaction_cancel(ldb);
2612                         TALLOC_FREE(frame);
2613                         return NT_STATUS_NO_MEMORY;
2614                 }
2615                 new_blob.previous.array = talloc_zero_array(frame,
2616                                                 struct AuthenticationInformation,
2617                                                 new_blob.count);
2618                 if (new_blob.current.array == NULL) {
2619                         ldb_transaction_cancel(ldb);
2620                         TALLOC_FREE(frame);
2621                         return NT_STATUS_NO_MEMORY;
2622                 }
2623
2624                 for (i = 0; i < old_blob.current.count; i++) {
2625                         struct AuthenticationInformation *o =
2626                                 &old_blob.current.array[i];
2627                         struct AuthenticationInformation *p =
2628                                 &new_blob.previous.array[i];
2629
2630                         *p = *o;
2631                         new_blob.previous.count++;
2632                 }
2633                 for (; i < new_blob.count; i++) {
2634                         struct AuthenticationInformation *pi =
2635                                 &new_blob.previous.array[i];
2636
2637                         if (i == 0) {
2638                                 /*
2639                                  * new_blob.previous is still empty so
2640                                  * we'll do new_blob.previous = new_blob.current
2641                                  * below.
2642                                  */
2643                                 break;
2644                         }
2645
2646                         pi->LastUpdateTime = now;
2647                         pi->AuthType = TRUST_AUTH_TYPE_NONE;
2648                         new_blob.previous.count++;
2649                 }
2650
2651                 for (i = 0; i < new_blob.count; i++) {
2652                         struct AuthenticationInformation *ci =
2653                                 &new_blob.current.array[i];
2654
2655                         ci->LastUpdateTime = now;
2656                         switch (i) {
2657                         case 0:
2658                                 if (ntNewHash != NULL) {
2659                                         ci->AuthType = TRUST_AUTH_TYPE_NT4OWF;
2660                                         ci->AuthInfo.nt4owf.password = *ntNewHash;
2661                                         break;
2662                                 }
2663
2664                                 ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2665                                 ci->AuthInfo.clear.size = new_password->length;
2666                                 ci->AuthInfo.clear.password = new_password->data;
2667                                 break;
2668                         case 1:
2669                                 ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2670                                 ci->AuthInfo.version.version = *new_version;
2671                                 break;
2672                         default:
2673                                 ci->AuthType = TRUST_AUTH_TYPE_NONE;
2674                                 break;
2675                         }
2676
2677                         new_blob.current.count++;
2678                 }
2679
2680                 if (new_blob.previous.count == 0) {
2681                         TALLOC_FREE(new_blob.previous.array);
2682                         new_blob.previous = new_blob.current;
2683                 }
2684
2685                 ndr_err = ndr_push_struct_blob(&new_val, frame, &new_blob,
2686                                 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2687                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2688                         ldb_transaction_cancel(ldb);
2689                         DEBUG(1, ("samdb_set_password_sid: "
2690                                   "failed(%s) to generate "
2691                                   "trustAuthOutgoing sAMAccountName[%s] "
2692                                   "DN[%s] TDO[%s], "
2693                                   "returning UNSUCCESSFUL\n",
2694                                   ndr_map_error2string(ndr_err),
2695                                   account_name,
2696                                   ldb_dn_get_linearized(user_msg->dn),
2697                                   ldb_dn_get_linearized(tdo_msg->dn)));
2698                         TALLOC_FREE(frame);
2699                         return NT_STATUS_UNSUCCESSFUL;
2700                 }
2701
2702                 tdo_msg->num_elements = 0;
2703                 TALLOC_FREE(tdo_msg->elements);
2704
2705                 ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming",
2706                                         LDB_FLAG_MOD_REPLACE, NULL);
2707                 if (ret != LDB_SUCCESS) {
2708                         ldb_transaction_cancel(ldb);
2709                         TALLOC_FREE(frame);
2710                         return NT_STATUS_NO_MEMORY;
2711                 }
2712                 ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming",
2713                                         &new_val, NULL);
2714                 if (ret != LDB_SUCCESS) {
2715                         ldb_transaction_cancel(ldb);
2716                         TALLOC_FREE(frame);
2717                         return NT_STATUS_NO_MEMORY;
2718                 }
2719
2720                 ret = ldb_modify(ldb, tdo_msg);
2721                 if (ret != LDB_SUCCESS) {
2722                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
2723                         ldb_transaction_cancel(ldb);
2724                         DEBUG(1, ("samdb_set_password_sid: "
2725                                   "failed to replace "
2726                                   "trustAuthOutgoing sAMAccountName[%s] "
2727                                   "DN[%s] TDO[%s], "
2728                                   "%s - %s\n",
2729                                   account_name,
2730                                   ldb_dn_get_linearized(user_msg->dn),
2731                                   ldb_dn_get_linearized(tdo_msg->dn),
2732                                   nt_errstr(nt_status), ldb_errstring(ldb)));
2733                         TALLOC_FREE(frame);
2734                         return nt_status;
2735                 }
2736         }
2737
2738         nt_status = samdb_set_password_internal(ldb, mem_ctx,
2739                                                 user_msg->dn, NULL,
2740                                                 new_password,
2741                                                 lmNewHash, ntNewHash,
2742                                                 lmOldHash, ntOldHash,
2743                                                 reject_reason, _dominfo,
2744                                                 true); /* permit trusts */
2745         if (!NT_STATUS_IS_OK(nt_status)) {
2746                 ldb_transaction_cancel(ldb);
2747                 TALLOC_FREE(frame);
2748                 return nt_status;
2749         }
2750
2751         ret = ldb_transaction_commit(ldb);
2752         if (ret != LDB_SUCCESS) {
2753                 DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
2754                          ldb_dn_get_linearized(user_msg->dn),
2755                          ldb_errstring(ldb)));
2756                 TALLOC_FREE(frame);
2757                 return NT_STATUS_TRANSACTION_ABORTED;
2758         }
2759
2760         TALLOC_FREE(frame);
2761         return NT_STATUS_OK;
2762 }
2763
2764
2765 NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, 
2766                                                  struct dom_sid *sid, struct ldb_dn **ret_dn) 
2767 {
2768         struct ldb_message *msg;
2769         struct ldb_dn *basedn;
2770         char *sidstr;
2771         int ret;
2772
2773         sidstr = dom_sid_string(mem_ctx, sid);
2774         NT_STATUS_HAVE_NO_MEMORY(sidstr);
2775
2776         /* We might have to create a ForeignSecurityPrincipal, even if this user
2777          * is in our own domain */
2778
2779         msg = ldb_msg_new(sidstr);
2780         if (msg == NULL) {
2781                 talloc_free(sidstr);
2782                 return NT_STATUS_NO_MEMORY;
2783         }
2784
2785         ret = dsdb_wellknown_dn(sam_ctx, sidstr,
2786                                 ldb_get_default_basedn(sam_ctx),
2787                                 DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER,
2788                                 &basedn);
2789         if (ret != LDB_SUCCESS) {
2790                 DEBUG(0, ("Failed to find DN for "
2791                           "ForeignSecurityPrincipal container - %s\n", ldb_errstring(sam_ctx)));
2792                 talloc_free(sidstr);
2793                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2794         }
2795
2796         /* add core elements to the ldb_message for the alias */
2797         msg->dn = basedn;
2798         if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s", sidstr)) {
2799                 talloc_free(sidstr);
2800                 return NT_STATUS_NO_MEMORY;
2801         }
2802
2803         ret = ldb_msg_add_string(msg, "objectClass",
2804                                  "foreignSecurityPrincipal");
2805         if (ret != LDB_SUCCESS) {
2806                 talloc_free(sidstr);
2807                 return NT_STATUS_NO_MEMORY;
2808         }
2809
2810         /* create the alias */
2811         ret = ldb_add(sam_ctx, msg);
2812         if (ret != LDB_SUCCESS) {
2813                 DEBUG(0,("Failed to create foreignSecurityPrincipal "
2814                          "record %s: %s\n", 
2815                          ldb_dn_get_linearized(msg->dn),
2816                          ldb_errstring(sam_ctx)));
2817                 talloc_free(sidstr);
2818                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2819         }
2820
2821         *ret_dn = talloc_steal(mem_ctx, msg->dn);
2822         talloc_free(sidstr);
2823
2824         return NT_STATUS_OK;
2825 }
2826
2827
2828 /*
2829   Find the DN of a domain, assuming it to be a dotted.dns name
2830 */
2831
2832 struct ldb_dn *samdb_dns_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *dns_domain) 
2833 {
2834         unsigned int i;
2835         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2836         const char *binary_encoded;
2837         const char * const *split_realm;
2838         struct ldb_dn *dn;
2839
2840         if (!tmp_ctx) {
2841                 return NULL;
2842         }
2843
2844         split_realm = (const char * const *)str_list_make(tmp_ctx, dns_domain, ".");
2845         if (!split_realm) {
2846                 talloc_free(tmp_ctx);
2847                 return NULL;
2848         }
2849         dn = ldb_dn_new(mem_ctx, ldb, NULL);
2850         for (i=0; split_realm[i]; i++) {
2851                 binary_encoded = ldb_binary_encode_string(tmp_ctx, split_realm[i]);
2852                 if (!ldb_dn_add_base_fmt(dn, "dc=%s", binary_encoded)) {
2853                         DEBUG(2, ("Failed to add dc=%s element to DN %s\n",
2854                                   binary_encoded, ldb_dn_get_linearized(dn)));
2855                         talloc_free(tmp_ctx);
2856                         return NULL;
2857                 }
2858         }
2859         if (!ldb_dn_validate(dn)) {
2860                 DEBUG(2, ("Failed to validated DN %s\n",
2861                           ldb_dn_get_linearized(dn)));
2862                 talloc_free(tmp_ctx);
2863                 return NULL;
2864         }
2865         talloc_free(tmp_ctx);
2866         return dn;
2867 }
2868
2869
2870 /*
2871   Find the DNS equivalent of a DN, in dotted DNS form
2872 */
2873 char *samdb_dn_to_dns_domain(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
2874 {
2875         int i, num_components = ldb_dn_get_comp_num(dn);
2876         char *dns_name = talloc_strdup(mem_ctx, "");
2877         if (dns_name == NULL) {
2878                 return NULL;
2879         }
2880
2881         for (i=0; i<num_components; i++) {
2882                 const struct ldb_val *v = ldb_dn_get_component_val(dn, i);
2883                 char *s;
2884                 if (v == NULL) {
2885                         talloc_free(dns_name);
2886                         return NULL;
2887                 }
2888                 s = talloc_asprintf_append_buffer(dns_name, "%*.*s.",
2889                                                   (int)v->length, (int)v->length, (char *)v->data);
2890                 if (s == NULL) {
2891                         talloc_free(dns_name);
2892                         return NULL;
2893                 }
2894                 dns_name = s;
2895         }
2896
2897         /* remove the last '.' */
2898         if (dns_name[0] != 0) {
2899                 dns_name[strlen(dns_name)-1] = 0;
2900         }
2901
2902         return dns_name;
2903 }
2904
2905 /*
2906   Find the DNS _msdcs name for a given NTDS GUID. The resulting DNS
2907   name is based on the forest DNS name
2908 */
2909 char *samdb_ntds_msdcs_dns_name(struct ldb_context *samdb,
2910                                 TALLOC_CTX *mem_ctx,
2911                                 const struct GUID *ntds_guid)
2912 {
2913         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
2914         const char *guid_str;
2915         struct ldb_dn *forest_dn;
2916         const char *dnsforest;
2917         char *ret;
2918
2919         guid_str = GUID_string(tmp_ctx, ntds_guid);
2920         if (guid_str == NULL) {
2921                 talloc_free(tmp_ctx);
2922                 return NULL;
2923         }
2924         forest_dn = ldb_get_root_basedn(samdb);
2925         if (forest_dn == NULL) {
2926                 talloc_free(tmp_ctx);
2927                 return NULL;
2928         }
2929         dnsforest = samdb_dn_to_dns_domain(tmp_ctx, forest_dn);
2930         if (dnsforest == NULL) {
2931                 talloc_free(tmp_ctx);
2932                 return NULL;
2933         }
2934         ret = talloc_asprintf(mem_ctx, "%s._msdcs.%s", guid_str, dnsforest);
2935         talloc_free(tmp_ctx);
2936         return ret;
2937 }
2938
2939
2940 /*
2941   Find the DN of a domain, be it the netbios or DNS name 
2942 */
2943 struct ldb_dn *samdb_domain_to_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, 
2944                                   const char *domain_name) 
2945 {
2946         const char * const domain_ref_attrs[] = {
2947                 "ncName", NULL
2948         };
2949         const char * const domain_ref2_attrs[] = {
2950                 NULL
2951         };
2952         struct ldb_result *res_domain_ref;
2953         char *escaped_domain = ldb_binary_encode_string(mem_ctx, domain_name);
2954         /* find the domain's DN */
2955         int ret_domain = ldb_search(ldb, mem_ctx,
2956                                             &res_domain_ref, 
2957                                             samdb_partitions_dn(ldb, mem_ctx), 
2958                                             LDB_SCOPE_ONELEVEL, 
2959                                             domain_ref_attrs,
2960                                             "(&(nETBIOSName=%s)(objectclass=crossRef))", 
2961                                             escaped_domain);
2962         if (ret_domain != LDB_SUCCESS) {
2963                 return NULL;
2964         }
2965
2966         if (res_domain_ref->count == 0) {
2967                 ret_domain = ldb_search(ldb, mem_ctx,
2968                                                 &res_domain_ref, 
2969                                                 samdb_dns_domain_to_dn(ldb, mem_ctx, domain_name),
2970                                                 LDB_SCOPE_BASE,
2971                                                 domain_ref2_attrs,
2972                                                 "(objectclass=domain)");
2973                 if (ret_domain != LDB_SUCCESS) {
2974                         return NULL;
2975                 }
2976
2977                 if (res_domain_ref->count == 1) {
2978                         return res_domain_ref->msgs[0]->dn;
2979                 }
2980                 return NULL;
2981         }
2982
2983         if (res_domain_ref->count > 1) {
2984                 DEBUG(0,("Found %d records matching domain [%s]\n", 
2985                          ret_domain, domain_name));
2986                 return NULL;
2987         }
2988
2989         return samdb_result_dn(ldb, mem_ctx, res_domain_ref->msgs[0], "nCName", NULL);
2990
2991 }
2992
2993
2994 /*
2995   use a GUID to find a DN
2996  */
2997 int dsdb_find_dn_by_guid(struct ldb_context *ldb, 
2998                          TALLOC_CTX *mem_ctx,
2999                          const struct GUID *guid,
3000                          uint32_t dsdb_flags,
3001                          struct ldb_dn **dn)
3002 {
3003         int ret;
3004         struct ldb_result *res;
3005         const char *attrs[] = { NULL };
3006         char *guid_str = GUID_string(mem_ctx, guid);
3007
3008         if (!guid_str) {
3009                 return ldb_operr(ldb);
3010         }
3011
3012         ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3013                           DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3014                           DSDB_SEARCH_SHOW_EXTENDED_DN |
3015                           DSDB_SEARCH_ONE_ONLY | dsdb_flags,
3016                           "objectGUID=%s", guid_str);
3017         talloc_free(guid_str);
3018         if (ret != LDB_SUCCESS) {
3019                 return ret;
3020         }
3021
3022         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3023         talloc_free(res);
3024
3025         return LDB_SUCCESS;
3026 }
3027
3028 /*
3029   use a DN to find a GUID with a given attribute name
3030  */
3031 int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
3032                               struct ldb_dn *dn, const char *attribute,
3033                               struct GUID *guid)
3034 {
3035         int ret;
3036         struct ldb_result *res;
3037         const char *attrs[2];
3038         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3039
3040         attrs[0] = attribute;
3041         attrs[1] = NULL;
3042
3043         ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3044                              DSDB_SEARCH_SHOW_DELETED |
3045                              DSDB_SEARCH_SHOW_RECYCLED);
3046         if (ret != LDB_SUCCESS) {
3047                 talloc_free(tmp_ctx);
3048                 return ret;
3049         }
3050         if (res->count < 1) {
3051                 talloc_free(tmp_ctx);
3052                 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3053         }
3054         *guid = samdb_result_guid(res->msgs[0], attribute);
3055         talloc_free(tmp_ctx);
3056         return LDB_SUCCESS;
3057 }
3058
3059 /*
3060   use a DN to find a GUID
3061  */
3062 int dsdb_find_guid_by_dn(struct ldb_context *ldb,
3063                          struct ldb_dn *dn, struct GUID *guid)
3064 {
3065         return dsdb_find_guid_attr_by_dn(ldb, dn, "objectGUID", guid);
3066 }
3067
3068
3069
3070 /*
3071  adds the given GUID to the given ldb_message. This value is added
3072  for the given attr_name (may be either "objectGUID" or "parentGUID").
3073  */
3074 int dsdb_msg_add_guid(struct ldb_message *msg,
3075                 struct GUID *guid,
3076                 const char *attr_name)
3077 {
3078         int ret;
3079         struct ldb_val v;
3080         NTSTATUS status;
3081         TALLOC_CTX *tmp_ctx =  talloc_init("dsdb_msg_add_guid");
3082
3083         status = GUID_to_ndr_blob(guid, tmp_ctx, &v);
3084         if (!NT_STATUS_IS_OK(status)) {
3085                 ret = LDB_ERR_OPERATIONS_ERROR;
3086                 goto done;
3087         }
3088
3089         ret = ldb_msg_add_steal_value(msg, attr_name, &v);
3090         if (ret != LDB_SUCCESS) {
3091                 DEBUG(4,(__location__ ": Failed to add %s to the message\n",
3092                                          attr_name));
3093                 goto done;
3094         }
3095
3096         ret = LDB_SUCCESS;
3097
3098 done:
3099         talloc_free(tmp_ctx);
3100         return ret;
3101
3102 }
3103
3104
3105 /*
3106   use a DN to find a SID
3107  */
3108 int dsdb_find_sid_by_dn(struct ldb_context *ldb, 
3109                         struct ldb_dn *dn, struct dom_sid *sid)
3110 {
3111         int ret;
3112         struct ldb_result *res;
3113         const char *attrs[] = { "objectSid", NULL };
3114         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3115         struct dom_sid *s;
3116
3117         ZERO_STRUCTP(sid);
3118
3119         ret = dsdb_search_dn(ldb, tmp_ctx, &res, dn, attrs,
3120                              DSDB_SEARCH_SHOW_DELETED |
3121                              DSDB_SEARCH_SHOW_RECYCLED);
3122         if (ret != LDB_SUCCESS) {
3123                 talloc_free(tmp_ctx);
3124                 return ret;
3125         }
3126         if (res->count < 1) {
3127                 talloc_free(tmp_ctx);
3128                 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3129         }
3130         s = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSid");
3131         if (s == NULL) {
3132                 talloc_free(tmp_ctx);
3133                 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3134         }
3135         *sid = *s;
3136         talloc_free(tmp_ctx);
3137         return LDB_SUCCESS;
3138 }
3139
3140 /*
3141   use a SID to find a DN
3142  */
3143 int dsdb_find_dn_by_sid(struct ldb_context *ldb,
3144                         TALLOC_CTX *mem_ctx,
3145                         struct dom_sid *sid, struct ldb_dn **dn)
3146 {
3147         int ret;
3148         struct ldb_result *res;
3149         const char *attrs[] = { NULL };
3150         char *sid_str = ldap_encode_ndr_dom_sid(mem_ctx, sid);
3151
3152         if (!sid_str) {
3153                 return ldb_operr(ldb);
3154         }
3155
3156         ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
3157                           DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
3158                           DSDB_SEARCH_SHOW_EXTENDED_DN |
3159                           DSDB_SEARCH_ONE_ONLY,
3160                           "objectSid=%s", sid_str);
3161         talloc_free(sid_str);
3162         if (ret != LDB_SUCCESS) {
3163                 return ret;
3164         }
3165
3166         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
3167         talloc_free(res);
3168
3169         return LDB_SUCCESS;
3170 }
3171
3172 /*
3173   load a repsFromTo blob list for a given partition GUID
3174   attr must be "repsFrom" or "repsTo"
3175  */
3176 WERROR dsdb_loadreps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3177                      const char *attr, struct repsFromToBlob **r, uint32_t *count)
3178 {
3179         const char *attrs[] = { attr, NULL };
3180         struct ldb_result *res = NULL;
3181         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3182         unsigned int i;
3183         struct ldb_message_element *el;
3184         int ret;
3185
3186         *r = NULL;
3187         *count = 0;
3188
3189         ret = dsdb_search_dn(sam_ctx, tmp_ctx, &res, dn, attrs, 0);
3190         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3191                 /* partition hasn't been replicated yet */
3192                 return WERR_OK;
3193         }
3194         if (ret != LDB_SUCCESS) {
3195                 DEBUG(0,("dsdb_loadreps: failed to read partition object: %s\n", ldb_errstring(sam_ctx)));
3196                 talloc_free(tmp_ctx);
3197                 return WERR_DS_DRA_INTERNAL_ERROR;
3198         }
3199
3200         el = ldb_msg_find_element(res->msgs[0], attr);
3201         if (el == NULL) {
3202                 /* it's OK to be empty */
3203                 talloc_free(tmp_ctx);
3204                 return WERR_OK;
3205         }
3206
3207         *count = el->num_values;
3208         *r = talloc_array(mem_ctx, struct repsFromToBlob, *count);
3209         if (*r == NULL) {
3210                 talloc_free(tmp_ctx);
3211                 return WERR_DS_DRA_INTERNAL_ERROR;
3212         }
3213
3214         for (i=0; i<(*count); i++) {
3215                 enum ndr_err_code ndr_err;
3216                 ndr_err = ndr_pull_struct_blob(&el->values[i], 
3217                                                mem_ctx, 
3218                                                &(*r)[i], 
3219                                                (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
3220                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3221                         talloc_free(tmp_ctx);
3222                         return WERR_DS_DRA_INTERNAL_ERROR;
3223                 }
3224         }
3225
3226         talloc_free(tmp_ctx);
3227         
3228         return WERR_OK;
3229 }
3230
3231 /*
3232   save the repsFromTo blob list for a given partition GUID
3233   attr must be "repsFrom" or "repsTo"
3234  */
3235 WERROR dsdb_savereps(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3236                      const char *attr, struct repsFromToBlob *r, uint32_t count)
3237 {
3238         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3239         struct ldb_message *msg;
3240         struct ldb_message_element *el;
3241         unsigned int i;
3242
3243         msg = ldb_msg_new(tmp_ctx);
3244         msg->dn = dn;
3245         if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_REPLACE, &el) != LDB_SUCCESS) {
3246                 goto failed;
3247         }
3248
3249         el->values = talloc_array(msg, struct ldb_val, count);
3250         if (!el->values) {
3251                 goto failed;
3252         }
3253
3254         for (i=0; i<count; i++) {
3255                 struct ldb_val v;
3256                 enum ndr_err_code ndr_err;
3257
3258                 ndr_err = ndr_push_struct_blob(&v, tmp_ctx, 
3259                                                &r[i], 
3260                                                (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
3261                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3262                         goto failed;
3263                 }
3264
3265                 el->num_values++;
3266                 el->values[i] = v;
3267         }
3268
3269         if (dsdb_modify(sam_ctx, msg, 0) != LDB_SUCCESS) {
3270                 DEBUG(0,("Failed to store %s - %s\n", attr, ldb_errstring(sam_ctx)));
3271                 goto failed;
3272         }
3273
3274         talloc_free(tmp_ctx);
3275         
3276         return WERR_OK;
3277
3278 failed:
3279         talloc_free(tmp_ctx);
3280         return WERR_DS_DRA_INTERNAL_ERROR;
3281 }
3282
3283
3284 /*
3285   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
3286   object for a partition
3287  */
3288 int dsdb_load_partition_usn(struct ldb_context *ldb, struct ldb_dn *dn,
3289                                 uint64_t *uSN, uint64_t *urgent_uSN)
3290 {
3291         struct ldb_request *req;
3292         int ret;
3293         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
3294         struct dsdb_control_current_partition *p_ctrl;
3295         struct ldb_result *res;
3296
3297         res = talloc_zero(tmp_ctx, struct ldb_result);
3298         if (!res) {
3299                 talloc_free(tmp_ctx);
3300                 return ldb_oom(ldb);
3301         }
3302
3303         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
3304                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
3305                                    LDB_SCOPE_BASE,
3306                                    NULL, NULL,
3307                                    NULL,
3308                                    res, ldb_search_default_callback,
3309                                    NULL);
3310         if (ret != LDB_SUCCESS) {
3311                 talloc_free(tmp_ctx);
3312                 return ret;
3313         }
3314
3315         p_ctrl = talloc(req, struct dsdb_control_current_partition);
3316         if (p_ctrl == NULL) {
3317                 talloc_free(tmp_ctx);
3318                 return ldb_oom(ldb);
3319         }
3320         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
3321         p_ctrl->dn = dn;
3322         
3323         ret = ldb_request_add_control(req,
3324                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
3325                                       false, p_ctrl);
3326         if (ret != LDB_SUCCESS) {
3327                 talloc_free(tmp_ctx);
3328                 return ret;
3329         }
3330         
3331         /* Run the new request */
3332         ret = ldb_request(ldb, req);
3333         
3334         if (ret == LDB_SUCCESS) {
3335                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
3336         }
3337
3338         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
3339                 /* it hasn't been created yet, which means
3340                    an implicit value of zero */
3341                 *uSN = 0;
3342                 talloc_free(tmp_ctx);
3343                 return LDB_SUCCESS;
3344         }
3345
3346         if (ret != LDB_SUCCESS) {
3347                 talloc_free(tmp_ctx);
3348                 return ret;
3349         }
3350
3351         if (res->count < 1) {
3352                 *uSN = 0;
3353                 if (urgent_uSN) {
3354                         *urgent_uSN = 0;
3355                 }
3356         } else {
3357                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
3358                 if (urgent_uSN) {
3359                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
3360                 }
3361         }
3362
3363         talloc_free(tmp_ctx);
3364
3365         return LDB_SUCCESS;     
3366 }
3367
3368 int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
3369                                                    const struct drsuapi_DsReplicaCursor2 *c2)
3370 {
3371         return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3372 }
3373
3374 int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
3375                                     const struct drsuapi_DsReplicaCursor *c2)
3376 {
3377         return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
3378 }
3379
3380
3381 /*
3382   see if a computer identified by its invocationId is a RODC
3383 */
3384 int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
3385 {
3386         /* 1) find the DN for this servers NTDSDSA object
3387            2) search for the msDS-isRODC attribute
3388            3) if not present then not a RODC
3389            4) if present and TRUE then is a RODC
3390         */
3391         struct ldb_dn *config_dn;
3392         const char *attrs[] = { "msDS-isRODC", NULL };
3393         int ret;
3394         struct ldb_result *res;
3395         TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
3396
3397         config_dn = ldb_get_config_basedn(sam_ctx);
3398         if (!config_dn) {
3399                 talloc_free(tmp_ctx);
3400                 return ldb_operr(sam_ctx);
3401         }
3402
3403         ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
3404                           DSDB_SEARCH_ONE_ONLY, "objectGUID=%s", GUID_string(tmp_ctx, objectGUID));
3405
3406         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3407                 *is_rodc = false;
3408                 talloc_free(tmp_ctx);
3409                 return LDB_SUCCESS;
3410         }
3411
3412         if (ret != LDB_SUCCESS) {
3413                 DEBUG(1,(("Failed to find our own NTDS Settings object by objectGUID=%s!\n"),
3414                          GUID_string(tmp_ctx, objectGUID)));
3415                 *is_rodc = false;
3416                 talloc_free(tmp_ctx);
3417                 return ret;
3418         }
3419
3420         ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
3421         *is_rodc = (ret == 1);
3422
3423         talloc_free(tmp_ctx);
3424         return LDB_SUCCESS;
3425 }
3426
3427
3428 /*
3429   see if we are a RODC
3430 */
3431 int samdb_rodc(struct ldb_context *sam_ctx, bool *am_rodc)
3432 {
3433         const struct GUID *objectGUID;
3434         int ret;
3435         bool *cached;
3436
3437         /* see if we have a cached copy */
3438         cached = (bool *)ldb_get_opaque(sam_ctx, "cache.am_rodc");
3439         if (cached) {
3440                 *am_rodc = *cached;
3441                 return LDB_SUCCESS;
3442         }
3443
3444         objectGUID = samdb_ntds_objectGUID(sam_ctx);
3445         if (!objectGUID) {
3446                 return ldb_operr(sam_ctx);
3447         }
3448
3449         ret = samdb_is_rodc(sam_ctx, objectGUID, am_rodc);
3450         if (ret != LDB_SUCCESS) {
3451                 return ret;
3452         }
3453
3454         cached = talloc(sam_ctx, bool);
3455         if (cached == NULL) {
3456                 return ldb_oom(sam_ctx);
3457         }
3458         *cached = *am_rodc;
3459
3460         ret = ldb_set_opaque(sam_ctx, "cache.am_rodc", cached);
3461         if (ret != LDB_SUCCESS) {
3462                 talloc_free(cached);
3463                 return ldb_operr(sam_ctx);
3464         }
3465
3466         return LDB_SUCCESS;
3467 }
3468
3469 bool samdb_set_am_rodc(struct ldb_context *ldb, bool am_rodc)
3470 {
3471         TALLOC_CTX *tmp_ctx;
3472         bool *cached;
3473
3474         tmp_ctx = talloc_new(ldb);
3475         if (tmp_ctx == NULL) {
3476                 goto failed;
3477         }
3478
3479         cached = talloc(tmp_ctx, bool);
3480         if (!cached) {
3481                 goto failed;
3482         }
3483
3484         *cached = am_rodc;
3485         if (ldb_set_opaque(ldb, "cache.am_rodc", cached) != LDB_SUCCESS) {
3486                 goto failed;
3487         }
3488
3489         talloc_steal(ldb, cached);
3490         talloc_free(tmp_ctx);
3491         return true;
3492
3493 failed:
3494         DEBUG(1,("Failed to set our own cached am_rodc in the ldb!\n"));
3495         talloc_free(tmp_ctx);
3496         return false;
3497 }
3498
3499
3500 /*
3501  * return NTDSSiteSettings options. See MS-ADTS 7.1.1.2.2.1.1
3502  * flags are DS_NTDSSETTINGS_OPT_*
3503  */
3504 int samdb_ntds_site_settings_options(struct ldb_context *ldb_ctx,
3505                                         uint32_t *options)
3506 {
3507         int rc;
3508         TALLOC_CTX *tmp_ctx;
3509         struct ldb_result *res;
3510         struct ldb_dn *site_dn;
3511         const char *attrs[] = { "options", NULL };
3512
3513         tmp_ctx = talloc_new(ldb_ctx);
3514         if (tmp_ctx == NULL)
3515                 goto failed;
3516
3517         /* Retrieve the site dn for the ldb that we
3518          * have open.  This is our local site.
3519          */
3520         site_dn = samdb_server_site_dn(ldb_ctx, tmp_ctx);
3521         if (site_dn == NULL)
3522                 goto failed;
3523
3524         /* Perform a one level (child) search from the local
3525          * site distinguided name.   We're looking for the
3526          * "options" attribute within the nTDSSiteSettings
3527          * object
3528          */
3529         rc = ldb_search(ldb_ctx, tmp_ctx, &res, site_dn,
3530                         LDB_SCOPE_ONELEVEL, attrs,
3531                         "objectClass=nTDSSiteSettings");
3532
3533         if (rc != LDB_SUCCESS || res->count != 1)
3534                 goto failed;
3535
3536         *options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
3537
3538         talloc_free(tmp_ctx);
3539
3540         return LDB_SUCCESS;
3541
3542 failed:
3543         DEBUG(1,("Failed to find our NTDS Site Settings options in ldb!\n"));
3544         talloc_free(tmp_ctx);
3545         return ldb_error(ldb_ctx, LDB_ERR_NO_SUCH_OBJECT, __func__);
3546 }
3547
3548 /*
3549   return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1 
3550
3551   flags are DS_NTDS_OPTION_*
3552 */
3553 int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
3554 {
3555         TALLOC_CTX *tmp_ctx;
3556         const char *attrs[] = { "options", NULL };
3557         int ret;
3558         struct ldb_result *res;
3559
3560         tmp_ctx = talloc_new(ldb);
3561         if (tmp_ctx == NULL) {
3562                 goto failed;
3563         }
3564
3565         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
3566         if (ret != LDB_SUCCESS) {
3567                 goto failed;
3568         }
3569
3570         if (res->count != 1) {
3571                 goto failed;
3572         }
3573
3574         *options = ldb_msg_find_attr_as_uint(res->msgs[0], "options", 0);
3575
3576         talloc_free(tmp_ctx);
3577
3578         return LDB_SUCCESS;
3579
3580 failed:
3581         DEBUG(1,("Failed to find our own NTDS Settings options in the ldb!\n"));
3582         talloc_free(tmp_ctx);
3583         return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3584 }
3585
3586 const char* samdb_ntds_object_category(TALLOC_CTX *tmp_ctx, struct ldb_context *ldb)
3587 {
3588         const char *attrs[] = { "objectCategory", NULL };
3589         int ret;
3590         struct ldb_result *res;
3591
3592         ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb, tmp_ctx), LDB_SCOPE_BASE, attrs, NULL);
3593         if (ret != LDB_SUCCESS) {
3594                 goto failed;
3595         }
3596
3597         if (res->count != 1) {
3598                 goto failed;
3599         }
3600
3601         return ldb_msg_find_attr_as_string(res->msgs[0], "objectCategory", NULL);
3602
3603 failed:
3604         DEBUG(1,("Failed to find our own NTDS Settings objectCategory in the ldb!\n"));
3605         return NULL;
3606 }
3607
3608 /*
3609  * Function which generates a "lDAPDisplayName" attribute from a "CN" one.
3610  * Algorithm implemented according to MS-ADTS 3.1.1.2.3.4
3611  */
3612 const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn)
3613 {
3614         char **tokens, *ret;
3615         size_t i;
3616
3617         tokens = str_list_make(mem_ctx, cn, " -_");
3618         if (tokens == NULL || tokens[0] == NULL) {
3619                 return NULL;
3620         }
3621
3622         /* "tolower()" and "toupper()" should also work properly on 0x00 */
3623         tokens[0][0] = tolower(tokens[0][0]);
3624         for (i = 1; tokens[i] != NULL; i++)
3625                 tokens[i][0] = toupper(tokens[i][0]);
3626
3627         ret = talloc_strdup(mem_ctx, tokens[0]);
3628         for (i = 1; tokens[i] != NULL; i++)
3629                 ret = talloc_asprintf_append_buffer(ret, "%s", tokens[i]);
3630
3631         talloc_free(tokens);
3632
3633         return ret;
3634 }
3635
3636 /*
3637  * This detects and returns the domain functional level (DS_DOMAIN_FUNCTION_*)
3638  */
3639 int dsdb_functional_level(struct ldb_context *ldb)
3640 {
3641         int *domainFunctionality =
3642                 talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
3643         if (!domainFunctionality) {
3644                 /* this is expected during initial provision */
3645                 DEBUG(4,(__location__ ": WARNING: domainFunctionality not setup\n"));
3646                 return DS_DOMAIN_FUNCTION_2000;
3647         }
3648         return *domainFunctionality;
3649 }
3650
3651 /*
3652  * This detects and returns the forest functional level (DS_DOMAIN_FUNCTION_*)
3653  */
3654 int dsdb_forest_functional_level(struct ldb_context *ldb)
3655 {
3656         int *forestFunctionality =
3657                 talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), int);
3658         if (!forestFunctionality) {
3659                 DEBUG(0,(__location__ ": WARNING: forestFunctionality not setup\n"));
3660                 return DS_DOMAIN_FUNCTION_2000;
3661         }
3662         return *forestFunctionality;
3663 }
3664
3665 /*
3666   set a GUID in an extended DN structure
3667  */
3668 int dsdb_set_extended_dn_guid(struct ldb_dn *dn, const struct GUID *guid, const char *component_name)
3669 {
3670         struct ldb_val v;
3671         NTSTATUS status;
3672         int ret;
3673
3674         status = GUID_to_ndr_blob(guid, dn, &v);
3675         if (!NT_STATUS_IS_OK(status)) {
3676                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
3677         }
3678
3679         ret = ldb_dn_set_extended_component(dn, component_name, &v);
3680         data_blob_free(&v);
3681         return ret;
3682 }
3683
3684 /*
3685   return a GUID from a extended DN structure
3686  */
3687 NTSTATUS dsdb_get_extended_dn_guid(struct ldb_dn *dn, struct GUID *guid, const char *component_name)
3688 {
3689         const struct ldb_val *v;
3690
3691         v = ldb_dn_get_extended_component(dn, component_name);
3692         if (v == NULL) {
3693                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3694         }
3695
3696         return GUID_from_ndr_blob(v, guid);
3697 }
3698
3699 /*
3700   return a uint64_t from a extended DN structure
3701  */
3702 NTSTATUS dsdb_get_extended_dn_uint64(struct ldb_dn *dn, uint64_t *val, const char *component_name)
3703 {
3704         const struct ldb_val *v;
3705
3706         v = ldb_dn_get_extended_component(dn, component_name);
3707         if (v == NULL) {
3708                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3709         }
3710
3711         {
3712                 char s[v->length+1];
3713                 memcpy(s, v->data, v->length);
3714                 s[v->length] = 0;
3715
3716                 *val = strtoull(s, NULL, 0);
3717         }
3718         return NT_STATUS_OK;
3719 }
3720
3721 /*
3722   return a NTTIME from a extended DN structure
3723  */
3724 NTSTATUS dsdb_get_extended_dn_nttime(struct ldb_dn *dn, NTTIME *nttime, const char *component_name)
3725 {
3726         return dsdb_get_extended_dn_uint64(dn, nttime, component_name);
3727 }
3728
3729 /*
3730   return a uint32_t from a extended DN structure
3731  */
3732 NTSTATUS dsdb_get_extended_dn_uint32(struct ldb_dn *dn, uint32_t *val, const char *component_name)
3733 {
3734         const struct ldb_val *v;
3735
3736         v = ldb_dn_get_extended_component(dn, component_name);
3737         if (v == NULL) {
3738                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3739         }
3740
3741         {
3742                 char s[v->length + 1];
3743                 memcpy(s, v->data, v->length);
3744                 s[v->length] = 0;
3745                 *val = strtoul(s, NULL, 0);
3746         }
3747
3748         return NT_STATUS_OK;
3749 }
3750
3751 /*
3752   return a dom_sid from a extended DN structure
3753  */
3754 NTSTATUS dsdb_get_extended_dn_sid(struct ldb_dn *dn, struct dom_sid *sid, const char *component_name)
3755 {
3756         const struct ldb_val *sid_blob;
3757         enum ndr_err_code ndr_err;
3758
3759         sid_blob = ldb_dn_get_extended_component(dn, component_name);
3760         if (!sid_blob) {
3761                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3762         }
3763
3764         ndr_err = ndr_pull_struct_blob_all_noalloc(sid_blob, sid,
3765                                                    (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
3766         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3767                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
3768                 return status;
3769         }
3770
3771         return NT_STATUS_OK;
3772 }
3773
3774
3775 /*
3776   return RMD_FLAGS directly from a ldb_dn
3777   returns 0 if not found
3778  */
3779 uint32_t dsdb_dn_rmd_flags(struct ldb_dn *dn)
3780 {
3781         const struct ldb_val *v;
3782         char buf[32];
3783         v = ldb_dn_get_extended_component(dn, "RMD_FLAGS");
3784         if (!v || v->length > sizeof(buf)-1) return 0;
3785         strncpy(buf, (const char *)v->data, v->length);
3786         buf[v->length] = 0;
3787         return strtoul(buf, NULL, 10);
3788 }
3789
3790 /*
3791   return RMD_FLAGS directly from a ldb_val for a DN
3792   returns 0 if RMD_FLAGS is not found
3793  */
3794 uint32_t dsdb_dn_val_rmd_flags(const struct ldb_val *val)
3795 {
3796         const char *p;
3797         uint32_t flags;
3798         char *end;
3799
3800         if (val->length < 13) {
3801                 return 0;
3802         }
3803         p = memmem(val->data, val->length, "<RMD_FLAGS=", 11);
3804         if (!p) {
3805                 return 0;
3806         }
3807         flags = strtoul(p+11, &end, 10);
3808         if (!end || *end != '>') {
3809                 /* it must end in a > */
3810                 return 0;
3811         }
3812         return flags;
3813 }
3814
3815 /*
3816   return true if a ldb_val containing a DN in storage form is deleted
3817  */
3818 bool dsdb_dn_is_deleted_val(const struct ldb_val *val)
3819 {
3820         return (dsdb_dn_val_rmd_flags(val) & DSDB_RMD_FLAG_DELETED) != 0;
3821 }
3822
3823 /*
3824   return true if a ldb_val containing a DN in storage form is
3825   in the upgraded w2k3 linked attribute format
3826  */
3827 bool dsdb_dn_is_upgraded_link_val(const struct ldb_val *val)
3828 {
3829         return memmem(val->data, val->length, "<RMD_VERSION=", 13) != NULL;
3830 }
3831
3832 /*
3833   return a DN for a wellknown GUID
3834  */
3835 int dsdb_wellknown_dn(struct ldb_context *samdb, TALLOC_CTX *mem_ctx,
3836                       struct ldb_dn *nc_root, const char *wk_guid,
3837                       struct ldb_dn **wkguid_dn)
3838 {
3839         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
3840         const char *attrs[] = { NULL };
3841         int ret;
3842         struct ldb_dn *dn;
3843         struct ldb_result *res;
3844
3845         /* construct the magic WKGUID DN */
3846         dn = ldb_dn_new_fmt(tmp_ctx, samdb, "<WKGUID=%s,%s>",
3847                             wk_guid, ldb_dn_get_linearized(nc_root));
3848         if (!wkguid_dn) {
3849                 talloc_free(tmp_ctx);
3850                 return ldb_operr(samdb);
3851         }
3852
3853         ret = dsdb_search_dn(samdb, tmp_ctx, &res, dn, attrs,
3854                              DSDB_SEARCH_SHOW_DELETED |
3855                              DSDB_SEARCH_SHOW_RECYCLED);
3856         if (ret != LDB_SUCCESS) {
3857                 talloc_free(tmp_ctx);
3858                 return ret;
3859         }
3860
3861         (*wkguid_dn) = talloc_steal(mem_ctx, res->msgs[0]->dn);
3862         talloc_free(tmp_ctx);
3863         return LDB_SUCCESS;
3864 }
3865
3866
3867 static int dsdb_dn_compare_ptrs(struct ldb_dn **dn1, struct ldb_dn **dn2)
3868 {
3869         return ldb_dn_compare(*dn1, *dn2);
3870 }
3871
3872 /*
3873   find a NC root given a DN within the NC
3874  */
3875 int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
3876                       struct ldb_dn **nc_root)
3877 {
3878         const char *root_attrs[] = { "namingContexts", NULL };
3879         TALLOC_CTX *tmp_ctx;
3880         int ret;
3881         struct ldb_message_element *el;
3882         struct ldb_result *root_res;
3883         unsigned int i;
3884         struct ldb_dn **nc_dns;
3885
3886         tmp_ctx = talloc_new(samdb);
3887         if (tmp_ctx == NULL) {
3888                 return ldb_oom(samdb);
3889         }
3890
3891         ret = ldb_search(samdb, tmp_ctx, &root_res,
3892                          ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
3893         if (ret != LDB_SUCCESS || root_res->count == 0) {
3894                 DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
3895                 talloc_free(tmp_ctx);
3896                 return ret;
3897         }
3898
3899         el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
3900         if ((el == NULL) || (el->num_values < 3)) {
3901                 struct ldb_message *tmp_msg;
3902
3903                 DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list."));
3904
3905                 /* This generates a temporary list of NCs in order to let the
3906                  * provisioning work. */
3907                 tmp_msg = ldb_msg_new(tmp_ctx);
3908                 if (tmp_msg == NULL) {
3909                         talloc_free(tmp_ctx);
3910                         return ldb_oom(samdb);
3911                 }
3912                 ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
3913                                                ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
3914                 if (ret != LDB_SUCCESS) {
3915                         talloc_free(tmp_ctx);
3916                         return ret;
3917                 }
3918                 ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
3919                                                ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
3920                 if (ret != LDB_SUCCESS) {
3921                         talloc_free(tmp_ctx);
3922                         return ret;
3923                 }
3924                 ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
3925                                                ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
3926                 if (ret != LDB_SUCCESS) {
3927                         talloc_free(tmp_ctx);
3928                         return ret;
3929                 }
3930                 el = &tmp_msg->elements[0];
3931         }
3932
3933        nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
3934        if (!nc_dns) {
3935                talloc_free(tmp_ctx);
3936                return ldb_oom(samdb);
3937        }
3938
3939        for (i=0; i<el->num_values; i++) {
3940                nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
3941                if (nc_dns[i] == NULL) {
3942                        talloc_free(tmp_ctx);
3943                        return ldb_operr(samdb);
3944                }
3945        }
3946
3947        TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);
3948
3949        for (i=0; i<el->num_values; i++) {
3950                if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
3951                        (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
3952                        talloc_free(tmp_ctx);
3953                        return LDB_SUCCESS;
3954                }
3955        }
3956
3957        talloc_free(tmp_ctx);
3958        return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3959 }
3960
3961
3962 /*
3963   find the deleted objects DN for any object, by looking for the NC
3964   root, then looking up the wellknown GUID
3965  */
3966 int dsdb_get_deleted_objects_dn(struct ldb_context *ldb,
3967                                 TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
3968                                 struct ldb_dn **do_dn)
3969 {
3970         struct ldb_dn *nc_root;
3971         int ret;
3972
3973         ret = dsdb_find_nc_root(ldb, mem_ctx, obj_dn, &nc_root);
3974         if (ret != LDB_SUCCESS) {
3975                 return ret;
3976         }
3977
3978         ret = dsdb_wellknown_dn(ldb, mem_ctx, nc_root, DS_GUID_DELETED_OBJECTS_CONTAINER, do_dn);
3979         talloc_free(nc_root);
3980         return ret;
3981 }
3982
3983 /*
3984   return the tombstoneLifetime, in days
3985  */
3986 int dsdb_tombstone_lifetime(struct ldb_context *ldb, uint32_t *lifetime)
3987 {
3988         struct ldb_dn *dn;
3989         dn = ldb_get_config_basedn(ldb);
3990         if (!dn) {
3991                 return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
3992         }
3993         dn = ldb_dn_copy(ldb, dn);
3994         if (!dn) {
3995                 return ldb_operr(ldb);
3996         }
3997         /* see MS-ADTS section 7.1.1.2.4.1.1. There doesn't appear to
3998          be a wellknown GUID for this */
3999         if (!ldb_dn_add_child_fmt(dn, "CN=Directory Service,CN=Windows NT,CN=Services")) {
4000                 talloc_free(dn);
4001                 return ldb_operr(ldb);
4002         }
4003
4004         *lifetime = samdb_search_uint(ldb, dn, 180, dn, "tombstoneLifetime", "objectClass=nTDSService");
4005         talloc_free(dn);
4006         return LDB_SUCCESS;
4007 }
4008
4009 /*
4010   compare a ldb_val to a string case insensitively
4011  */
4012 int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
4013 {
4014         size_t len = strlen(s);
4015         int ret;
4016         if (len > v->length) return 1;
4017         ret = strncasecmp(s, (const char *)v->data, v->length);
4018         if (ret != 0) return ret;
4019         if (v->length > len && v->data[len] != 0) {
4020                 return -1;
4021         }
4022         return 0;
4023 }
4024
4025
4026 /*
4027   load the UDV for a partition in v2 format
4028   The list is returned sorted, and with our local cursor added
4029  */
4030 int dsdb_load_udv_v2(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
4031                      struct drsuapi_DsReplicaCursor2 **cursors, uint32_t *count)
4032 {
4033         static const char *attrs[] = { "replUpToDateVector", NULL };
4034         struct ldb_result *r;
4035         const struct ldb_val *ouv_value;
4036         unsigned int i;
4037         int ret;
4038         uint64_t highest_usn = 0;
4039         const struct GUID *our_invocation_id;
4040         static const struct timeval tv1970;
4041         NTTIME nt1970 = timeval_to_nttime(&tv1970);
4042
4043         ret = dsdb_search_dn(samdb, mem_ctx, &r, dn, attrs, DSDB_SEARCH_SHOW_RECYCLED|DSDB_SEARCH_SHOW_DELETED);
4044         if (ret != LDB_SUCCESS) {
4045                 return ret;
4046         }
4047
4048         ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
4049         if (ouv_value) {
4050                 enum ndr_err_code ndr_err;
4051                 struct replUpToDateVectorBlob ouv;
4052
4053                 ndr_err = ndr_pull_struct_blob(ouv_value, r, &ouv,
4054                                                (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
4055                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4056                         talloc_free(r);
4057                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
4058                 }
4059                 if (ouv.version != 2) {
4060                         /* we always store as version 2, and
4061                          * replUpToDateVector is not replicated
4062                          */
4063                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
4064                 }
4065
4066                 *count = ouv.ctr.ctr2.count;
4067                 *cursors = talloc_steal(mem_ctx, ouv.ctr.ctr2.cursors);
4068         } else {
4069                 *count = 0;
4070                 *cursors = NULL;
4071         }
4072
4073         talloc_free(r);
4074
4075         our_invocation_id = samdb_ntds_invocation_id(samdb);
4076         if (!our_invocation_id) {
4077                 DEBUG(0,(__location__ ": No invocationID on samdb - %s\n", ldb_errstring(samdb)));
4078                 talloc_free(*cursors);
4079                 return ldb_operr(samdb);
4080         }
4081
4082         ret = ldb_sequence_number(samdb, LDB_SEQ_HIGHEST_SEQ, &highest_usn);
4083         if (ret != LDB_SUCCESS) {
4084                 /* nothing to add - this can happen after a vampire */
4085                 TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4086                 return LDB_SUCCESS;
4087         }
4088
4089         for (i=0; i<*count; i++) {
4090                 if (GUID_equal(our_invocation_id, &(*cursors)[i].source_dsa_invocation_id)) {
4091                         (*cursors)[i].highest_usn = highest_usn;
4092                         (*cursors)[i].last_sync_success = nt1970;
4093                         TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4094                         return LDB_SUCCESS;
4095                 }
4096         }
4097
4098         (*cursors) = talloc_realloc(mem_ctx, *cursors, struct drsuapi_DsReplicaCursor2, (*count)+1);
4099         if (! *cursors) {
4100                 return ldb_oom(samdb);
4101         }
4102
4103         (*cursors)[*count].source_dsa_invocation_id = *our_invocation_id;
4104         (*cursors)[*count].highest_usn = highest_usn;
4105         (*cursors)[*count].last_sync_success = nt1970;
4106         (*count)++;
4107
4108         TYPESAFE_QSORT(*cursors, *count, drsuapi_DsReplicaCursor2_compare);
4109
4110         return LDB_SUCCESS;
4111 }
4112
4113 /*
4114   load the UDV for a partition in version 1 format
4115   The list is returned sorted, and with our local cursor added
4116  */
4117 int dsdb_load_udv_v1(struct ldb_context *samdb, struct ldb_dn *dn, TALLOC_CTX *mem_ctx,
4118                      struct drsuapi_DsReplicaCursor **cursors, uint32_t *count)
4119 {
4120         struct drsuapi_DsReplicaCursor2 *v2;
4121         uint32_t i;
4122         int ret;
4123
4124         ret = dsdb_load_udv_v2(samdb, dn, mem_ctx, &v2, count);
4125         if (ret != LDB_SUCCESS) {
4126                 return ret;
4127         }
4128
4129         if (*count == 0) {
4130                 talloc_free(v2);
4131                 *cursors = NULL;
4132                 return LDB_SUCCESS;
4133         }
4134
4135         *cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, *count);
4136         if (*cursors == NULL) {
4137                 talloc_free(v2);
4138                 return ldb_oom(samdb);
4139         }
4140
4141         for (i=0; i<*count; i++) {
4142                 (*cursors)[i].source_dsa_invocation_id = v2[i].source_dsa_invocation_id;
4143                 (*cursors)[i].highest_usn = v2[i].highest_usn;
4144         }
4145         talloc_free(v2);
4146         return LDB_SUCCESS;
4147 }
4148
4149 /*
4150   add a set of controls to a ldb_request structure based on a set of
4151   flags. See util.h for a list of available flags
4152  */
4153 int dsdb_request_add_controls(struct ldb_request *req, uint32_t dsdb_flags)
4154 {
4155         int ret;
4156         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
4157                 struct ldb_search_options_control *options;
4158                 /* Using the phantom root control allows us to search all partitions */
4159                 options = talloc(req, struct ldb_search_options_control);
4160                 if (options == NULL) {
4161                         return LDB_ERR_OPERATIONS_ERROR;
4162                 }
4163                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
4164
4165                 ret = ldb_request_add_control(req,
4166                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
4167                                               true, options);
4168                 if (ret != LDB_SUCCESS) {
4169                         return ret;
4170                 }
4171         }
4172
4173         if (dsdb_flags & DSDB_SEARCH_NO_GLOBAL_CATALOG) {
4174                 ret = ldb_request_add_control(req,
4175                                               DSDB_CONTROL_NO_GLOBAL_CATALOG,
4176                                               false, NULL);
4177                 if (ret != LDB_SUCCESS) {
4178                         return ret;
4179                 }
4180         }
4181
4182         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
4183                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
4184                 if (ret != LDB_SUCCESS) {
4185                         return ret;
4186                 }
4187         }
4188
4189         if (dsdb_flags & DSDB_SEARCH_SHOW_RECYCLED) {
4190                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, false, NULL);
4191                 if (ret != LDB_SUCCESS) {
4192                         return ret;
4193                 }
4194         }
4195
4196         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
4197                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, false, NULL);
4198                 if (ret != LDB_SUCCESS) {
4199                         return ret;
4200                 }
4201         }
4202
4203         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
4204                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
4205                 if (!extended_ctrl) {
4206                         return LDB_ERR_OPERATIONS_ERROR;
4207                 }
4208                 extended_ctrl->type = 1;
4209
4210                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
4211                 if (ret != LDB_SUCCESS) {
4212                         return ret;
4213                 }
4214         }
4215
4216         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
4217                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
4218                 if (ret != LDB_SUCCESS) {
4219                         return ret;
4220                 }
4221         }
4222
4223         if (dsdb_flags & DSDB_MODIFY_RELAX) {
4224                 ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
4225                 if (ret != LDB_SUCCESS) {
4226                         return ret;
4227                 }
4228         }
4229
4230         if (dsdb_flags & DSDB_MODIFY_PERMISSIVE) {
4231                 ret = ldb_request_add_control(req, LDB_CONTROL_PERMISSIVE_MODIFY_OID, false, NULL);
4232                 if (ret != LDB_SUCCESS) {
4233                         return ret;
4234                 }
4235         }
4236
4237         if (dsdb_flags & DSDB_FLAG_AS_SYSTEM) {
4238                 ret = ldb_request_add_control(req, LDB_CONTROL_AS_SYSTEM_OID, false, NULL);
4239                 if (ret != LDB_SUCCESS) {
4240                         return ret;
4241                 }
4242         }
4243
4244         if (dsdb_flags & DSDB_TREE_DELETE) {
4245                 ret = ldb_request_add_control(req, LDB_CONTROL_TREE_DELETE_OID, false, NULL);
4246                 if (ret != LDB_SUCCESS) {
4247                         return ret;
4248                 }
4249         }
4250
4251         if (dsdb_flags & DSDB_PROVISION) {
4252                 ret = ldb_request_add_control(req, LDB_CONTROL_PROVISION_OID, false, NULL);
4253                 if (ret != LDB_SUCCESS) {
4254                         return ret;
4255                 }
4256         }
4257
4258         /* This is a special control to bypass the password_hash module for use in pdb_samba4 for Samba3 upgrades */
4259         if (dsdb_flags & DSDB_BYPASS_PASSWORD_HASH) {
4260                 ret = ldb_request_add_control(req, DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID, true, NULL);
4261                 if (ret != LDB_SUCCESS) {
4262                         return ret;
4263                 }
4264         }
4265
4266         if (dsdb_flags & DSDB_PASSWORD_BYPASS_LAST_SET) {
4267                 /* 
4268                  * This must not be critical, as it will only be
4269                  * handled (and need to be handled) if the other
4270                  * attributes in the request bring password_hash into
4271                  * action
4272                  */
4273                 ret = ldb_request_add_control(req, DSDB_CONTROL_PASSWORD_BYPASS_LAST_SET_OID, false, NULL);
4274                 if (ret != LDB_SUCCESS) {
4275                         return ret;
4276                 }
4277         }
4278
4279         if (dsdb_flags & DSDB_MODIFY_PARTIAL_REPLICA) {
4280                 ret = ldb_request_add_control(req, DSDB_CONTROL_PARTIAL_REPLICA, false, NULL);
4281                 if (ret != LDB_SUCCESS) {
4282                         return ret;
4283                 }
4284         }
4285
4286         return LDB_SUCCESS;
4287 }
4288
4289 /*
4290   an add with a set of controls
4291 */
4292 int dsdb_add(struct ldb_context *ldb, const struct ldb_message *message,
4293              uint32_t dsdb_flags)
4294 {
4295         struct ldb_request *req;
4296         int ret;
4297
4298         ret = ldb_build_add_req(&req, ldb, ldb,
4299                                 message,
4300                                 NULL,
4301                                 NULL,
4302                                 ldb_op_default_callback,
4303                                 NULL);
4304
4305         if (ret != LDB_SUCCESS) return ret;
4306
4307         ret = dsdb_request_add_controls(req, dsdb_flags);
4308         if (ret != LDB_SUCCESS) {
4309                 talloc_free(req);
4310                 return ret;
4311         }
4312
4313         ret = dsdb_autotransaction_request(ldb, req);
4314
4315         talloc_free(req);
4316         return ret;
4317 }
4318
4319 /*
4320   a modify with a set of controls
4321 */
4322 int dsdb_modify(struct ldb_context *ldb, const struct ldb_message *message,
4323                 uint32_t dsdb_flags)
4324 {
4325         struct ldb_request *req;
4326         int ret;
4327
4328         ret = ldb_build_mod_req(&req, ldb, ldb,
4329                                 message,
4330                                 NULL,
4331                                 NULL,
4332                                 ldb_op_default_callback,
4333                                 NULL);
4334
4335         if (ret != LDB_SUCCESS) return ret;
4336
4337         ret = dsdb_request_add_controls(req, dsdb_flags);
4338         if (ret != LDB_SUCCESS) {
4339                 talloc_free(req);
4340                 return ret;
4341         }
4342
4343         ret = dsdb_autotransaction_request(ldb, req);
4344
4345         talloc_free(req);
4346         return ret;
4347 }
4348
4349 /*
4350   a delete with a set of flags
4351 */
4352 int dsdb_delete(struct ldb_context *ldb, struct ldb_dn *dn,
4353                 uint32_t dsdb_flags)
4354 {
4355         struct ldb_request *req;
4356         int ret;
4357
4358         ret = ldb_build_del_req(&req, ldb, ldb,
4359                                 dn,
4360                                 NULL,
4361                                 NULL,
4362                                 ldb_op_default_callback,
4363                                 NULL);
4364
4365         if (ret != LDB_SUCCESS) return ret;
4366
4367         ret = dsdb_request_add_controls(req, dsdb_flags);
4368         if (ret != LDB_SUCCESS) {
4369                 talloc_free(req);
4370                 return ret;
4371         }
4372
4373         ret = dsdb_autotransaction_request(ldb, req);
4374
4375         talloc_free(req);
4376         return ret;
4377 }
4378
4379 /*
4380   like dsdb_modify() but set all the element flags to
4381   LDB_FLAG_MOD_REPLACE
4382  */
4383 int dsdb_replace(struct ldb_context *ldb, struct ldb_message *msg, uint32_t dsdb_flags)
4384 {
4385         unsigned int i;
4386
4387         /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
4388         for (i=0;i<msg->num_elements;i++) {
4389                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
4390         }
4391
4392         return dsdb_modify(ldb, msg, dsdb_flags);
4393 }
4394
4395
4396 /*
4397   search for attrs on one DN, allowing for dsdb_flags controls
4398  */
4399 int dsdb_search_dn(struct ldb_context *ldb,
4400                    TALLOC_CTX *mem_ctx,
4401                    struct ldb_result **_result,
4402                    struct ldb_dn *basedn,
4403                    const char * const *attrs,
4404                    uint32_t dsdb_flags)
4405 {
4406         int ret;
4407         struct ldb_request *req;
4408         struct ldb_result *res;
4409
4410         res = talloc_zero(mem_ctx, struct ldb_result);
4411         if (!res) {
4412                 return ldb_oom(ldb);
4413         }
4414
4415         ret = ldb_build_search_req(&req, ldb, res,
4416                                    basedn,
4417                                    LDB_SCOPE_BASE,
4418                                    NULL,
4419                                    attrs,
4420                                    NULL,
4421                                    res,
4422                                    ldb_search_default_callback,
4423                                    NULL);
4424         if (ret != LDB_SUCCESS) {
4425                 talloc_free(res);
4426                 return ret;
4427         }
4428
4429         ret = dsdb_request_add_controls(req, dsdb_flags);
4430         if (ret != LDB_SUCCESS) {
4431                 talloc_free(res);
4432                 return ret;
4433         }
4434
4435         ret = ldb_request(ldb, req);
4436         if (ret == LDB_SUCCESS) {
4437                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4438         }
4439
4440         talloc_free(req);
4441         if (ret != LDB_SUCCESS) {
4442                 talloc_free(res);
4443                 return ret;
4444         }
4445
4446         *_result = res;
4447         return LDB_SUCCESS;
4448 }
4449
4450 /*
4451   search for attrs on one DN, by the GUID of the DN, allowing for
4452   dsdb_flags controls
4453  */
4454 int dsdb_search_by_dn_guid(struct ldb_context *ldb,
4455                            TALLOC_CTX *mem_ctx,
4456                            struct ldb_result **_result,
4457                            const struct GUID *guid,
4458                            const char * const *attrs,
4459                            uint32_t dsdb_flags)
4460 {
4461         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4462         struct ldb_dn *dn;
4463         int ret;
4464
4465         dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<GUID=%s>", GUID_string(tmp_ctx, guid));
4466         if (dn == NULL) {
4467                 talloc_free(tmp_ctx);
4468                 return ldb_oom(ldb);
4469         }
4470
4471         ret = dsdb_search_dn(ldb, mem_ctx, _result, dn, attrs, dsdb_flags);
4472         talloc_free(tmp_ctx);
4473         return ret;
4474 }
4475
4476 /*
4477   general search with dsdb_flags for controls
4478  */
4479 int dsdb_search(struct ldb_context *ldb,
4480                 TALLOC_CTX *mem_ctx,
4481                 struct ldb_result **_result,
4482                 struct ldb_dn *basedn,
4483                 enum ldb_scope scope,
4484                 const char * const *attrs,
4485                 uint32_t dsdb_flags,
4486                 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
4487 {
4488         int ret;
4489         struct ldb_request *req;
4490         struct ldb_result *res;
4491         va_list ap;
4492         char *expression = NULL;
4493         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4494
4495         /* cross-partitions searches with a basedn break multi-domain support */
4496         SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
4497
4498         res = talloc_zero(tmp_ctx, struct ldb_result);
4499         if (!res) {
4500                 talloc_free(tmp_ctx);
4501                 return ldb_oom(ldb);
4502         }
4503
4504         if (exp_fmt) {
4505                 va_start(ap, exp_fmt);
4506                 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
4507                 va_end(ap);
4508
4509                 if (!expression) {
4510                         talloc_free(tmp_ctx);
4511                         return ldb_oom(ldb);
4512                 }
4513         }
4514
4515         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
4516                                    basedn,
4517                                    scope,
4518                                    expression,
4519                                    attrs,
4520                                    NULL,
4521                                    res,
4522                                    ldb_search_default_callback,
4523                                    NULL);
4524         if (ret != LDB_SUCCESS) {
4525                 talloc_free(tmp_ctx);
4526                 return ret;
4527         }
4528
4529         ret = dsdb_request_add_controls(req, dsdb_flags);
4530         if (ret != LDB_SUCCESS) {
4531                 talloc_free(tmp_ctx);
4532                 ldb_reset_err_string(ldb);
4533                 return ret;
4534         }
4535
4536         ret = ldb_request(ldb, req);
4537         if (ret == LDB_SUCCESS) {
4538                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4539         }
4540
4541         if (ret != LDB_SUCCESS) {
4542                 talloc_free(tmp_ctx);
4543                 return ret;
4544         }
4545
4546         if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
4547                 if (res->count == 0) {
4548                         talloc_free(tmp_ctx);
4549                         ldb_reset_err_string(ldb);
4550                         return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, __func__);
4551                 }
4552                 if (res->count != 1) {
4553                         talloc_free(tmp_ctx);
4554                         ldb_reset_err_string(ldb);
4555                         return LDB_ERR_CONSTRAINT_VIOLATION;
4556                 }
4557         }
4558
4559         *_result = talloc_steal(mem_ctx, res);
4560         talloc_free(tmp_ctx);
4561
4562         return LDB_SUCCESS;
4563 }
4564
4565
4566 /*
4567   general search with dsdb_flags for controls
4568   returns exactly 1 record or an error
4569  */
4570 int dsdb_search_one(struct ldb_context *ldb,
4571                     TALLOC_CTX *mem_ctx,
4572                     struct ldb_message **msg,
4573                     struct ldb_dn *basedn,
4574                     enum ldb_scope scope,
4575                     const char * const *attrs,
4576                     uint32_t dsdb_flags,
4577                     const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
4578 {
4579         int ret;
4580         struct ldb_result *res;
4581         va_list ap;
4582         char *expression = NULL;
4583         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4584
4585         dsdb_flags |= DSDB_SEARCH_ONE_ONLY;
4586
4587         res = talloc_zero(tmp_ctx, struct ldb_result);
4588         if (!res) {
4589                 talloc_free(tmp_ctx);
4590                 return ldb_oom(ldb);
4591         }
4592
4593         if (exp_fmt) {
4594                 va_start(ap, exp_fmt);
4595                 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
4596                 va_end(ap);
4597
4598                 if (!expression) {
4599                         talloc_free(tmp_ctx);
4600                         return ldb_oom(ldb);
4601                 }
4602                 ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
4603                                   dsdb_flags, "%s", expression);
4604         } else {
4605                 ret = dsdb_search(ldb, tmp_ctx, &res, basedn, scope, attrs,
4606                                   dsdb_flags, NULL);
4607         }
4608
4609         if (ret != LDB_SUCCESS) {
4610                 talloc_free(tmp_ctx);
4611                 return ret;
4612         }
4613
4614         *msg = talloc_steal(mem_ctx, res->msgs[0]);
4615         talloc_free(tmp_ctx);
4616
4617         return LDB_SUCCESS;
4618 }
4619
4620 /* returns back the forest DNS name */
4621 const char *samdb_forest_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
4622 {
4623         const char *forest_name = ldb_dn_canonical_string(mem_ctx,
4624                                                           ldb_get_root_basedn(ldb));
4625         char *p;
4626
4627         if (forest_name == NULL) {
4628                 return NULL;
4629         }
4630
4631         p = strchr(forest_name, '/');
4632         if (p) {
4633                 *p = '\0';
4634         }
4635
4636         return forest_name;
4637 }
4638
4639 /* returns back the default domain DNS name */
4640 const char *samdb_default_domain_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
4641 {
4642         const char *domain_name = ldb_dn_canonical_string(mem_ctx,
4643                                                           ldb_get_default_basedn(ldb));
4644         char *p;
4645
4646         if (domain_name == NULL) {
4647                 return NULL;
4648         }
4649
4650         p = strchr(domain_name, '/');
4651         if (p) {
4652                 *p = '\0';
4653         }
4654
4655         return domain_name;
4656 }
4657
4658 /*
4659    validate that an DSA GUID belongs to the specified user sid.
4660    The user SID must be a domain controller account (either RODC or
4661    RWDC)
4662  */
4663 int dsdb_validate_dsa_guid(struct ldb_context *ldb,
4664                            const struct GUID *dsa_guid,
4665                            const struct dom_sid *sid)
4666 {
4667         /* strategy:
4668             - find DN of record with the DSA GUID in the
4669               configuration partition (objectGUID)
4670             - remove "NTDS Settings" component from DN
4671             - do a base search on that DN for serverReference with
4672               extended-dn enabled
4673             - extract objectSid from resulting serverReference
4674               attribute
4675             - check this sid matches the sid argument
4676         */
4677         struct ldb_dn *config_dn;
4678         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
4679         struct ldb_message *msg;
4680         const char *attrs1[] = { NULL };
4681         const char *attrs2[] = { "serverReference", NULL };
4682         int ret;
4683         struct ldb_dn *dn, *account_dn;
4684         struct dom_sid sid2;
4685         NTSTATUS status;
4686
4687         config_dn = ldb_get_config_basedn(ldb);
4688
4689         ret = dsdb_search_one(ldb, tmp_ctx, &msg, config_dn, LDB_SCOPE_SUBTREE,
4690                               attrs1, 0, "(&(objectGUID=%s)(objectClass=nTDSDSA))", GUID_string(tmp_ctx, dsa_guid));
4691         if (ret != LDB_SUCCESS) {
4692                 DEBUG(1,(__location__ ": Failed to find DSA objectGUID %s for sid %s\n",
4693                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4694                 talloc_free(tmp_ctx);
4695                 return ldb_operr(ldb);
4696         }
4697         dn = msg->dn;
4698
4699         if (!ldb_dn_remove_child_components(dn, 1)) {
4700                 talloc_free(tmp_ctx);
4701                 return ldb_operr(ldb);
4702         }
4703
4704         ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE,
4705                               attrs2, DSDB_SEARCH_SHOW_EXTENDED_DN,
4706                               "(objectClass=server)");
4707         if (ret != LDB_SUCCESS) {
4708                 DEBUG(1,(__location__ ": Failed to find server record for DSA with objectGUID %s, sid %s\n",
4709                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4710                 talloc_free(tmp_ctx);
4711                 return ldb_operr(ldb);
4712         }
4713
4714         account_dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, msg, "serverReference");
4715         if (account_dn == NULL) {
4716                 DEBUG(1,(__location__ ": Failed to find account dn "
4717                          "(serverReference) for %s, parent of DSA with "
4718                          "objectGUID %s, sid %s\n",
4719                          ldb_dn_get_linearized(msg->dn),
4720                          GUID_string(tmp_ctx, dsa_guid),
4721                          dom_sid_string(tmp_ctx, sid)));
4722                 talloc_free(tmp_ctx);
4723                 return ldb_operr(ldb);
4724         }
4725
4726         status = dsdb_get_extended_dn_sid(account_dn, &sid2, "SID");
4727         if (!NT_STATUS_IS_OK(status)) {
4728                 DEBUG(1,(__location__ ": Failed to find SID for DSA with objectGUID %s, sid %s\n",
4729                          GUID_string(tmp_ctx, dsa_guid), dom_sid_string(tmp_ctx, sid)));
4730                 talloc_free(tmp_ctx);
4731                 return ldb_operr(ldb);
4732         }
4733
4734         if (!dom_sid_equal(sid, &sid2)) {
4735                 /* someone is trying to spoof another account */
4736                 DEBUG(0,(__location__ ": Bad DSA objectGUID %s for sid %s - expected sid %s\n",
4737                          GUID_string(tmp_ctx, dsa_guid),
4738                          dom_sid_string(tmp_ctx, sid),
4739                          dom_sid_string(tmp_ctx, &sid2)));
4740                 talloc_free(tmp_ctx);
4741                 return ldb_operr(ldb);
4742         }
4743
4744         talloc_free(tmp_ctx);
4745         return LDB_SUCCESS;
4746 }
4747
4748 static const char * const secret_attributes[] = {
4749         DSDB_SECRET_ATTRIBUTES,
4750         NULL
4751 };
4752
4753 /*
4754   check if the attribute belongs to the RODC filtered attribute set
4755   Note that attributes that are in the filtered attribute set are the
4756   ones that _are_ always sent to a RODC
4757 */
4758 bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa)
4759 {
4760         /* they never get secret attributes */
4761         if (is_attr_in_list(secret_attributes, sa->lDAPDisplayName)) {
4762                 return false;
4763         }
4764
4765         /* they do get non-secret critical attributes */
4766         if (sa->schemaFlagsEx & SCHEMA_FLAG_ATTR_IS_CRITICAL) {
4767                 return true;
4768         }
4769
4770         /* they do get non-secret attributes marked as being in the FAS  */
4771         if (sa->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) {
4772                 return true;
4773         }
4774
4775         /* other attributes are denied */
4776         return false;
4777 }
4778
4779 /* return fsmo role dn and role owner dn for a particular role*/
4780 WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx,
4781                                struct ldb_context *ldb,
4782                                uint32_t role,
4783                                struct ldb_dn **fsmo_role_dn,
4784                                struct ldb_dn **role_owner_dn)
4785 {
4786         int ret;
4787         switch (role) {
4788         case DREPL_NAMING_MASTER:
4789                 *fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx);
4790                 ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
4791                 if (ret != LDB_SUCCESS) {
4792                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
4793                                  ldb_errstring(ldb)));
4794                         talloc_free(tmp_ctx);
4795                         return WERR_DS_DRA_INTERNAL_ERROR;
4796                 }
4797                 break;
4798         case DREPL_INFRASTRUCTURE_MASTER:
4799                 *fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
4800                 ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
4801                 if (ret != LDB_SUCCESS) {
4802                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
4803                                  ldb_errstring(ldb)));
4804                         talloc_free(tmp_ctx);
4805                         return WERR_DS_DRA_INTERNAL_ERROR;
4806                 }
4807                 break;
4808         case DREPL_RID_MASTER:
4809                 ret = samdb_rid_manager_dn(ldb, tmp_ctx, fsmo_role_dn);
4810                 if (ret != LDB_SUCCESS) {
4811                         DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
4812                         talloc_free(tmp_ctx);
4813                         return WERR_DS_DRA_INTERNAL_ERROR;
4814                 }
4815
4816                 ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
4817                 if (ret != LDB_SUCCESS) {
4818                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
4819                                  ldb_errstring(ldb)));
4820                         talloc_free(tmp_ctx);
4821                         return WERR_DS_DRA_INTERNAL_ERROR;
4822                 }
4823                 break;
4824         case DREPL_SCHEMA_MASTER:
4825                 *fsmo_role_dn = ldb_get_schema_basedn(ldb);
4826                 ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
4827                 if (ret != LDB_SUCCESS) {
4828                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
4829                                  ldb_errstring(ldb)));
4830                         talloc_free(tmp_ctx);
4831                         return WERR_DS_DRA_INTERNAL_ERROR;
4832                 }
4833                 break;
4834         case DREPL_PDC_MASTER:
4835                 *fsmo_role_dn = ldb_get_default_basedn(ldb);
4836                 ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
4837                 if (ret != LDB_SUCCESS) {
4838                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
4839                                  ldb_errstring(ldb)));
4840                         talloc_free(tmp_ctx);
4841                         return WERR_DS_DRA_INTERNAL_ERROR;
4842                 }
4843                 break;
4844         default:
4845                 return WERR_DS_DRA_INTERNAL_ERROR;
4846         }
4847         return WERR_OK;
4848 }
4849
4850 const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
4851                                     TALLOC_CTX *mem_ctx,
4852                                     struct ldb_dn *server_dn)
4853 {
4854         int ldb_ret;
4855         struct ldb_result *res = NULL;
4856         const char * const attrs[] = { "dNSHostName", NULL};
4857
4858         ldb_ret = ldb_search(ldb, mem_ctx, &res,
4859                              server_dn,
4860                              LDB_SCOPE_BASE,
4861                              attrs, NULL);
4862         if (ldb_ret != LDB_SUCCESS) {
4863                 DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s",
4864                           ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
4865                 return NULL;
4866         }
4867
4868         return ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
4869 }
4870
4871 /*
4872   returns true if an attribute is in the filter,
4873   false otherwise, provided that attribute value is provided with the expression
4874 */
4875 bool dsdb_attr_in_parse_tree(struct ldb_parse_tree *tree,
4876                              const char *attr)
4877 {
4878        unsigned int i;
4879        switch (tree->operation) {
4880        case LDB_OP_AND:
4881        case LDB_OP_OR:
4882                for (i=0;i<tree->u.list.num_elements;i++) {
4883                        if (dsdb_attr_in_parse_tree(tree->u.list.elements[i],
4884                                                        attr))
4885                                return true;
4886                }
4887                return false;
4888        case LDB_OP_NOT:
4889                return dsdb_attr_in_parse_tree(tree->u.isnot.child, attr);
4890        case LDB_OP_EQUALITY:
4891        case LDB_OP_GREATER:
4892        case LDB_OP_LESS:
4893        case LDB_OP_APPROX:
4894                if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
4895                        return true;
4896                }
4897                return false;
4898        case LDB_OP_SUBSTRING:
4899                if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
4900                        return true;
4901                }
4902                return false;
4903        case LDB_OP_PRESENT:
4904                /* (attrname=*) is not filtered out */
4905                return false;
4906        case LDB_OP_EXTENDED:
4907                if (tree->u.extended.attr &&
4908                    ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
4909                        return true;
4910                }
4911                return false;
4912        }
4913        return false;
4914 }
4915
4916 bool is_attr_in_list(const char * const * attrs, const char *attr)
4917 {
4918         unsigned int i;
4919
4920         for (i = 0; attrs[i]; i++) {
4921                 if (ldb_attr_cmp(attrs[i], attr) == 0)
4922                         return true;
4923         }
4924
4925         return false;
4926 }
4927
4928 int dsdb_werror_at(struct ldb_context *ldb, int ldb_ecode, WERROR werr,
4929                    const char *location, const char *func,
4930                    const char *reason)
4931 {
4932         if (reason == NULL) {
4933                 reason = win_errstr(werr);
4934         }
4935         ldb_asprintf_errstring(ldb, "%08X: %s at %s:%s",
4936                                W_ERROR_V(werr), reason, location, func);
4937         return ldb_ecode;
4938 }
4939
4940 /*
4941   map an ldb error code to an approximate NTSTATUS code
4942  */
4943 NTSTATUS dsdb_ldb_err_to_ntstatus(int err)
4944 {
4945         switch (err) {
4946         case LDB_SUCCESS:
4947                 return NT_STATUS_OK;
4948
4949         case LDB_ERR_PROTOCOL_ERROR:
4950                 return NT_STATUS_DEVICE_PROTOCOL_ERROR;
4951
4952         case LDB_ERR_TIME_LIMIT_EXCEEDED:
4953                 return NT_STATUS_IO_TIMEOUT;
4954
4955         case LDB_ERR_SIZE_LIMIT_EXCEEDED:
4956                 return NT_STATUS_BUFFER_TOO_SMALL;
4957
4958         case LDB_ERR_COMPARE_FALSE:
4959         case LDB_ERR_COMPARE_TRUE:
4960                 return NT_STATUS_REVISION_MISMATCH;
4961
4962         case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
4963                 return NT_STATUS_NOT_SUPPORTED;
4964
4965         case LDB_ERR_STRONG_AUTH_REQUIRED:
4966         case LDB_ERR_CONFIDENTIALITY_REQUIRED:
4967         case LDB_ERR_SASL_BIND_IN_PROGRESS:
4968         case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
4969         case LDB_ERR_INVALID_CREDENTIALS:
4970         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4971         case LDB_ERR_UNWILLING_TO_PERFORM:
4972                 return NT_STATUS_ACCESS_DENIED;
4973
4974         case LDB_ERR_NO_SUCH_OBJECT:
4975                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4976
4977         case LDB_ERR_REFERRAL:
4978         case LDB_ERR_NO_SUCH_ATTRIBUTE:
4979                 return NT_STATUS_NOT_FOUND;
4980
4981         case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
4982                 return NT_STATUS_NOT_SUPPORTED;
4983
4984         case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
4985                 return NT_STATUS_BUFFER_TOO_SMALL;
4986
4987         case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
4988         case LDB_ERR_INAPPROPRIATE_MATCHING:
4989         case LDB_ERR_CONSTRAINT_VIOLATION:
4990         case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
4991         case LDB_ERR_INVALID_DN_SYNTAX:
4992         case LDB_ERR_NAMING_VIOLATION:
4993         case LDB_ERR_OBJECT_CLASS_VIOLATION:
4994         case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
4995         case LDB_ERR_NOT_ALLOWED_ON_RDN:
4996                 return NT_STATUS_INVALID_PARAMETER;
4997
4998         case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
4999         case LDB_ERR_ENTRY_ALREADY_EXISTS:
5000                 return NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS;
5001
5002         case LDB_ERR_BUSY:
5003                 return NT_STATUS_NETWORK_BUSY;
5004
5005         case LDB_ERR_ALIAS_PROBLEM:
5006         case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
5007         case LDB_ERR_UNAVAILABLE:
5008         case LDB_ERR_LOOP_DETECT:
5009         case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
5010         case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
5011         case LDB_ERR_OTHER:
5012         case LDB_ERR_OPERATIONS_ERROR:
5013                 break;
5014         }
5015         return NT_STATUS_UNSUCCESSFUL;
5016 }
5017
5018
5019 /*
5020   create a new naming context that will hold a partial replica
5021  */
5022 int dsdb_create_partial_replica_NC(struct ldb_context *ldb,  struct ldb_dn *dn)
5023 {
5024         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
5025         struct ldb_message *msg;
5026         int ret;
5027
5028         msg = ldb_msg_new(tmp_ctx);
5029         if (msg == NULL) {
5030                 talloc_free(tmp_ctx);
5031                 return ldb_oom(ldb);
5032         }
5033
5034         msg->dn = dn;
5035         ret = ldb_msg_add_string(msg, "objectClass", "top");
5036         if (ret != LDB_SUCCESS) {
5037                 talloc_free(tmp_ctx);
5038                 return ldb_oom(ldb);
5039         }
5040
5041         /* [MS-DRSR] implies that we should only add the 'top'
5042          * objectclass, but that would cause lots of problems with our
5043          * objectclass code as top is not structural, so we add
5044          * 'domainDNS' as well to keep things sane. We're expecting
5045          * this new NC to be of objectclass domainDNS after
5046          * replication anyway
5047          */
5048         ret = ldb_msg_add_string(msg, "objectClass", "domainDNS");
5049         if (ret != LDB_SUCCESS) {
5050                 talloc_free(tmp_ctx);
5051                 return ldb_oom(ldb);
5052         }
5053
5054         ret = ldb_msg_add_fmt(msg, "instanceType", "%u",
5055                               INSTANCE_TYPE_IS_NC_HEAD|
5056                               INSTANCE_TYPE_NC_ABOVE|
5057                               INSTANCE_TYPE_UNINSTANT);
5058         if (ret != LDB_SUCCESS) {
5059                 talloc_free(tmp_ctx);
5060                 return ldb_oom(ldb);
5061         }
5062
5063         ret = dsdb_add(ldb, msg, DSDB_MODIFY_PARTIAL_REPLICA);
5064         if (ret != LDB_SUCCESS && ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
5065                 DEBUG(0,("Failed to create new NC for %s - %s (%s)\n",
5066                          ldb_dn_get_linearized(dn),
5067                          ldb_errstring(ldb), ldb_strerror(ret)));
5068                 talloc_free(tmp_ctx);
5069                 return ret;
5070         }
5071
5072         DEBUG(1,("Created new NC for %s\n", ldb_dn_get_linearized(dn)));
5073
5074         talloc_free(tmp_ctx);
5075         return LDB_SUCCESS;
5076 }
5077
5078 /**
5079   build a GUID from a string
5080 */
5081 _PUBLIC_ NTSTATUS NS_GUID_from_string(const char *s, struct GUID *guid)
5082 {
5083         NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
5084         uint32_t time_low;
5085         uint32_t time_mid, time_hi_and_version;
5086         uint32_t clock_seq[2];
5087         uint32_t node[6];
5088         int i;
5089
5090         if (s == NULL) {
5091                 return NT_STATUS_INVALID_PARAMETER;
5092         }
5093
5094         if (11 == sscanf(s, "%08x-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02x",
5095                          &time_low, &time_mid, &time_hi_and_version, 
5096                          &clock_seq[0], &clock_seq[1],
5097                          &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
5098                 status = NT_STATUS_OK;
5099         }
5100
5101         if (!NT_STATUS_IS_OK(status)) {
5102                 return status;
5103         }
5104
5105         guid->time_low = time_low;
5106         guid->time_mid = time_mid;
5107         guid->time_hi_and_version = time_hi_and_version;
5108         guid->clock_seq[0] = clock_seq[0];
5109         guid->clock_seq[1] = clock_seq[1];
5110         for (i=0;i<6;i++) {
5111                 guid->node[i] = node[i];
5112         }
5113
5114         return NT_STATUS_OK;
5115 }
5116
5117 _PUBLIC_ char *NS_GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
5118 {
5119         return talloc_asprintf(mem_ctx, 
5120                                "%08x-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02x",
5121                                guid->time_low, guid->time_mid,
5122                                guid->time_hi_and_version,
5123                                guid->clock_seq[0],
5124                                guid->clock_seq[1],
5125                                guid->node[0], guid->node[1],
5126                                guid->node[2], guid->node[3],
5127                                guid->node[4], guid->node[5]);
5128 }
5129
5130 /*
5131  * Return the effective badPwdCount
5132  *
5133  * This requires that the user_msg have (if present):
5134  *  - badPasswordTime
5135  *  - badPwdCount
5136  *
5137  * This also requires that the domain_msg have (if present):
5138  *  - lockOutObservationWindow
5139  */
5140 static int dsdb_effective_badPwdCount(const struct ldb_message *user_msg,
5141                                       int64_t lockOutObservationWindow,
5142                                       NTTIME now)
5143 {
5144         int64_t badPasswordTime;
5145         badPasswordTime = ldb_msg_find_attr_as_int64(user_msg, "badPasswordTime", 0);
5146
5147         if (badPasswordTime - lockOutObservationWindow >= now) {
5148                 return ldb_msg_find_attr_as_int(user_msg, "badPwdCount", 0);
5149         } else {
5150                 return 0;
5151         }
5152 }
5153
5154 /*
5155  * Return the effective badPwdCount
5156  *
5157  * This requires that the user_msg have (if present):
5158  *  - badPasswordTime
5159  *  - badPwdCount
5160  *
5161  */
5162 int samdb_result_effective_badPwdCount(struct ldb_context *sam_ldb,
5163                                        TALLOC_CTX *mem_ctx,
5164                                        struct ldb_dn *domain_dn,
5165                                        const struct ldb_message *user_msg)
5166 {
5167         struct timeval tv_now = timeval_current();
5168         NTTIME now = timeval_to_nttime(&tv_now);
5169         int64_t lockOutObservationWindow = samdb_search_int64(sam_ldb, mem_ctx, 0, domain_dn,
5170                                                               "lockOutObservationWindow", NULL);
5171         return dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
5172 }
5173
5174 /*
5175  * Prepare an update to the badPwdCount and associated attributes.
5176  *
5177  * This requires that the user_msg have (if present):
5178  *  - objectSid
5179  *  - badPasswordTime
5180  *  - badPwdCount
5181  *
5182  * This also requires that the domain_msg have (if present):
5183  *  - pwdProperties
5184  *  - lockoutThreshold
5185  *  - lockOutObservationWindow
5186  */
5187 NTSTATUS dsdb_update_bad_pwd_count(TALLOC_CTX *mem_ctx,
5188                                    struct ldb_context *sam_ctx,
5189                                    struct ldb_message *user_msg,
5190                                    struct ldb_message *domain_msg,
5191                                    struct ldb_message **_mod_msg)
5192 {
5193         int i, ret, badPwdCount;
5194         int64_t lockoutThreshold, lockOutObservationWindow;
5195         struct dom_sid *sid;
5196         struct timeval tv_now = timeval_current();
5197         NTTIME now = timeval_to_nttime(&tv_now);
5198         NTSTATUS status;
5199         uint32_t pwdProperties, rid = 0;
5200         struct ldb_message *mod_msg;
5201
5202         sid = samdb_result_dom_sid(mem_ctx, user_msg, "objectSid");
5203
5204         pwdProperties = ldb_msg_find_attr_as_uint(domain_msg,
5205                                                   "pwdProperties", -1);
5206         if (sid && !(pwdProperties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
5207                 status = dom_sid_split_rid(NULL, sid, NULL, &rid);
5208                 if (!NT_STATUS_IS_OK(status)) {
5209                         /*
5210                          * This can't happen anyway, but always try
5211                          * and update the badPwdCount on failure
5212                          */
5213                         rid = 0;
5214                 }
5215         }
5216         TALLOC_FREE(sid);
5217
5218         /*
5219          * Work out if we are doing password lockout on the domain.
5220          * Also, the built in administrator account is exempt:
5221          * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375371%28v=vs.85%29.aspx
5222          */
5223         lockoutThreshold = ldb_msg_find_attr_as_int(domain_msg,
5224                                                     "lockoutThreshold", 0);
5225         if (lockoutThreshold == 0 || (rid == DOMAIN_RID_ADMINISTRATOR)) {
5226                 DEBUG(5, ("Not updating badPwdCount on %s after wrong password\n",
5227                           ldb_dn_get_linearized(user_msg->dn)));
5228                 return NT_STATUS_OK;
5229         }
5230
5231         mod_msg = ldb_msg_new(mem_ctx);
5232         if (mod_msg == NULL) {
5233                 return NT_STATUS_NO_MEMORY;
5234         }
5235         mod_msg->dn = ldb_dn_copy(mod_msg, user_msg->dn);
5236         if (mod_msg->dn == NULL) {
5237                 TALLOC_FREE(mod_msg);
5238                 return NT_STATUS_NO_MEMORY;
5239         }
5240
5241         lockOutObservationWindow = ldb_msg_find_attr_as_int64(domain_msg,
5242                                                               "lockOutObservationWindow", 0);
5243
5244         badPwdCount = dsdb_effective_badPwdCount(user_msg, lockOutObservationWindow, now);
5245
5246         badPwdCount++;
5247
5248         ret = samdb_msg_add_int(sam_ctx, mod_msg, mod_msg, "badPwdCount", badPwdCount);
5249         if (ret != LDB_SUCCESS) {
5250                 TALLOC_FREE(mod_msg);
5251                 return NT_STATUS_NO_MEMORY;
5252         }
5253         ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "badPasswordTime", now);
5254         if (ret != LDB_SUCCESS) {
5255                 TALLOC_FREE(mod_msg);
5256                 return NT_STATUS_NO_MEMORY;
5257         }
5258
5259         if (badPwdCount >= lockoutThreshold) {
5260                 ret = samdb_msg_add_int64(sam_ctx, mod_msg, mod_msg, "lockoutTime", now);
5261                 if (ret != LDB_SUCCESS) {
5262                         TALLOC_FREE(mod_msg);
5263                         return NT_STATUS_NO_MEMORY;
5264                 }
5265                 DEBUG(5, ("Locked out user %s after %d wrong passwords\n",
5266                           ldb_dn_get_linearized(user_msg->dn), badPwdCount));
5267         } else {
5268                 DEBUG(5, ("Updated badPwdCount on %s after %d wrong passwords\n",
5269                           ldb_dn_get_linearized(user_msg->dn), badPwdCount));
5270         }
5271
5272         /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
5273         for (i=0; i< mod_msg->num_elements; i++) {
5274                 mod_msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
5275         }
5276
5277         *_mod_msg = mod_msg;
5278         return NT_STATUS_OK;
5279 }
5280
5281 /**
5282  * Sets defaults for a User object
5283  * List of default attributes set:
5284  *      accountExpires, badPasswordTime, badPwdCount,
5285  *      codePage, countryCode, lastLogoff, lastLogon
5286  *      logonCount, pwdLastSet
5287  */
5288 int dsdb_user_obj_set_defaults(struct ldb_context *ldb,
5289                                struct ldb_message *usr_obj,
5290                                struct ldb_request *req)
5291 {
5292         int i, ret;
5293         const struct attribute_values {
5294                 const char *name;
5295                 const char *value;
5296                 const char *add_control;
5297         } map[] = {
5298                 {
5299                         .name = "accountExpires",
5300                         .value = "9223372036854775807"
5301                 },
5302                 {
5303                         .name = "badPasswordTime",
5304                         .value = "0"
5305                 },
5306                 {
5307                         .name = "badPwdCount",
5308                         .value = "0"
5309                 },
5310                 {
5311                         .name = "codePage",
5312                         .value = "0"
5313                 },
5314                 {
5315                         .name = "countryCode",
5316                         .value = "0"
5317                 },
5318                 {
5319                         .name = "lastLogoff",
5320                         .value = "0"
5321                 },
5322                 {
5323                         .name = "lastLogon",
5324                         .value = "0"
5325                 },
5326                 {
5327                         .name = "logonCount",
5328                         .value = "0"
5329                 },
5330                 {
5331                         .name = "pwdLastSet",
5332                         .value = "0",
5333                         .add_control = DSDB_CONTROL_PASSWORD_DEFAULT_LAST_SET_OID,
5334                 }
5335         };
5336
5337         for (i = 0; i < ARRAY_SIZE(map); i++) {
5338                 bool added = false;
5339
5340                 ret = samdb_find_or_add_attribute_ex(ldb, usr_obj,
5341                                                      map[i].name,
5342                                                      map[i].value,
5343                                                      &added);
5344                 if (ret != LDB_SUCCESS) {
5345                         return ret;
5346                 }
5347
5348                 if (req != NULL && added && map[i].add_control != NULL) {
5349                         ret = ldb_request_add_control(req,
5350                                                       map[i].add_control,
5351                                                       false, NULL);
5352                         if (ret != LDB_SUCCESS) {
5353                                 return ret;
5354                         }
5355                 }
5356         }
5357
5358         return LDB_SUCCESS;
5359 }
5360
5361 /**
5362  * Sets 'sAMAccountType on user object based on userAccountControl
5363  * @param ldb Current ldb_context
5364  * @param usr_obj ldb_message representing User object
5365  * @param user_account_control Value for userAccountControl flags
5366  * @param account_type_p Optional pointer to account_type to return
5367  * @return LDB_SUCCESS or LDB_ERR* code on failure
5368  */
5369 int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message *usr_obj,
5370                                    uint32_t user_account_control, uint32_t *account_type_p)
5371 {
5372         int ret;
5373         uint32_t account_type;
5374         struct ldb_message_element *el;
5375
5376         account_type = ds_uf2atype(user_account_control);
5377         if (account_type == 0) {
5378                 ldb_set_errstring(ldb, "dsdb: Unrecognized account type!");
5379                 return LDB_ERR_UNWILLING_TO_PERFORM;
5380         }
5381         ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
5382                                  "sAMAccountType",
5383                                  account_type);
5384         if (ret != LDB_SUCCESS) {
5385                 return ret;
5386         }
5387         el = ldb_msg_find_element(usr_obj, "sAMAccountType");
5388         el->flags = LDB_FLAG_MOD_REPLACE;
5389
5390         if (account_type_p) {
5391                 *account_type_p = account_type;
5392         }
5393
5394         return LDB_SUCCESS;
5395 }
5396
5397 /**
5398  * Determine and set primaryGroupID based on userAccountControl value
5399  * @param ldb Current ldb_context
5400  * @param usr_obj ldb_message representing User object
5401  * @param user_account_control Value for userAccountControl flags
5402  * @param group_rid_p Optional pointer to group RID to return
5403  * @return LDB_SUCCESS or LDB_ERR* code on failure
5404  */
5405 int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_message *usr_obj,
5406                                        uint32_t user_account_control, uint32_t *group_rid_p)
5407 {
5408         int ret;
5409         uint32_t rid;
5410         struct ldb_message_element *el;
5411
5412         rid = ds_uf2prim_group_rid(user_account_control);
5413
5414         ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
5415                                  "primaryGroupID", rid);
5416         if (ret != LDB_SUCCESS) {
5417                 return ret;
5418         }
5419         el = ldb_msg_find_element(usr_obj, "primaryGroupID");
5420         el->flags = LDB_FLAG_MOD_REPLACE;
5421
5422         if (group_rid_p) {
5423                 *group_rid_p = rid;
5424         }
5425
5426         return LDB_SUCCESS;
5427 }