s4-auth Rework auth subsystem to remove struct auth_serversupplied_info
[nivanova/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "kdc/kdc-policy.h"
35
36 /*
37   this type allows us to distinguish handle types
38 */
39
40 /*
41   state associated with a lsa_OpenAccount() operation
42 */
43 struct lsa_account_state {
44         struct lsa_policy_state *policy;
45         uint32_t access_mask;
46         struct dom_sid *account_sid;
47 };
48
49
50 /*
51   state associated with a lsa_OpenSecret() operation
52 */
53 struct lsa_secret_state {
54         struct lsa_policy_state *policy;
55         uint32_t access_mask;
56         struct ldb_dn *secret_dn;
57         struct ldb_context *sam_ldb;
58         bool global;
59 };
60
61 /*
62   state associated with a lsa_OpenTrustedDomain() operation
63 */
64 struct lsa_trusted_domain_state {
65         struct lsa_policy_state *policy;
66         uint32_t access_mask;
67         struct ldb_dn *trusted_domain_dn;
68         struct ldb_dn *trusted_domain_user_dn;
69 };
70
71 /*
72   this is based on the samba3 function make_lsa_object_sd()
73   It uses the same logic, but with samba4 helper functions
74  */
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx, 
76                                     struct security_descriptor **sd,
77                                     struct dom_sid *sid, 
78                                     uint32_t sid_access)
79 {
80         NTSTATUS status;
81         uint32_t rid;
82         struct dom_sid *domain_sid, *domain_admins_sid;
83         const char *domain_admins_sid_str, *sidstr;
84         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
85
86         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
88
89         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
91
92         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
93         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
94         
95         sidstr = dom_sid_string(tmp_ctx, sid);
96         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
97                                                       
98         *sd = security_descriptor_dacl_create(mem_ctx,
99                                               0, sidstr, NULL,
100
101                                               SID_WORLD,
102                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
103                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
104                                               
105                                               SID_BUILTIN_ADMINISTRATORS,
106                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
107                                               SEC_GENERIC_ALL, 0,
108                                               
109                                               SID_BUILTIN_ACCOUNT_OPERATORS,
110                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
111                                               SEC_GENERIC_ALL, 0,
112                                               
113                                               domain_admins_sid_str,
114                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
115                                               SEC_GENERIC_ALL, 0,
116
117                                               sidstr,
118                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
119                                               sid_access, 0,
120
121                                               NULL);
122         talloc_free(tmp_ctx);
123
124         NT_STATUS_HAVE_NO_MEMORY(*sd);
125
126         return NT_STATUS_OK;
127 }
128
129
130 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
131                                       TALLOC_CTX *mem_ctx,
132                                       struct lsa_EnumAccountRights *r);
133
134 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
135                                            TALLOC_CTX *mem_ctx,
136                                            struct lsa_policy_state *state,
137                                            int ldb_flag,
138                                            struct dom_sid *sid,
139                                            const struct lsa_RightSet *rights);
140
141 /* 
142   lsa_Close 
143 */
144 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145                           struct lsa_Close *r)
146 {
147         struct dcesrv_handle *h;
148
149         *r->out.handle = *r->in.handle;
150
151         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
152
153         talloc_free(h);
154
155         ZERO_STRUCTP(r->out.handle);
156
157         return NT_STATUS_OK;
158 }
159
160
161 /* 
162   lsa_Delete 
163 */
164 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
165                            struct lsa_Delete *r)
166 {
167         return NT_STATUS_NOT_SUPPORTED;
168 }
169
170
171 /* 
172   lsa_DeleteObject
173 */
174 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
175                        struct lsa_DeleteObject *r)
176 {
177         struct dcesrv_handle *h;
178         int ret;
179
180         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
181
182         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
183                 struct lsa_secret_state *secret_state = h->data;
184
185                 /* Ensure user is permitted to delete this... */
186                 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
187                 {
188                 case SECURITY_SYSTEM:
189                 case SECURITY_ADMINISTRATOR:
190                         break;
191                 default:
192                         /* Users and anonymous are not allowed to delete things */
193                         return NT_STATUS_ACCESS_DENIED;
194                 }
195
196                 ret = ldb_delete(secret_state->sam_ldb, 
197                                  secret_state->secret_dn);
198                 if (ret != LDB_SUCCESS) {
199                         return NT_STATUS_INVALID_HANDLE;
200                 }
201
202                 ZERO_STRUCTP(r->out.handle);
203
204                 return NT_STATUS_OK;
205
206         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
207                 struct lsa_trusted_domain_state *trusted_domain_state = 
208                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
209                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
210                 if (ret != LDB_SUCCESS) {
211                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
212                 }
213
214                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
215                                  trusted_domain_state->trusted_domain_dn);
216                 if (ret != LDB_SUCCESS) {
217                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
218                         return NT_STATUS_INVALID_HANDLE;
219                 }
220
221                 if (trusted_domain_state->trusted_domain_user_dn) {
222                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
223                                          trusted_domain_state->trusted_domain_user_dn);
224                         if (ret != LDB_SUCCESS) {
225                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
226                                 return NT_STATUS_INVALID_HANDLE;
227                         }
228                 }
229
230                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
231                 if (ret != LDB_SUCCESS) {
232                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
233                 }
234
235                 ZERO_STRUCTP(r->out.handle);
236
237                 return NT_STATUS_OK;
238
239         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
240                 struct lsa_RightSet *rights;
241                 struct lsa_account_state *astate;
242                 struct lsa_EnumAccountRights r2;
243                 NTSTATUS status;
244
245                 rights = talloc(mem_ctx, struct lsa_RightSet);
246
247                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
248                 
249                 astate = h->data;
250
251                 r2.in.handle = &astate->policy->handle->wire_handle;
252                 r2.in.sid = astate->account_sid;
253                 r2.out.rights = rights;
254
255                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
256                    but we have a LSA_HANDLE_ACCOUNT here, so this call
257                    will always fail */
258                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
259                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
260                         return NT_STATUS_OK;
261                 }
262
263                 if (!NT_STATUS_IS_OK(status)) {
264                         return status;
265                 }
266
267                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
268                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
269                                                     r2.out.rights);
270                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
271                         return NT_STATUS_OK;
272                 }
273
274                 if (!NT_STATUS_IS_OK(status)) {
275                         return status;
276                 }
277
278                 ZERO_STRUCTP(r->out.handle);
279
280                 return NT_STATUS_OK;
281         } 
282         
283         return NT_STATUS_INVALID_HANDLE;
284 }
285
286
287 /* 
288   lsa_EnumPrivs 
289 */
290 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291                               struct lsa_EnumPrivs *r)
292 {
293         struct dcesrv_handle *h;
294         struct lsa_policy_state *state;
295         uint32_t i;
296         enum sec_privilege priv;
297         const char *privname;
298
299         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
300
301         state = h->data;
302
303         i = *r->in.resume_handle;
304
305         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
306                r->out.privs->count < r->in.max_count) {
307                 struct lsa_PrivEntry *e;
308                 privname = sec_privilege_name(priv);
309                 r->out.privs->privs = talloc_realloc(r->out.privs,
310                                                        r->out.privs->privs, 
311                                                        struct lsa_PrivEntry, 
312                                                        r->out.privs->count+1);
313                 if (r->out.privs->privs == NULL) {
314                         return NT_STATUS_NO_MEMORY;
315                 }
316                 e = &r->out.privs->privs[r->out.privs->count];
317                 e->luid.low = priv;
318                 e->luid.high = 0;
319                 e->name.string = privname;
320                 r->out.privs->count++;
321                 i++;
322         }
323
324         *r->out.resume_handle = i;
325
326         return NT_STATUS_OK;
327 }
328
329
330 /* 
331   lsa_QuerySecObj 
332 */
333 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
334                                          struct lsa_QuerySecurity *r)
335 {
336         struct dcesrv_handle *h;
337         struct security_descriptor *sd;
338         NTSTATUS status;
339         struct dom_sid *sid;
340
341         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
342
343         sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
344
345         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
346                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
347         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
348                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 
349                                              LSA_ACCOUNT_ALL_ACCESS);
350         } else {
351                 return NT_STATUS_INVALID_HANDLE;
352         }
353         NT_STATUS_NOT_OK_RETURN(status);
354
355         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
356         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
357
358         (*r->out.sdbuf)->sd = sd;
359         
360         return NT_STATUS_OK;
361 }
362
363
364 /* 
365   lsa_SetSecObj 
366 */
367 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
368                               struct lsa_SetSecObj *r)
369 {
370         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
371 }
372
373
374 /* 
375   lsa_ChangePassword 
376 */
377 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
378                                    struct lsa_ChangePassword *r)
379 {
380         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
381 }
382
383 /* 
384   dssetup_DsRoleGetPrimaryDomainInformation 
385
386   This is not an LSA call, but is the only call left on the DSSETUP
387   pipe (after the pipe was truncated), and needs lsa_get_policy_state
388 */
389 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
390                                                  TALLOC_CTX *mem_ctx,
391                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
392 {
393         union dssetup_DsRoleInfo *info;
394
395         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
396         W_ERROR_HAVE_NO_MEMORY(info);
397
398         switch (r->in.level) {
399         case DS_ROLE_BASIC_INFORMATION:
400         {
401                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
402                 uint32_t flags = 0;
403                 const char *domain = NULL;
404                 const char *dns_domain = NULL;
405                 const char *forest = NULL;
406                 struct GUID domain_guid;
407                 struct lsa_policy_state *state;
408
409                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
410                 if (!NT_STATUS_IS_OK(status)) {
411                         return ntstatus_to_werror(status);
412                 }
413
414                 ZERO_STRUCT(domain_guid);
415
416                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
417                 case ROLE_STANDALONE:
418                         role            = DS_ROLE_STANDALONE_SERVER;
419                         break;
420                 case ROLE_DOMAIN_MEMBER:
421                         role            = DS_ROLE_MEMBER_SERVER;
422                         break;
423                 case ROLE_DOMAIN_CONTROLLER:
424                         if (samdb_is_pdc(state->sam_ldb)) {
425                                 role    = DS_ROLE_PRIMARY_DC;
426                         } else {
427                                 role    = DS_ROLE_BACKUP_DC;
428                         }
429                         break;
430                 }
431
432                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
433                 case ROLE_STANDALONE:
434                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
435                         W_ERROR_HAVE_NO_MEMORY(domain);
436                         break;
437                 case ROLE_DOMAIN_MEMBER:
438                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
439                         W_ERROR_HAVE_NO_MEMORY(domain);
440                         /* TODO: what is with dns_domain and forest and guid? */
441                         break;
442                 case ROLE_DOMAIN_CONTROLLER:
443                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
444
445                         if (state->mixed_domain == 1) {
446                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
447                         }
448                         
449                         domain          = state->domain_name;
450                         dns_domain      = state->domain_dns;
451                         forest          = state->forest_dns;
452
453                         domain_guid     = state->domain_guid;
454                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
455                         break;
456                 }
457
458                 info->basic.role        = role; 
459                 info->basic.flags       = flags;
460                 info->basic.domain      = domain;
461                 info->basic.dns_domain  = dns_domain;
462                 info->basic.forest      = forest;
463                 info->basic.domain_guid = domain_guid;
464
465                 r->out.info = info;
466                 return WERR_OK;
467         }
468         case DS_ROLE_UPGRADE_STATUS:
469         {
470                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
471                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
472
473                 r->out.info = info;
474                 return WERR_OK;
475         }
476         case DS_ROLE_OP_STATUS:
477         {
478                 info->opstatus.status = DS_ROLE_OP_IDLE;
479
480                 r->out.info = info;
481                 return WERR_OK;
482         }
483         default:
484                 return WERR_INVALID_PARAM;
485         }
486 }
487
488 /*
489   fill in the AccountDomain info
490 */
491 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
492                                        struct lsa_DomainInfo *info)
493 {
494         info->name.string = state->domain_name;
495         info->sid         = state->domain_sid;
496
497         return NT_STATUS_OK;
498 }
499
500 /*
501   fill in the DNS domain info
502 */
503 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
504                              struct lsa_DnsDomainInfo *info)
505 {
506         info->name.string = state->domain_name;
507         info->sid         = state->domain_sid;
508         info->dns_domain.string = state->domain_dns;
509         info->dns_forest.string = state->forest_dns;
510         info->domain_guid       = state->domain_guid;
511
512         return NT_STATUS_OK;
513 }
514
515 /* 
516   lsa_QueryInfoPolicy2
517 */
518 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
519                                      struct lsa_QueryInfoPolicy2 *r)
520 {
521         struct lsa_policy_state *state;
522         struct dcesrv_handle *h;
523         union lsa_PolicyInformation *info;
524
525         *r->out.info = NULL;
526
527         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
528
529         state = h->data;
530
531         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
532         if (!info) {
533                 return NT_STATUS_NO_MEMORY;
534         }
535         *r->out.info = info;
536
537         switch (r->in.level) {
538         case LSA_POLICY_INFO_AUDIT_LOG:
539                 /* we don't need to fill in any of this */
540                 ZERO_STRUCT(info->audit_log);
541                 return NT_STATUS_OK;
542         case LSA_POLICY_INFO_AUDIT_EVENTS:
543                 /* we don't need to fill in any of this */
544                 ZERO_STRUCT(info->audit_events);
545                 return NT_STATUS_OK;
546         case LSA_POLICY_INFO_PD:
547                 /* we don't need to fill in any of this */
548                 ZERO_STRUCT(info->pd);
549                 return NT_STATUS_OK;
550
551         case LSA_POLICY_INFO_DOMAIN:
552                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
553         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
554                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
555         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
556                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
557
558         case LSA_POLICY_INFO_ROLE:
559                 info->role.role = LSA_ROLE_PRIMARY;
560                 return NT_STATUS_OK;
561
562         case LSA_POLICY_INFO_DNS:
563         case LSA_POLICY_INFO_DNS_INT:
564                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
565
566         case LSA_POLICY_INFO_REPLICA:
567                 ZERO_STRUCT(info->replica);
568                 return NT_STATUS_OK;
569
570         case LSA_POLICY_INFO_QUOTA:
571                 ZERO_STRUCT(info->quota);
572                 return NT_STATUS_OK;
573
574         case LSA_POLICY_INFO_MOD:
575         case LSA_POLICY_INFO_AUDIT_FULL_SET:
576         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
577                 /* windows gives INVALID_PARAMETER */
578                 *r->out.info = NULL;
579                 return NT_STATUS_INVALID_PARAMETER;
580         }
581
582         *r->out.info = NULL;
583         return NT_STATUS_INVALID_INFO_CLASS;
584 }
585
586 /* 
587   lsa_QueryInfoPolicy 
588 */
589 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590                                     struct lsa_QueryInfoPolicy *r)
591 {
592         struct lsa_QueryInfoPolicy2 r2;
593         NTSTATUS status;
594
595         ZERO_STRUCT(r2);
596
597         r2.in.handle = r->in.handle;
598         r2.in.level = r->in.level;
599         r2.out.info = r->out.info;
600         
601         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
602
603         return status;
604 }
605
606 /* 
607   lsa_SetInfoPolicy 
608 */
609 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
610                                   struct lsa_SetInfoPolicy *r)
611 {
612         /* need to support this */
613         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
614 }
615
616
617 /* 
618   lsa_ClearAuditLog 
619 */
620 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621                                   struct lsa_ClearAuditLog *r)
622 {
623         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
624 }
625
626
627 /* 
628   lsa_CreateAccount 
629
630   This call does not seem to have any long-term effects, hence no database operations
631
632   we need to talk to the MS product group to find out what this account database means!
633
634   answer is that the lsa database is totally separate from the SAM and
635   ldap databases. We are going to need a separate ldb to store these
636   accounts. The SIDs on this account bear no relation to the SIDs in
637   AD
638 */
639 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
640                                   struct lsa_CreateAccount *r)
641 {
642         struct lsa_account_state *astate;
643
644         struct lsa_policy_state *state;
645         struct dcesrv_handle *h, *ah;
646
647         ZERO_STRUCTP(r->out.acct_handle);
648
649         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
650
651         state = h->data;
652
653         astate = talloc(dce_call->conn, struct lsa_account_state);
654         if (astate == NULL) {
655                 return NT_STATUS_NO_MEMORY;
656         }
657
658         astate->account_sid = dom_sid_dup(astate, r->in.sid);
659         if (astate->account_sid == NULL) {
660                 talloc_free(astate);
661                 return NT_STATUS_NO_MEMORY;
662         }
663         
664         astate->policy = talloc_reference(astate, state);
665         astate->access_mask = r->in.access_mask;
666
667         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
668         if (!ah) {
669                 talloc_free(astate);
670                 return NT_STATUS_NO_MEMORY;
671         }
672
673         ah->data = talloc_steal(ah, astate);
674
675         *r->out.acct_handle = ah->wire_handle;
676
677         return NT_STATUS_OK;
678 }
679
680
681 /* 
682   lsa_EnumAccounts 
683 */
684 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685                                  struct lsa_EnumAccounts *r)
686 {
687         struct dcesrv_handle *h;
688         struct lsa_policy_state *state;
689         int ret;
690         struct ldb_message **res;
691         const char * const attrs[] = { "objectSid", NULL};
692         uint32_t count, i;
693
694         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
695
696         state = h->data;
697
698         /* NOTE: This call must only return accounts that have at least
699            one privilege set 
700         */
701         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
702                            "(&(objectSid=*)(privilege=*))");
703         if (ret < 0) {
704                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
705         }
706
707         if (*r->in.resume_handle >= ret) {
708                 return NT_STATUS_NO_MORE_ENTRIES;
709         }
710
711         count = ret - *r->in.resume_handle;
712         if (count > r->in.num_entries) {
713                 count = r->in.num_entries;
714         }
715
716         if (count == 0) {
717                 return NT_STATUS_NO_MORE_ENTRIES;
718         }
719
720         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
721         if (r->out.sids->sids == NULL) {
722                 return NT_STATUS_NO_MEMORY;
723         }
724
725         for (i=0;i<count;i++) {
726                 r->out.sids->sids[i].sid = 
727                         samdb_result_dom_sid(r->out.sids->sids, 
728                                              res[i + *r->in.resume_handle],
729                                              "objectSid");
730                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
731         }
732
733         r->out.sids->num_sids = count;
734         *r->out.resume_handle = count + *r->in.resume_handle;
735
736         return NT_STATUS_OK;
737         
738 }
739
740 /* This decrypts and returns Trusted Domain Auth Information Internal data */
741 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
742                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
743                                        struct trustDomainPasswords *auth_struct)
744 {
745         DATA_BLOB session_key = data_blob(NULL, 0);
746         enum ndr_err_code ndr_err;
747         NTSTATUS nt_status;
748
749         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
750         if (!NT_STATUS_IS_OK(nt_status)) {
751                 return nt_status;
752         }
753
754         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
755         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
756                                        auth_struct,
757                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
758         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
759                 return NT_STATUS_INVALID_PARAMETER;
760         }
761
762         return NT_STATUS_OK;
763 }
764
765 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
766                                          TALLOC_CTX *mem_ctx,
767                                          struct trustAuthInOutBlob *iopw,
768                                          DATA_BLOB *trustauth_blob)
769 {
770         enum ndr_err_code ndr_err;
771
772         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
773                                        iopw,
774                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
775         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
776                 return NT_STATUS_INVALID_PARAMETER;
777         }
778
779         return NT_STATUS_OK;
780 }
781
782 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
783                                struct ldb_context *sam_ldb,
784                                struct ldb_dn *base_dn,
785                                const char *netbios_name,
786                                struct trustAuthInOutBlob *in,
787                                struct ldb_dn **user_dn)
788 {
789         struct ldb_message *msg;
790         struct ldb_dn *dn;
791         uint32_t i;
792         int ret;
793
794         dn = ldb_dn_copy(mem_ctx, base_dn);
795         if (!dn) {
796                 return NT_STATUS_NO_MEMORY;
797         }
798         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
799                 return NT_STATUS_NO_MEMORY;
800         }
801
802         msg = ldb_msg_new(mem_ctx);
803         if (!msg) {
804                 return NT_STATUS_NO_MEMORY;
805         }
806         msg->dn = dn;
807
808         ret = ldb_msg_add_string(msg, "objectClass", "user");
809         if (ret != LDB_SUCCESS) {
810                 return NT_STATUS_NO_MEMORY;
811         }
812
813         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
814         if (ret != LDB_SUCCESS) {
815                 return NT_STATUS_NO_MEMORY;
816         }
817
818         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
819                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
820         if (ret != LDB_SUCCESS) {
821                 return NT_STATUS_NO_MEMORY;
822         }
823
824         for (i = 0; i < in->count; i++) {
825                 const char *attribute;
826                 struct ldb_val v;
827                 switch (in->current.array[i].AuthType) {
828                 case TRUST_AUTH_TYPE_NT4OWF:
829                         attribute = "unicodePwd";
830                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
831                         v.length = 16;
832                         break;
833                 case TRUST_AUTH_TYPE_CLEAR:
834                         attribute = "clearTextPassword";
835                         v.data = in->current.array[i].AuthInfo.clear.password;
836                         v.length = in->current.array[i].AuthInfo.clear.size;
837                         break;
838                 default:
839                         continue;
840                 }
841
842                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
843                 if (ret != LDB_SUCCESS) {
844                         return NT_STATUS_NO_MEMORY;
845                 }
846         }
847
848         /* create the trusted_domain user account */
849         ret = ldb_add(sam_ldb, msg);
850         if (ret != LDB_SUCCESS) {
851                 DEBUG(0,("Failed to create user record %s: %s\n",
852                          ldb_dn_get_linearized(msg->dn),
853                          ldb_errstring(sam_ldb)));
854
855                 switch (ret) {
856                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
857                         return NT_STATUS_DOMAIN_EXISTS;
858                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
859                         return NT_STATUS_ACCESS_DENIED;
860                 default:
861                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
862                 }
863         }
864
865         if (user_dn) {
866                 *user_dn = dn;
867         }
868         return NT_STATUS_OK;
869 }
870
871 /*
872   lsa_CreateTrustedDomainEx2
873 */
874 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
875                                                     TALLOC_CTX *mem_ctx,
876                                                     struct lsa_CreateTrustedDomainEx2 *r,
877                                                     int op)
878 {
879         struct dcesrv_handle *policy_handle;
880         struct lsa_policy_state *policy_state;
881         struct lsa_trusted_domain_state *trusted_domain_state;
882         struct dcesrv_handle *handle;
883         struct ldb_message **msgs, *msg;
884         const char *attrs[] = {
885                 NULL
886         };
887         const char *netbios_name;
888         const char *dns_name;
889         const char *name;
890         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
891         struct trustDomainPasswords auth_struct;
892         int ret;
893         NTSTATUS nt_status;
894         struct ldb_context *sam_ldb;
895
896         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
897         ZERO_STRUCTP(r->out.trustdom_handle);
898
899         policy_state = policy_handle->data;
900         sam_ldb = policy_state->sam_ldb;
901
902         netbios_name = r->in.info->netbios_name.string;
903         if (!netbios_name) {
904                 return NT_STATUS_INVALID_PARAMETER;
905         }
906
907         dns_name = r->in.info->domain_name.string;
908
909         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
910         if (!trusted_domain_state) {
911                 return NT_STATUS_NO_MEMORY;
912         }
913         trusted_domain_state->policy = policy_state;
914
915         if (strcasecmp(netbios_name, "BUILTIN") == 0
916             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
917             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
918                 return NT_STATUS_INVALID_PARAMETER;
919         }
920
921         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
922             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
923             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
924             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
925             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
926                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
927         }
928
929         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
930         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
931                 /* No secrets are created at this time, for this function */
932                 auth_struct.outgoing.count = 0;
933                 auth_struct.incoming.count = 0;
934         } else {
935                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
936                                             r->in.auth_info->auth_blob.size);
937                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
938                                                    &auth_blob, &auth_struct);
939                 if (!NT_STATUS_IS_OK(nt_status)) {
940                         return nt_status;
941                 }
942
943                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
944                         if (auth_struct.incoming.count > 1) {
945                                 return NT_STATUS_INVALID_PARAMETER;
946                         }
947                 }
948         }
949
950         if (auth_struct.incoming.count) {
951                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
952                                                      &auth_struct.incoming,
953                                                      &trustAuthIncoming);
954                 if (!NT_STATUS_IS_OK(nt_status)) {
955                         return nt_status;
956                 }
957         } else {
958                 trustAuthIncoming = data_blob(NULL, 0);
959         }
960
961         if (auth_struct.outgoing.count) {
962                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
963                                                      &auth_struct.outgoing,
964                                                      &trustAuthOutgoing);
965                 if (!NT_STATUS_IS_OK(nt_status)) {
966                         return nt_status;
967                 }
968         } else {
969                 trustAuthOutgoing = data_blob(NULL, 0);
970         }
971
972         ret = ldb_transaction_start(sam_ldb);
973         if (ret != LDB_SUCCESS) {
974                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
975         }
976
977         if (dns_name) {
978                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
979                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
980                 /* search for the trusted_domain record */
981                 ret = gendb_search(sam_ldb,
982                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
983                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
984                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
985                 if (ret > 0) {
986                         ldb_transaction_cancel(sam_ldb);
987                         return NT_STATUS_OBJECT_NAME_COLLISION;
988                 }
989         } else {
990                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
991                 /* search for the trusted_domain record */
992                 ret = gendb_search(sam_ldb,
993                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
994                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
995                                    netbios_encoded, netbios_encoded, netbios_encoded);
996                 if (ret > 0) {
997                         ldb_transaction_cancel(sam_ldb);
998                         return NT_STATUS_OBJECT_NAME_COLLISION;
999                 }
1000         }
1001
1002         if (ret < 0 ) {
1003                 ldb_transaction_cancel(sam_ldb);
1004                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1005         }
1006
1007         name = dns_name ? dns_name : netbios_name;
1008
1009         msg = ldb_msg_new(mem_ctx);
1010         if (msg == NULL) {
1011                 return NT_STATUS_NO_MEMORY;
1012         }
1013
1014         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1015         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1016                         ldb_transaction_cancel(sam_ldb);
1017                 return NT_STATUS_NO_MEMORY;
1018         }
1019
1020         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1021
1022         if (r->in.info->sid) {
1023                 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1024                 if (ret != LDB_SUCCESS) {
1025                         ldb_transaction_cancel(sam_ldb);
1026                         return NT_STATUS_INVALID_PARAMETER;
1027                 }
1028         }
1029
1030         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1031
1032         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1033
1034         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1035
1036         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1037
1038         if (dns_name) {
1039                 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1040         }
1041
1042         if (trustAuthIncoming.data) {
1043                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1044                 if (ret != LDB_SUCCESS) {
1045                         ldb_transaction_cancel(sam_ldb);
1046                         return NT_STATUS_NO_MEMORY;
1047                 }
1048         }
1049         if (trustAuthOutgoing.data) {
1050                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1051                 if (ret != LDB_SUCCESS) {
1052                         ldb_transaction_cancel(sam_ldb);
1053                         return NT_STATUS_NO_MEMORY;
1054                 }
1055         }
1056
1057         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1058
1059         /* create the trusted_domain */
1060         ret = ldb_add(sam_ldb, msg);
1061         switch (ret) {
1062         case  LDB_SUCCESS:
1063                 break;
1064         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1065                 ldb_transaction_cancel(sam_ldb);
1066                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1067                          ldb_dn_get_linearized(msg->dn),
1068                          ldb_errstring(sam_ldb)));
1069                 return NT_STATUS_DOMAIN_EXISTS;
1070         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1071                 ldb_transaction_cancel(sam_ldb);
1072                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1073                          ldb_dn_get_linearized(msg->dn),
1074                          ldb_errstring(sam_ldb)));
1075                 return NT_STATUS_ACCESS_DENIED;
1076         default:
1077                 ldb_transaction_cancel(sam_ldb);
1078                 DEBUG(0,("Failed to create user record %s: %s\n",
1079                          ldb_dn_get_linearized(msg->dn),
1080                          ldb_errstring(sam_ldb)));
1081                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1082         }
1083
1084         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1085                 struct ldb_dn *user_dn;
1086                 /* Inbound trusts must also create a cn=users object to match */
1087                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1088                                            policy_state->domain_dn,
1089                                            netbios_name,
1090                                            &auth_struct.incoming,
1091                                            &user_dn);
1092                 if (!NT_STATUS_IS_OK(nt_status)) {
1093                         ldb_transaction_cancel(sam_ldb);
1094                         return nt_status;
1095                 }
1096
1097                 /* save the trust user dn */
1098                 trusted_domain_state->trusted_domain_user_dn
1099                         = talloc_steal(trusted_domain_state, user_dn);
1100         }
1101
1102         ret = ldb_transaction_commit(sam_ldb);
1103         if (ret != LDB_SUCCESS) {
1104                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1105         }
1106
1107         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1108         if (!handle) {
1109                 return NT_STATUS_NO_MEMORY;
1110         }
1111
1112         handle->data = talloc_steal(handle, trusted_domain_state);
1113
1114         trusted_domain_state->access_mask = r->in.access_mask;
1115         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1116
1117         *r->out.trustdom_handle = handle->wire_handle;
1118
1119         return NT_STATUS_OK;
1120 }
1121
1122 /*
1123   lsa_CreateTrustedDomainEx2
1124 */
1125 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1126                                            TALLOC_CTX *mem_ctx,
1127                                            struct lsa_CreateTrustedDomainEx2 *r)
1128 {
1129         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1130 }
1131 /*
1132   lsa_CreateTrustedDomainEx
1133 */
1134 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1135                                           TALLOC_CTX *mem_ctx,
1136                                           struct lsa_CreateTrustedDomainEx *r)
1137 {
1138         struct lsa_CreateTrustedDomainEx2 r2;
1139
1140         r2.in.policy_handle = r->in.policy_handle;
1141         r2.in.info = r->in.info;
1142         r2.in.auth_info = r->in.auth_info;
1143         r2.out.trustdom_handle = r->out.trustdom_handle;
1144         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1145 }
1146
1147 /* 
1148   lsa_CreateTrustedDomain 
1149 */
1150 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151                                         struct lsa_CreateTrustedDomain *r)
1152 {
1153         struct lsa_CreateTrustedDomainEx2 r2;
1154
1155         r2.in.policy_handle = r->in.policy_handle;
1156         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1157         if (!r2.in.info) {
1158                 return NT_STATUS_NO_MEMORY;
1159         }
1160
1161         r2.in.info->domain_name.string = NULL;
1162         r2.in.info->netbios_name = r->in.info->name;
1163         r2.in.info->sid = r->in.info->sid;
1164         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1165         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1166         r2.in.info->trust_attributes = 0;
1167         
1168         r2.in.access_mask = r->in.access_mask;
1169         r2.out.trustdom_handle = r->out.trustdom_handle;
1170
1171         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1172                          
1173 }
1174
1175 /* 
1176   lsa_OpenTrustedDomain
1177 */
1178 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179                                       struct lsa_OpenTrustedDomain *r)
1180 {
1181         struct dcesrv_handle *policy_handle;
1182         
1183         struct lsa_policy_state *policy_state;
1184         struct lsa_trusted_domain_state *trusted_domain_state;
1185         struct dcesrv_handle *handle;
1186         struct ldb_message **msgs;
1187         const char *attrs[] = {
1188                 "trustDirection",
1189                 "flatname",
1190                 NULL
1191         };
1192
1193         const char *sid_string;
1194         int ret;
1195
1196         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1197         ZERO_STRUCTP(r->out.trustdom_handle);
1198         policy_state = policy_handle->data;
1199
1200         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1201         if (!trusted_domain_state) {
1202                 return NT_STATUS_NO_MEMORY;
1203         }
1204         trusted_domain_state->policy = policy_state;
1205
1206         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1207         if (!sid_string) {
1208                 return NT_STATUS_NO_MEMORY;
1209         }
1210
1211         /* search for the trusted_domain record */
1212         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1213                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1214                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
1215                            sid_string);
1216         if (ret == 0) {
1217                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1218         }
1219         
1220         if (ret != 1) {
1221                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1222                          ldb_dn_get_linearized(policy_state->system_dn)));
1223                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1224         }
1225
1226         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1227
1228         trusted_domain_state->trusted_domain_user_dn = NULL;
1229
1230         if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1231                 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1232                 /* search for the trusted_domain record */
1233                 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1234                                    mem_ctx, policy_state->domain_dn, &msgs, attrs,
1235                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
1236                                    flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1237                 if (ret == 1) {
1238                         trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1239                 }
1240         }
1241         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1242         if (!handle) {
1243                 return NT_STATUS_NO_MEMORY;
1244         }
1245         
1246         handle->data = talloc_steal(handle, trusted_domain_state);
1247         
1248         trusted_domain_state->access_mask = r->in.access_mask;
1249         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1250         
1251         *r->out.trustdom_handle = handle->wire_handle;
1252         
1253         return NT_STATUS_OK;
1254 }
1255
1256
1257 /*
1258   lsa_OpenTrustedDomainByName
1259 */
1260 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1261                                             TALLOC_CTX *mem_ctx,
1262                                             struct lsa_OpenTrustedDomainByName *r)
1263 {
1264         struct dcesrv_handle *policy_handle;
1265
1266         struct lsa_policy_state *policy_state;
1267         struct lsa_trusted_domain_state *trusted_domain_state;
1268         struct dcesrv_handle *handle;
1269         struct ldb_message **msgs;
1270         const char *attrs[] = {
1271                 NULL
1272         };
1273         char *td_name;
1274         int ret;
1275
1276         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1277         ZERO_STRUCTP(r->out.trustdom_handle);
1278         policy_state = policy_handle->data;
1279
1280         if (!r->in.name.string) {
1281                 return NT_STATUS_INVALID_PARAMETER;
1282         }
1283
1284         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1285         if (!trusted_domain_state) {
1286                 return NT_STATUS_NO_MEMORY;
1287         }
1288         trusted_domain_state->policy = policy_state;
1289
1290         /* search for the trusted_domain record */
1291         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1292         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1293                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1294                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1295                              "(objectclass=trustedDomain))",
1296                            td_name, td_name, td_name);
1297         if (ret == 0) {
1298                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1299         }
1300
1301         if (ret != 1) {
1302                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1303                          ldb_dn_get_linearized(policy_state->system_dn)));
1304                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1305         }
1306
1307         /* TODO: perform access checks */
1308
1309         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1310
1311         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1312         if (!handle) {
1313                 return NT_STATUS_NO_MEMORY;
1314         }
1315
1316         handle->data = talloc_steal(handle, trusted_domain_state);
1317
1318         trusted_domain_state->access_mask = r->in.access_mask;
1319         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1320
1321         *r->out.trustdom_handle = handle->wire_handle;
1322
1323         return NT_STATUS_OK;
1324 }
1325
1326
1327
1328 /* 
1329   lsa_SetTrustedDomainInfo
1330 */
1331 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1332                                          struct lsa_SetTrustedDomainInfo *r)
1333 {
1334         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1335 }
1336
1337
1338
1339 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1340  * otherwise at least one must be provided */
1341 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1342                         struct ldb_dn *basedn, const char *dns_domain,
1343                         const char *netbios, struct dom_sid2 *sid,
1344                         struct ldb_message ***msgs)
1345 {
1346         const char *attrs[] = { "flatname", "trustPartner",
1347                                 "securityIdentifier", "trustDirection",
1348                                 "trustType", "trustAttributes",
1349                                 "trustPosixOffset",
1350                                 "msDs-supportedEncryptionTypes", NULL };
1351         char *dns = NULL;
1352         char *nbn = NULL;
1353         char *sidstr = NULL;
1354         char *filter;
1355         int ret;
1356
1357
1358         if (dns_domain || netbios || sid) {
1359                 filter = talloc_strdup(mem_ctx,
1360                                    "(&(objectclass=trustedDomain)(|");
1361         } else {
1362                 filter = talloc_strdup(mem_ctx,
1363                                        "(objectclass=trustedDomain)");
1364         }
1365         if (!filter) {
1366                 return NT_STATUS_NO_MEMORY;
1367         }
1368
1369         if (dns_domain) {
1370                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1371                 if (!dns) {
1372                         return NT_STATUS_NO_MEMORY;
1373                 }
1374                 filter = talloc_asprintf_append(filter,
1375                                                 "(trustPartner=%s)", dns);
1376                 if (!filter) {
1377                         return NT_STATUS_NO_MEMORY;
1378                 }
1379         }
1380         if (netbios) {
1381                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1382                 if (!nbn) {
1383                         return NT_STATUS_NO_MEMORY;
1384                 }
1385                 filter = talloc_asprintf_append(filter,
1386                                                 "(flatname=%s)", nbn);
1387                 if (!filter) {
1388                         return NT_STATUS_NO_MEMORY;
1389                 }
1390         }
1391         if (sid) {
1392                 sidstr = dom_sid_string(mem_ctx, sid);
1393                 if (!sidstr) {
1394                         return NT_STATUS_INVALID_PARAMETER;
1395                 }
1396                 filter = talloc_asprintf_append(filter,
1397                                                 "(securityIdentifier=%s)",
1398                                                 sidstr);
1399                 if (!filter) {
1400                         return NT_STATUS_NO_MEMORY;
1401                 }
1402         }
1403         if (dns_domain || netbios || sid) {
1404                 filter = talloc_asprintf_append(filter, "))");
1405                 if (!filter) {
1406                         return NT_STATUS_NO_MEMORY;
1407                 }
1408         }
1409
1410         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1411         if (ret == 0) {
1412                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1413         }
1414
1415         if (ret != 1) {
1416                 return NT_STATUS_OBJECT_NAME_COLLISION;
1417         }
1418
1419         return NT_STATUS_OK;
1420 }
1421
1422 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1423                                       struct ldb_context *sam_ldb,
1424                                       struct ldb_message *orig,
1425                                       struct ldb_message *dest,
1426                                       const char *attribute,
1427                                       uint32_t value,
1428                                       uint32_t *orig_value)
1429 {
1430         const struct ldb_val *orig_val;
1431         uint32_t orig_uint = 0;
1432         int flags = 0;
1433         int ret;
1434
1435         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1436         if (!orig_val || !orig_val->data) {
1437                 /* add new attribute */
1438                 flags = LDB_FLAG_MOD_ADD;
1439
1440         } else {
1441                 errno = 0;
1442                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1443                 if (errno != 0 || orig_uint != value) {
1444                         /* replace also if can't get value */
1445                         flags = LDB_FLAG_MOD_REPLACE;
1446                 }
1447         }
1448
1449         if (flags == 0) {
1450                 /* stored value is identical, nothing to change */
1451                 goto done;
1452         }
1453
1454         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1455         if (ret != LDB_SUCCESS) {
1456                 return NT_STATUS_NO_MEMORY;
1457         }
1458
1459         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1460         if (ret != LDB_SUCCESS) {
1461                 return NT_STATUS_NO_MEMORY;
1462         }
1463
1464 done:
1465         if (orig_value) {
1466                 *orig_value = orig_uint;
1467         }
1468         return NT_STATUS_OK;
1469 }
1470
1471 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1472                                   struct ldb_context *sam_ldb,
1473                                   struct ldb_dn *base_dn,
1474                                   bool delete_user,
1475                                   const char *netbios_name,
1476                                   struct trustAuthInOutBlob *in)
1477 {
1478         const char *attrs[] = { "userAccountControl", NULL };
1479         struct ldb_message **msgs;
1480         struct ldb_message *msg;
1481         uint32_t uac;
1482         uint32_t i;
1483         int ret;
1484
1485         ret = gendb_search(sam_ldb, mem_ctx,
1486                            base_dn, &msgs, attrs,
1487                            "samAccountName=%s$", netbios_name);
1488         if (ret > 1) {
1489                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1490         }
1491
1492         if (ret == 0) {
1493                 if (delete_user) {
1494                         return NT_STATUS_OK;
1495                 }
1496
1497                 /* ok no existing user, add it from scratch */
1498                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1499                                       netbios_name, in, NULL);
1500         }
1501
1502         /* check user is what we are looking for */
1503         uac = ldb_msg_find_attr_as_uint(msgs[0],
1504                                         "userAccountControl", 0);
1505         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1506                 return NT_STATUS_OBJECT_NAME_COLLISION;
1507         }
1508
1509         if (delete_user) {
1510                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1511                 switch (ret) {
1512                 case LDB_SUCCESS:
1513                         return NT_STATUS_OK;
1514                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1515                         return NT_STATUS_ACCESS_DENIED;
1516                 default:
1517                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1518                 }
1519         }
1520
1521         /* entry exists, just modify secret if any */
1522         if (in->count == 0) {
1523                 return NT_STATUS_OK;
1524         }
1525
1526         msg = ldb_msg_new(mem_ctx);
1527         if (!msg) {
1528                 return NT_STATUS_NO_MEMORY;
1529         }
1530         msg->dn = msgs[0]->dn;
1531
1532         for (i = 0; i < in->count; i++) {
1533                 const char *attribute;
1534                 struct ldb_val v;
1535                 switch (in->current.array[i].AuthType) {
1536                 case TRUST_AUTH_TYPE_NT4OWF:
1537                         attribute = "unicodePwd";
1538                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1539                         v.length = 16;
1540                         break;
1541                 case TRUST_AUTH_TYPE_CLEAR:
1542                         attribute = "clearTextPassword";
1543                         v.data = in->current.array[i].AuthInfo.clear.password;
1544                         v.length = in->current.array[i].AuthInfo.clear.size;
1545                         break;
1546                 default:
1547                         continue;
1548                 }
1549
1550                 ret = ldb_msg_add_empty(msg, attribute,
1551                                         LDB_FLAG_MOD_REPLACE, NULL);
1552                 if (ret != LDB_SUCCESS) {
1553                         return NT_STATUS_NO_MEMORY;
1554                 }
1555
1556                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1557                 if (ret != LDB_SUCCESS) {
1558                         return NT_STATUS_NO_MEMORY;
1559                 }
1560         }
1561
1562         /* create the trusted_domain user account */
1563         ret = ldb_modify(sam_ldb, msg);
1564         if (ret != LDB_SUCCESS) {
1565                 DEBUG(0,("Failed to create user record %s: %s\n",
1566                          ldb_dn_get_linearized(msg->dn),
1567                          ldb_errstring(sam_ldb)));
1568
1569                 switch (ret) {
1570                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1571                         return NT_STATUS_DOMAIN_EXISTS;
1572                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1573                         return NT_STATUS_ACCESS_DENIED;
1574                 default:
1575                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1576                 }
1577         }
1578
1579         return NT_STATUS_OK;
1580 }
1581
1582
1583 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1584                                           struct dcesrv_handle *p_handle,
1585                                           TALLOC_CTX *mem_ctx,
1586                                           struct ldb_message *dom_msg,
1587                                           enum lsa_TrustDomInfoEnum level,
1588                                           union lsa_TrustedDomainInfo *info)
1589 {
1590         struct lsa_policy_state *p_state = p_handle->data;
1591         uint32_t *posix_offset = NULL;
1592         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1593         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1594         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1595         uint32_t *enc_types = NULL;
1596         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1597         struct trustDomainPasswords auth_struct;
1598         NTSTATUS nt_status;
1599         struct ldb_message **msgs;
1600         struct ldb_message *msg;
1601         bool add_outgoing = false;
1602         bool add_incoming = false;
1603         bool del_outgoing = false;
1604         bool del_incoming = false;
1605         bool in_transaction = false;
1606         int ret;
1607         bool am_rodc;
1608
1609         switch (level) {
1610         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1611                 posix_offset = &info->posix_offset.posix_offset;
1612                 break;
1613         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1614                 info_ex = &info->info_ex;
1615                 break;
1616         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1617                 auth_info = &info->auth_info;
1618                 break;
1619         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1620                 posix_offset = &info->full_info.posix_offset.posix_offset;
1621                 info_ex = &info->full_info.info_ex;
1622                 auth_info = &info->full_info.auth_info;
1623                 break;
1624         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1625                 auth_info_int = &info->auth_info_internal;
1626                 break;
1627         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1628                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1629                 info_ex = &info->full_info_internal.info_ex;
1630                 auth_info_int = &info->full_info_internal.auth_info;
1631                 break;
1632         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1633                 enc_types = &info->enc_types.enc_types;
1634                 break;
1635         default:
1636                 return NT_STATUS_INVALID_PARAMETER;
1637         }
1638
1639         if (auth_info) {
1640                 /* FIXME: not handled yet */
1641                 return NT_STATUS_INVALID_PARAMETER;
1642         }
1643
1644         /* decode auth_info_int if set */
1645         if (auth_info_int) {
1646
1647                 /* now decrypt blob */
1648                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1649                                             auth_info_int->auth_blob.size);
1650
1651                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1652                                                    &auth_blob, &auth_struct);
1653                 if (!NT_STATUS_IS_OK(nt_status)) {
1654                         return nt_status;
1655                 }
1656         }
1657
1658         if (info_ex) {
1659                 /* verify data matches */
1660                 if (info_ex->trust_attributes &
1661                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1662                         /* TODO: check what behavior level we have */
1663                        if (strcasecmp_m(p_state->domain_dns,
1664                                         p_state->forest_dns) != 0) {
1665                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1666                         }
1667                 }
1668
1669                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1670                 if (ret == LDB_SUCCESS && am_rodc) {
1671                         return NT_STATUS_NO_SUCH_DOMAIN;
1672                 }
1673
1674                 /* verify only one object matches the dns/netbios/sid
1675                  * triplet and that this is the one we already have */
1676                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1677                                     p_state->system_dn,
1678                                     info_ex->domain_name.string,
1679                                     info_ex->netbios_name.string,
1680                                     info_ex->sid, &msgs);
1681                 if (!NT_STATUS_IS_OK(nt_status)) {
1682                         return nt_status;
1683                 }
1684                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1685                         return NT_STATUS_OBJECT_NAME_COLLISION;
1686                 }
1687                 talloc_free(msgs);
1688         }
1689
1690         /* TODO: should we fetch previous values from the existing entry
1691          * and append them ? */
1692         if (auth_struct.incoming.count) {
1693                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1694                                                      &auth_struct.incoming,
1695                                                      &trustAuthIncoming);
1696                 if (!NT_STATUS_IS_OK(nt_status)) {
1697                         return nt_status;
1698                 }
1699         } else {
1700                 trustAuthIncoming = data_blob(NULL, 0);
1701         }
1702
1703         if (auth_struct.outgoing.count) {
1704                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1705                                                      &auth_struct.outgoing,
1706                                                      &trustAuthOutgoing);
1707                 if (!NT_STATUS_IS_OK(nt_status)) {
1708                         return nt_status;
1709                 }
1710         } else {
1711                 trustAuthOutgoing = data_blob(NULL, 0);
1712         }
1713
1714         msg = ldb_msg_new(mem_ctx);
1715         if (msg == NULL) {
1716                 return NT_STATUS_NO_MEMORY;
1717         }
1718         msg->dn = dom_msg->dn;
1719
1720         if (posix_offset) {
1721                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1722                                                   dom_msg, msg,
1723                                                   "trustPosixOffset",
1724                                                   *posix_offset, NULL);
1725                 if (!NT_STATUS_IS_OK(nt_status)) {
1726                         return nt_status;
1727                 }
1728         }
1729
1730         if (info_ex) {
1731                 uint32_t origattrs;
1732                 uint32_t origdir;
1733                 uint32_t tmp;
1734                 int origtype;
1735
1736                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1737                                                   dom_msg, msg,
1738                                                   "trustDirection",
1739                                                   info_ex->trust_direction,
1740                                                   &origdir);
1741                 if (!NT_STATUS_IS_OK(nt_status)) {
1742                         return nt_status;
1743                 }
1744
1745                 tmp = info_ex->trust_direction ^ origdir;
1746                 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1747                         if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1748                                 del_incoming = true;
1749                         } else {
1750                                 add_incoming = true;
1751                         }
1752                 }
1753                 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1754                         if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1755                                 del_outgoing = true;
1756                         } else {
1757                                 add_outgoing = true;
1758                         }
1759                 }
1760
1761                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1762                 if (origtype == -1 || origtype != info_ex->trust_type) {
1763                         DEBUG(1, ("Attempted to change trust type! "
1764                                   "Operation not handled\n"));
1765                         return NT_STATUS_INVALID_PARAMETER;
1766                 }
1767
1768                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1769                                                   dom_msg, msg,
1770                                                   "trustAttributes",
1771                                                   info_ex->trust_attributes,
1772                                                   &origattrs);
1773                 if (!NT_STATUS_IS_OK(nt_status)) {
1774                         return nt_status;
1775                 }
1776                 /* TODO: check forestFunctionality from ldb opaque */
1777                 /* TODO: check what is set makes sense */
1778                 /* for now refuse changes */
1779                 if (origattrs == -1 ||
1780                     origattrs != info_ex->trust_attributes) {
1781                         DEBUG(1, ("Attempted to change trust attributes! "
1782                                   "Operation not handled\n"));
1783                         return NT_STATUS_INVALID_PARAMETER;
1784                 }
1785         }
1786
1787         if (enc_types) {
1788                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1789                                                   dom_msg, msg,
1790                                                   "msDS-SupportedEncryptionTypes",
1791                                                   *enc_types, NULL);
1792                 if (!NT_STATUS_IS_OK(nt_status)) {
1793                         return nt_status;
1794                 }
1795         }
1796
1797         if (add_incoming && trustAuthIncoming.data) {
1798                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1799                                         LDB_FLAG_MOD_REPLACE, NULL);
1800                 if (ret != LDB_SUCCESS) {
1801                         return NT_STATUS_NO_MEMORY;
1802                 }
1803                 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1804                                         &trustAuthIncoming, NULL);
1805                 if (ret != LDB_SUCCESS) {
1806                         return NT_STATUS_NO_MEMORY;
1807                 }
1808         }
1809         if (add_outgoing && trustAuthOutgoing.data) {
1810                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1811                                         LDB_FLAG_MOD_REPLACE, NULL);
1812                 if (ret != LDB_SUCCESS) {
1813                         return NT_STATUS_NO_MEMORY;
1814                 }
1815                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1816                                         &trustAuthOutgoing, NULL);
1817                 if (ret != LDB_SUCCESS) {
1818                         return NT_STATUS_NO_MEMORY;
1819                 }
1820         }
1821
1822         /* start transaction */
1823         ret = ldb_transaction_start(p_state->sam_ldb);
1824         if (ret != LDB_SUCCESS) {
1825                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1826         }
1827         in_transaction = true;
1828
1829         ret = ldb_modify(p_state->sam_ldb, msg);
1830         if (ret != LDB_SUCCESS) {
1831                 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1832                          ldb_dn_get_linearized(msg->dn),
1833                          ldb_errstring(p_state->sam_ldb)));
1834                 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1835                         nt_status = NT_STATUS_ACCESS_DENIED;
1836                 } else {
1837                         nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1838                 }
1839                 goto done;
1840         }
1841
1842         if (add_incoming || del_incoming) {
1843                 const char *netbios_name;
1844
1845                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1846                                                            "flatname", NULL);
1847                 if (!netbios_name) {
1848                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1849                         goto done;
1850                 }
1851
1852                 nt_status = update_trust_user(mem_ctx,
1853                                               p_state->sam_ldb,
1854                                               p_state->domain_dn,
1855                                               del_incoming,
1856                                               netbios_name,
1857                                               &auth_struct.incoming);
1858                 if (!NT_STATUS_IS_OK(nt_status)) {
1859                         goto done;
1860                 }
1861         }
1862
1863         /* ok, all fine, commit transaction and return */
1864         ret = ldb_transaction_commit(p_state->sam_ldb);
1865         if (ret != LDB_SUCCESS) {
1866                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1867         }
1868         in_transaction = false;
1869
1870         nt_status = NT_STATUS_OK;
1871
1872 done:
1873         if (in_transaction) {
1874                 ldb_transaction_cancel(p_state->sam_ldb);
1875         }
1876         return nt_status;
1877 }
1878
1879 /*
1880   lsa_SetInfomrationTrustedDomain
1881 */
1882 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1883                                 struct dcesrv_call_state *dce_call,
1884                                 TALLOC_CTX *mem_ctx,
1885                                 struct lsa_SetInformationTrustedDomain *r)
1886 {
1887         struct dcesrv_handle *h;
1888         struct lsa_trusted_domain_state *td_state;
1889         struct ldb_message **msgs;
1890         NTSTATUS nt_status;
1891
1892         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1893                            LSA_HANDLE_TRUSTED_DOMAIN);
1894
1895         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1896
1897         /* get the trusted domain object */
1898         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1899                             td_state->trusted_domain_dn,
1900                             NULL, NULL, NULL, &msgs);
1901         if (!NT_STATUS_IS_OK(nt_status)) {
1902                 if (NT_STATUS_EQUAL(nt_status,
1903                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1904                         return nt_status;
1905                 }
1906                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1907         }
1908
1909         return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1910                                          msgs[0], r->in.level, r->in.info);
1911 }
1912
1913
1914 /* 
1915   lsa_DeleteTrustedDomain
1916 */
1917 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1918                                       struct lsa_DeleteTrustedDomain *r)
1919 {
1920         NTSTATUS status;
1921         struct lsa_OpenTrustedDomain opn;
1922         struct lsa_DeleteObject del;
1923         struct dcesrv_handle *h;
1924
1925         opn.in.handle = r->in.handle;
1926         opn.in.sid = r->in.dom_sid;
1927         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1928         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1929         if (!opn.out.trustdom_handle) {
1930                 return NT_STATUS_NO_MEMORY;
1931         }
1932         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1933         if (!NT_STATUS_IS_OK(status)) {
1934                 return status;
1935         }
1936
1937         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1938         talloc_steal(mem_ctx, h);
1939
1940         del.in.handle = opn.out.trustdom_handle;
1941         del.out.handle = opn.out.trustdom_handle;
1942         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1943         if (!NT_STATUS_IS_OK(status)) {
1944                 return status;
1945         }
1946         return NT_STATUS_OK;
1947 }
1948
1949 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1950                                      struct ldb_message *msg, 
1951                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1952 {
1953         info_ex->domain_name.string
1954                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1955         info_ex->netbios_name.string
1956                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1957         info_ex->sid 
1958                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1959         info_ex->trust_direction
1960                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1961         info_ex->trust_type
1962                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1963         info_ex->trust_attributes
1964                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1965         return NT_STATUS_OK;
1966 }
1967
1968 /* 
1969   lsa_QueryTrustedDomainInfo
1970 */
1971 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1972                                            struct lsa_QueryTrustedDomainInfo *r)
1973 {
1974         union lsa_TrustedDomainInfo *info = NULL;
1975         struct dcesrv_handle *h;
1976         struct lsa_trusted_domain_state *trusted_domain_state;
1977         struct ldb_message *msg;
1978         int ret;
1979         struct ldb_message **res;
1980         const char *attrs[] = {
1981                 "flatname", 
1982                 "trustPartner",
1983                 "securityIdentifier",
1984                 "trustDirection",
1985                 "trustType",
1986                 "trustAttributes", 
1987                 "msDs-supportedEncryptionTypes",
1988                 NULL
1989         };
1990
1991         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1992
1993         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1994
1995         /* pull all the user attributes */
1996         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1997                               trusted_domain_state->trusted_domain_dn, &res, attrs);
1998         if (ret != 1) {
1999                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2000         }
2001         msg = res[0];
2002         
2003         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2004         if (!info) {
2005                 return NT_STATUS_NO_MEMORY;
2006         }
2007         *r->out.info = info;
2008
2009         switch (r->in.level) {
2010         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2011                 info->name.netbios_name.string
2012                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2013                 break;
2014         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2015                 info->posix_offset.posix_offset
2016                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2017                 break;
2018 #if 0  /* Win2k3 doesn't implement this */
2019         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2020                 r->out.info->info_basic.netbios_name.string 
2021                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2022                 r->out.info->info_basic.sid
2023                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2024                 break;
2025 #endif
2026         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2027                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2028
2029         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2030                 ZERO_STRUCT(info->full_info);
2031                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2032         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2033                 ZERO_STRUCT(info->full_info2_internal);
2034                 info->full_info2_internal.posix_offset.posix_offset
2035                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2036                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2037                 
2038         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2039                 info->enc_types.enc_types
2040                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2041                 break;
2042
2043         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2044         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2045                 /* oops, we don't want to return the info after all */
2046                 talloc_free(info);
2047                 *r->out.info = NULL;
2048                 return NT_STATUS_INVALID_PARAMETER;
2049         default:
2050                 /* oops, we don't want to return the info after all */
2051                 talloc_free(info);
2052                 *r->out.info = NULL;
2053                 return NT_STATUS_INVALID_INFO_CLASS;
2054         }
2055
2056         return NT_STATUS_OK;
2057 }
2058
2059
2060 /* 
2061   lsa_QueryTrustedDomainInfoBySid
2062 */
2063 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2064                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2065 {
2066         NTSTATUS status;
2067         struct lsa_OpenTrustedDomain opn;
2068         struct lsa_QueryTrustedDomainInfo query;
2069         struct dcesrv_handle *h;
2070
2071         opn.in.handle = r->in.handle;
2072         opn.in.sid = r->in.dom_sid;
2073         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2074         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2075         if (!opn.out.trustdom_handle) {
2076                 return NT_STATUS_NO_MEMORY;
2077         }
2078         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2079         if (!NT_STATUS_IS_OK(status)) {
2080                 return status;
2081         }
2082
2083         /* Ensure this handle goes away at the end of this call */
2084         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2085         talloc_steal(mem_ctx, h);
2086
2087         query.in.trustdom_handle = opn.out.trustdom_handle;
2088         query.in.level = r->in.level;
2089         query.out.info = r->out.info;
2090         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2091         if (!NT_STATUS_IS_OK(status)) {
2092                 return status;
2093         }
2094
2095         return NT_STATUS_OK;
2096 }
2097
2098 /*
2099   lsa_SetTrustedDomainInfoByName
2100 */
2101 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2102                                                TALLOC_CTX *mem_ctx,
2103                                                struct lsa_SetTrustedDomainInfoByName *r)
2104 {
2105         struct dcesrv_handle *policy_handle;
2106         struct lsa_policy_state *policy_state;
2107         struct ldb_message **msgs;
2108         NTSTATUS nt_status;
2109
2110         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2111         policy_state = policy_handle->data;
2112
2113         /* get the trusted domain object */
2114         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2115                             policy_state->domain_dn,
2116                             r->in.trusted_domain->string,
2117                             r->in.trusted_domain->string,
2118                             NULL, &msgs);
2119         if (!NT_STATUS_IS_OK(nt_status)) {
2120                 if (NT_STATUS_EQUAL(nt_status,
2121                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2122                         return nt_status;
2123                 }
2124                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2125         }
2126
2127         return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2128                                          msgs[0], r->in.level, r->in.info);
2129 }
2130
2131 /* 
2132    lsa_QueryTrustedDomainInfoByName
2133 */
2134 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2135                                                  TALLOC_CTX *mem_ctx,
2136                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2137 {
2138         NTSTATUS status;
2139         struct lsa_OpenTrustedDomainByName opn;
2140         struct lsa_QueryTrustedDomainInfo query;
2141         struct dcesrv_handle *h;
2142
2143         opn.in.handle = r->in.handle;
2144         opn.in.name = *r->in.trusted_domain;
2145         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2146         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2147         if (!opn.out.trustdom_handle) {
2148                 return NT_STATUS_NO_MEMORY;
2149         }
2150         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2151         if (!NT_STATUS_IS_OK(status)) {
2152                 return status;
2153         }
2154         
2155         /* Ensure this handle goes away at the end of this call */
2156         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2157         talloc_steal(mem_ctx, h);
2158
2159         query.in.trustdom_handle = opn.out.trustdom_handle;
2160         query.in.level = r->in.level;
2161         query.out.info = r->out.info;
2162         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2163         if (!NT_STATUS_IS_OK(status)) {
2164                 return status;
2165         }
2166         
2167         return NT_STATUS_OK;
2168 }
2169
2170 /*
2171   lsa_CloseTrustedDomainEx 
2172 */
2173 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2174                                          TALLOC_CTX *mem_ctx,
2175                                          struct lsa_CloseTrustedDomainEx *r)
2176 {
2177         /* The result of a bad hair day from an IDL programmer?  Not
2178          * implmented in Win2k3.  You should always just lsa_Close
2179          * anyway. */
2180         return NT_STATUS_NOT_IMPLEMENTED;
2181 }
2182
2183
2184 /*
2185   comparison function for sorting lsa_DomainInformation array
2186 */
2187 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2188 {
2189         return strcasecmp_m(e1->name.string, e2->name.string);
2190 }
2191
2192 /* 
2193   lsa_EnumTrustDom 
2194 */
2195 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2196                                  struct lsa_EnumTrustDom *r)
2197 {
2198         struct dcesrv_handle *policy_handle;
2199         struct lsa_DomainInfo *entries;
2200         struct lsa_policy_state *policy_state;
2201         struct ldb_message **domains;
2202         const char *attrs[] = {
2203                 "flatname", 
2204                 "securityIdentifier",
2205                 NULL
2206         };
2207
2208
2209         int count, i;
2210
2211         *r->out.resume_handle = 0;
2212
2213         r->out.domains->domains = NULL;
2214         r->out.domains->count = 0;
2215
2216         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2217
2218         policy_state = policy_handle->data;
2219
2220         /* search for all users in this domain. This could possibly be cached and 
2221            resumed based on resume_key */
2222         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2223                              "objectclass=trustedDomain");
2224         if (count < 0) {
2225                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2226         }
2227
2228         /* convert to lsa_TrustInformation format */
2229         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2230         if (!entries) {
2231                 return NT_STATUS_NO_MEMORY;
2232         }
2233         for (i=0;i<count;i++) {
2234                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2235                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2236         }
2237
2238         /* sort the results by name */
2239         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2240
2241         if (*r->in.resume_handle >= count) {
2242                 *r->out.resume_handle = -1;
2243
2244                 return NT_STATUS_NO_MORE_ENTRIES;
2245         }
2246
2247         /* return the rest, limit by max_size. Note that we 
2248            use the w2k3 element size value of 60 */
2249         r->out.domains->count = count - *r->in.resume_handle;
2250         r->out.domains->count = MIN(r->out.domains->count, 
2251                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2252
2253         r->out.domains->domains = entries + *r->in.resume_handle;
2254         r->out.domains->count = r->out.domains->count;
2255
2256         if (r->out.domains->count < count - *r->in.resume_handle) {
2257                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2258                 return STATUS_MORE_ENTRIES;
2259         }
2260
2261         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2262          * always be larger than the previous input resume handle, in
2263          * particular when hitting the last query it is vital to set the
2264          * resume handle correctly to avoid infinite client loops, as
2265          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2266          * status is NT_STATUS_OK - gd */
2267
2268         *r->out.resume_handle = (uint32_t)-1;
2269
2270         return NT_STATUS_OK;
2271 }
2272
2273 /*
2274   comparison function for sorting lsa_DomainInformation array
2275 */
2276 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2277 {
2278         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2279 }
2280
2281 /* 
2282   lsa_EnumTrustedDomainsEx 
2283 */
2284 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2285                                         struct lsa_EnumTrustedDomainsEx *r)
2286 {
2287         struct dcesrv_handle *policy_handle;
2288         struct lsa_TrustDomainInfoInfoEx *entries;
2289         struct lsa_policy_state *policy_state;
2290         struct ldb_message **domains;
2291         const char *attrs[] = {
2292                 "flatname", 
2293                 "trustPartner",
2294                 "securityIdentifier",
2295                 "trustDirection",
2296                 "trustType",
2297                 "trustAttributes", 
2298                 NULL
2299         };
2300         NTSTATUS nt_status;
2301
2302         int count, i;
2303
2304         *r->out.resume_handle = 0;
2305
2306         r->out.domains->domains = NULL;
2307         r->out.domains->count = 0;
2308
2309         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2310
2311         policy_state = policy_handle->data;
2312
2313         /* search for all users in this domain. This could possibly be cached and 
2314            resumed based on resume_key */
2315         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2316                              "objectclass=trustedDomain");
2317         if (count < 0) {
2318                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2319         }
2320
2321         /* convert to lsa_DomainInformation format */
2322         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2323         if (!entries) {
2324                 return NT_STATUS_NO_MEMORY;
2325         }
2326         for (i=0;i<count;i++) {
2327                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2328                 if (!NT_STATUS_IS_OK(nt_status)) {
2329                         return nt_status;
2330                 }
2331         }
2332
2333         /* sort the results by name */
2334         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2335
2336         if (*r->in.resume_handle >= count) {
2337                 *r->out.resume_handle = -1;
2338
2339                 return NT_STATUS_NO_MORE_ENTRIES;
2340         }
2341
2342         /* return the rest, limit by max_size. Note that we 
2343            use the w2k3 element size value of 60 */
2344         r->out.domains->count = count - *r->in.resume_handle;
2345         r->out.domains->count = MIN(r->out.domains->count, 
2346                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2347
2348         r->out.domains->domains = entries + *r->in.resume_handle;
2349         r->out.domains->count = r->out.domains->count;
2350
2351         if (r->out.domains->count < count - *r->in.resume_handle) {
2352                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2353                 return STATUS_MORE_ENTRIES;
2354         }
2355
2356         return NT_STATUS_OK;
2357 }
2358
2359
2360 /* 
2361   lsa_OpenAccount 
2362 */
2363 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2364                                 struct lsa_OpenAccount *r)
2365 {
2366         struct dcesrv_handle *h, *ah;
2367         struct lsa_policy_state *state;
2368         struct lsa_account_state *astate;
2369
2370         ZERO_STRUCTP(r->out.acct_handle);
2371
2372         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2373
2374         state = h->data;
2375
2376         astate = talloc(dce_call->conn, struct lsa_account_state);
2377         if (astate == NULL) {
2378                 return NT_STATUS_NO_MEMORY;
2379         }
2380
2381         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2382         if (astate->account_sid == NULL) {
2383                 talloc_free(astate);
2384                 return NT_STATUS_NO_MEMORY;
2385         }
2386         
2387         astate->policy = talloc_reference(astate, state);
2388         astate->access_mask = r->in.access_mask;
2389
2390         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2391         if (!ah) {
2392                 talloc_free(astate);
2393                 return NT_STATUS_NO_MEMORY;
2394         }
2395
2396         ah->data = talloc_steal(ah, astate);
2397
2398         *r->out.acct_handle = ah->wire_handle;
2399
2400         return NT_STATUS_OK;
2401 }
2402
2403
2404 /* 
2405   lsa_EnumPrivsAccount 
2406 */
2407 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
2408                                      TALLOC_CTX *mem_ctx,
2409                                      struct lsa_EnumPrivsAccount *r)
2410 {
2411         struct dcesrv_handle *h;
2412         struct lsa_account_state *astate;
2413         int ret;
2414         unsigned int i, j;
2415         struct ldb_message **res;
2416         const char * const attrs[] = { "privilege", NULL};
2417         struct ldb_message_element *el;
2418         const char *sidstr;
2419         struct lsa_PrivilegeSet *privs;
2420
2421         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2422
2423         astate = h->data;
2424
2425         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2426         if (privs == NULL) {
2427                 return NT_STATUS_NO_MEMORY;
2428         }
2429         privs->count = 0;
2430         privs->unknown = 0;
2431         privs->set = NULL;
2432
2433         *r->out.privs = privs;
2434
2435         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2436         if (sidstr == NULL) {
2437                 return NT_STATUS_NO_MEMORY;
2438         }
2439
2440         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
2441                            "objectSid=%s", sidstr);
2442         if (ret < 0) {
2443                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2444         }
2445         if (ret != 1) {
2446                 return NT_STATUS_OK;
2447         }
2448
2449         el = ldb_msg_find_element(res[0], "privilege");
2450         if (el == NULL || el->num_values == 0) {
2451                 return NT_STATUS_OK;
2452         }
2453
2454         privs->set = talloc_array(privs,
2455                                   struct lsa_LUIDAttribute, el->num_values);
2456         if (privs->set == NULL) {
2457                 return NT_STATUS_NO_MEMORY;
2458         }
2459
2460         j = 0;
2461         for (i=0;i<el->num_values;i++) {
2462                 int id = sec_privilege_id((const char *)el->values[i].data);
2463                 if (id == SEC_PRIV_INVALID) {
2464                         /* Perhaps an account right, not a privilege */
2465                         continue;
2466                 }
2467                 privs->set[j].attribute = 0;
2468                 privs->set[j].luid.low = id;
2469                 privs->set[j].luid.high = 0;
2470                 j++;
2471         }
2472
2473         privs->count = j;
2474
2475         return NT_STATUS_OK;
2476 }
2477
2478 /* 
2479   lsa_EnumAccountRights 
2480 */
2481 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
2482                                       TALLOC_CTX *mem_ctx,
2483                                       struct lsa_EnumAccountRights *r)
2484 {
2485         struct dcesrv_handle *h;
2486         struct lsa_policy_state *state;
2487         int ret;
2488         unsigned int i;
2489         struct ldb_message **res;
2490         const char * const attrs[] = { "privilege", NULL};
2491         const char *sidstr;
2492         struct ldb_message_element *el;
2493
2494         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2495
2496         state = h->data;
2497
2498         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2499         if (sidstr == NULL) {
2500                 return NT_STATUS_NO_MEMORY;
2501         }
2502
2503         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2504                            "(&(objectSid=%s)(privilege=*))", sidstr);
2505         if (ret == 0) {
2506                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2507         }
2508         if (ret != 1) {
2509                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
2510                           dom_sid_string(mem_ctx, r->in.sid),
2511                           ldb_errstring(state->pdb)));
2512                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2513         }
2514
2515         el = ldb_msg_find_element(res[0], "privilege");
2516         if (el == NULL || el->num_values == 0) {
2517                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2518         }
2519
2520         r->out.rights->count = el->num_values;
2521         r->out.rights->names = talloc_array(r->out.rights, 
2522                                             struct lsa_StringLarge, r->out.rights->count);
2523         if (r->out.rights->names == NULL) {
2524                 return NT_STATUS_NO_MEMORY;
2525         }
2526
2527         for (i=0;i<el->num_values;i++) {
2528                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2529         }
2530
2531         return NT_STATUS_OK;
2532 }
2533
2534
2535
2536 /* 
2537   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2538 */
2539 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
2540                                            TALLOC_CTX *mem_ctx,
2541                                            struct lsa_policy_state *state,
2542                                            int ldb_flag,
2543                                            struct dom_sid *sid,
2544                                            const struct lsa_RightSet *rights)
2545 {
2546         const char *sidstr, *sidndrstr;
2547         struct ldb_message *msg;
2548         struct ldb_message_element *el;
2549         int ret;
2550         uint32_t i;
2551         struct lsa_EnumAccountRights r2;
2552         char *dnstr;
2553
2554         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2555             SECURITY_ADMINISTRATOR) {
2556                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2557                 return NT_STATUS_ACCESS_DENIED;
2558         }
2559
2560         msg = ldb_msg_new(mem_ctx);
2561         if (msg == NULL) {
2562                 return NT_STATUS_NO_MEMORY;
2563         }
2564
2565         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2566         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2567
2568         sidstr = dom_sid_string(msg, sid);
2569         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2570
2571         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2572         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2573
2574         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2575         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2576
2577         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2578                 NTSTATUS status;
2579
2580                 r2.in.handle = &state->handle->wire_handle;
2581                 r2.in.sid = sid;
2582                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2583
2584                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2585                 if (!NT_STATUS_IS_OK(status)) {
2586                         ZERO_STRUCTP(r2.out.rights);
2587                 }
2588         }
2589
2590         for (i=0;i<rights->count;i++) {
2591                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2592                         if (sec_right_bit(rights->names[i].string) == 0) {
2593                                 talloc_free(msg);
2594                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2595                         }
2596
2597                         talloc_free(msg);
2598                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2599                 }
2600
2601                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2602                         uint32_t j;
2603                         for (j=0;j<r2.out.rights->count;j++) {
2604                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
2605                                                rights->names[i].string) == 0) {
2606                                         break;
2607                                 }
2608                         }
2609                         if (j != r2.out.rights->count) continue;
2610                 }
2611
2612                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2613                 if (ret != LDB_SUCCESS) {
2614                         talloc_free(msg);
2615                         return NT_STATUS_NO_MEMORY;
2616                 }
2617         }
2618
2619         el = ldb_msg_find_element(msg, "privilege");
2620         if (!el) {
2621                 talloc_free(msg);
2622                 return NT_STATUS_OK;
2623         }
2624
2625         el->flags = ldb_flag;
2626
2627         ret = ldb_modify(state->pdb, msg);
2628         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2629                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2630                         talloc_free(msg);
2631                         return NT_STATUS_NO_MEMORY;
2632                 }
2633                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2634                 ret = ldb_add(state->pdb, msg);         
2635         }
2636         if (ret != LDB_SUCCESS) {
2637                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2638                         talloc_free(msg);
2639                         return NT_STATUS_OK;
2640                 }
2641                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2642                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2643                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2644                 talloc_free(msg);
2645                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2646         }
2647
2648         talloc_free(msg);
2649         return NT_STATUS_OK;
2650 }
2651
2652 /* 
2653   lsa_AddPrivilegesToAccount
2654 */
2655 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2656                                            struct lsa_AddPrivilegesToAccount *r)
2657 {
2658         struct lsa_RightSet rights;
2659         struct dcesrv_handle *h;
2660         struct lsa_account_state *astate;
2661         uint32_t i;
2662
2663         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2664
2665         astate = h->data;
2666
2667         rights.count = r->in.privs->count;
2668         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2669         if (rights.names == NULL) {
2670                 return NT_STATUS_NO_MEMORY;
2671         }
2672         for (i=0;i<rights.count;i++) {
2673                 int id = r->in.privs->set[i].luid.low;
2674                 if (r->in.privs->set[i].luid.high) {
2675                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2676                 }
2677                 rights.names[i].string = sec_privilege_name(id);
2678                 if (rights.names[i].string == NULL) {
2679                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2680                 }
2681         }
2682
2683         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2684                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2685                                           &rights);
2686 }
2687
2688
2689 /* 
2690   lsa_RemovePrivilegesFromAccount
2691 */
2692 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2693                                                 struct lsa_RemovePrivilegesFromAccount *r)
2694 {
2695         struct lsa_RightSet *rights;
2696         struct dcesrv_handle *h;
2697         struct lsa_account_state *astate;
2698         uint32_t i;
2699
2700         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2701
2702         astate = h->data;
2703
2704         rights = talloc(mem_ctx, struct lsa_RightSet);
2705
2706         if (r->in.remove_all == 1 && 
2707             r->in.privs == NULL) {
2708                 struct lsa_EnumAccountRights r2;
2709                 NTSTATUS status;
2710
2711                 r2.in.handle = &astate->policy->handle->wire_handle;
2712                 r2.in.sid = astate->account_sid;
2713                 r2.out.rights = rights;
2714
2715                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2716                 if (!NT_STATUS_IS_OK(status)) {
2717                         return status;
2718                 }
2719
2720                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2721                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2722                                                   r2.out.rights);
2723         }
2724
2725         if (r->in.remove_all != 0) {
2726                 return NT_STATUS_INVALID_PARAMETER;
2727         }
2728
2729         rights->count = r->in.privs->count;
2730         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2731         if (rights->names == NULL) {
2732                 return NT_STATUS_NO_MEMORY;
2733         }
2734         for (i=0;i<rights->count;i++) {
2735                 int id = r->in.privs->set[i].luid.low;
2736                 if (r->in.privs->set[i].luid.high) {
2737                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2738                 }
2739                 rights->names[i].string = sec_privilege_name(id);
2740                 if (rights->names[i].string == NULL) {
2741                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2742                 }
2743         }
2744
2745         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2746                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2747                                           rights);
2748 }
2749
2750
2751 /* 
2752   lsa_GetQuotasForAccount
2753 */
2754 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2755                        struct lsa_GetQuotasForAccount *r)
2756 {
2757         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2758 }
2759
2760
2761 /* 
2762   lsa_SetQuotasForAccount
2763 */
2764 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2765                        struct lsa_SetQuotasForAccount *r)
2766 {
2767         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2768 }
2769
2770
2771 /* 
2772   lsa_GetSystemAccessAccount
2773 */
2774 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2775                        struct lsa_GetSystemAccessAccount *r)
2776 {
2777         struct dcesrv_handle *h;
2778         struct lsa_account_state *astate;
2779         int ret;
2780         unsigned int i;
2781         struct ldb_message **res;
2782         const char * const attrs[] = { "privilege", NULL};
2783         struct ldb_message_element *el;
2784         const char *sidstr;
2785
2786         *(r->out.access_mask) = 0x00000000;
2787
2788         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2789
2790         astate = h->data;
2791
2792         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2793         if (sidstr == NULL) {
2794                 return NT_STATUS_NO_MEMORY;
2795         }
2796
2797         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
2798                            "objectSid=%s", sidstr);
2799         if (ret < 0) {
2800                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2801         }
2802         if (ret != 1) {
2803                 return NT_STATUS_OK;
2804         }
2805
2806         el = ldb_msg_find_element(res[0], "privilege");
2807         if (el == NULL || el->num_values == 0) {
2808                 return NT_STATUS_OK;
2809         }
2810
2811         for (i=0;i<el->num_values;i++) {
2812                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2813                 if (right_bit == 0) {
2814                         /* Perhaps an privilege, not a right */
2815                         continue;
2816                 }
2817                 *(r->out.access_mask) |= right_bit;
2818         }
2819
2820         return NT_STATUS_OK;
2821 }
2822
2823
2824 /* 
2825   lsa_SetSystemAccessAccount
2826 */
2827 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2828                        struct lsa_SetSystemAccessAccount *r)
2829 {
2830         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2831 }
2832
2833
2834 /* 
2835   lsa_CreateSecret 
2836 */
2837 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2838                                  struct lsa_CreateSecret *r)
2839 {
2840         struct dcesrv_handle *policy_handle;
2841         struct lsa_policy_state *policy_state;
2842         struct lsa_secret_state *secret_state;
2843         struct dcesrv_handle *handle;
2844         struct ldb_message **msgs, *msg;
2845         const char *attrs[] = {
2846                 NULL
2847         };
2848
2849         const char *name;
2850
2851         int ret;
2852
2853         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2854         ZERO_STRUCTP(r->out.sec_handle);
2855         
2856         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2857         {
2858         case SECURITY_SYSTEM:
2859         case SECURITY_ADMINISTRATOR:
2860                 break;
2861         default:
2862                 /* Users and annonymous are not allowed create secrets */
2863                 return NT_STATUS_ACCESS_DENIED;
2864         }
2865
2866         policy_state = policy_handle->data;
2867
2868         if (!r->in.name.string) {
2869                 return NT_STATUS_INVALID_PARAMETER;
2870         }
2871         
2872         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2873         NT_STATUS_HAVE_NO_MEMORY(secret_state);
2874         secret_state->policy = policy_state;
2875
2876         msg = ldb_msg_new(mem_ctx);
2877         if (msg == NULL) {
2878                 return NT_STATUS_NO_MEMORY;
2879         }
2880
2881         if (strncmp("G$", r->in.name.string, 2) == 0) {
2882                 const char *name2;
2883
2884                 secret_state->global = true;
2885
2886                 name = &r->in.name.string[2];
2887                 if (strlen(name) == 0) {
2888                         return NT_STATUS_INVALID_PARAMETER;
2889                 }
2890
2891                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2892                                         ldb_binary_encode_string(mem_ctx, name));
2893                 NT_STATUS_HAVE_NO_MEMORY(name2);
2894
2895                 /* We need to connect to the database as system, as this is one
2896                  * of the rare RPC calls that must read the secrets (and this
2897                  * is denied otherwise) */
2898                 secret_state->sam_ldb = talloc_reference(secret_state,
2899                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
2900                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2901
2902                 /* search for the secret record */
2903                 ret = gendb_search(secret_state->sam_ldb,
2904                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2905                                    "(&(cn=%s)(objectclass=secret))", 
2906                                    name2);
2907                 if (ret > 0) {
2908                         return NT_STATUS_OBJECT_NAME_COLLISION;
2909                 }
2910                 
2911                 if (ret < 0) {
2912                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2913                                  name2, ldb_errstring(secret_state->sam_ldb)));
2914                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2915                 }
2916
2917                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2918                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2919                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2920                         return NT_STATUS_NO_MEMORY;
2921                 }
2922
2923                 ret = ldb_msg_add_string(msg, "cn", name2);
2924                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2925         } else {
2926                 secret_state->global = false;
2927
2928                 name = r->in.name.string;
2929                 if (strlen(name) == 0) {
2930                         return NT_STATUS_INVALID_PARAMETER;
2931                 }
2932
2933                 secret_state->sam_ldb = talloc_reference(secret_state, 
2934                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2935                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2936
2937                 /* search for the secret record */
2938                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2939                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2940                                    &msgs, attrs,
2941                                    "(&(cn=%s)(objectclass=secret))", 
2942                                    ldb_binary_encode_string(mem_ctx, name));
2943                 if (ret > 0) {
2944                         return NT_STATUS_OBJECT_NAME_COLLISION;
2945                 }
2946                 
2947                 if (ret < 0) {
2948                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2949                                  name, ldb_errstring(secret_state->sam_ldb)));
2950                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2951                 }
2952
2953                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2954                                          "cn=%s,cn=LSA Secrets", name);
2955                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2956                 ret = ldb_msg_add_string(msg, "cn", name);
2957                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2958         } 
2959
2960         ret = samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg,
2961                                    "objectClass", "secret");
2962         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2963         
2964         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2965         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2966
2967         /* create the secret */
2968         ret = ldb_add(secret_state->sam_ldb, msg);
2969         if (ret != LDB_SUCCESS) {
2970                 DEBUG(0,("Failed to create secret record %s: %s\n",
2971                          ldb_dn_get_linearized(msg->dn), 
2972                          ldb_errstring(secret_state->sam_ldb)));
2973                 return NT_STATUS_ACCESS_DENIED;
2974         }
2975
2976         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2977         NT_STATUS_HAVE_NO_MEMORY(handle);
2978
2979         handle->data = talloc_steal(handle, secret_state);
2980         
2981         secret_state->access_mask = r->in.access_mask;
2982         secret_state->policy = talloc_reference(secret_state, policy_state);
2983         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2984         
2985         *r->out.sec_handle = handle->wire_handle;
2986         
2987         return NT_STATUS_OK;
2988 }
2989
2990
2991 /* 
2992   lsa_OpenSecret 
2993 */
2994 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2995                                struct lsa_OpenSecret *r)
2996 {
2997         struct dcesrv_handle *policy_handle;
2998         
2999         struct lsa_policy_state *policy_state;
3000         struct lsa_secret_state *secret_state;
3001         struct dcesrv_handle *handle;
3002         struct ldb_message **msgs;
3003         const char *attrs[] = {
3004                 NULL
3005         };
3006
3007         const char *name;
3008
3009         int ret;
3010
3011         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3012         ZERO_STRUCTP(r->out.sec_handle);
3013         policy_state = policy_handle->data;
3014
3015         if (!r->in.name.string) {
3016                 return NT_STATUS_INVALID_PARAMETER;
3017         }
3018         
3019         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3020         {
3021         case SECURITY_SYSTEM:
3022         case SECURITY_ADMINISTRATOR:
3023                 break;
3024         default:
3025                 /* Users and annonymous are not allowed to access secrets */
3026                 return NT_STATUS_ACCESS_DENIED;
3027         }
3028
3029         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3030         if (!secret_state) {
3031                 return NT_STATUS_NO_MEMORY;
3032         }
3033         secret_state->policy = policy_state;
3034
3035         if (strncmp("G$", r->in.name.string, 2) == 0) {
3036                 name = &r->in.name.string[2];
3037                 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
3038                 secret_state->sam_ldb = talloc_reference(secret_state, 
3039                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
3040                 secret_state->global = true;
3041
3042                 if (strlen(name) < 1) {
3043                         return NT_STATUS_INVALID_PARAMETER;
3044                 }
3045
3046                 /* search for the secret record */
3047                 ret = gendb_search(secret_state->sam_ldb,
3048                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3049                                    "(&(cn=%s Secret)(objectclass=secret))", 
3050                                    ldb_binary_encode_string(mem_ctx, name));
3051                 if (ret == 0) {
3052                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3053                 }
3054                 
3055                 if (ret != 1) {
3056                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3057                                  ldb_dn_get_linearized(policy_state->system_dn)));
3058                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3059                 }
3060         
3061         } else {
3062                 secret_state->global = false;
3063                 secret_state->sam_ldb = talloc_reference(secret_state, 
3064                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3065
3066                 name = r->in.name.string;
3067                 if (strlen(name) < 1) {
3068                         return NT_STATUS_INVALID_PARAMETER;
3069                 }
3070
3071                 /* search for the secret record */
3072                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3073                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3074                                    &msgs, attrs,
3075                                    "(&(cn=%s)(objectclass=secret))", 
3076                                    ldb_binary_encode_string(mem_ctx, name));
3077                 if (ret == 0) {
3078                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3079                 }
3080                 
3081                 if (ret != 1) {
3082                         DEBUG(0,("Found %d records matching CN=%s\n", 
3083                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3084                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3085                 }
3086         } 
3087
3088         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3089         
3090         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3091         if (!handle) {
3092                 return NT_STATUS_NO_MEMORY;
3093         }
3094         
3095         handle->data = talloc_steal(handle, secret_state);
3096         
3097         secret_state->access_mask = r->in.access_mask;
3098         secret_state->policy = talloc_reference(secret_state, policy_state);
3099         
3100         *r->out.sec_handle = handle->wire_handle;
3101         
3102         return NT_STATUS_OK;
3103 }
3104
3105
3106 /* 
3107   lsa_SetSecret 
3108 */
3109 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3110                               struct lsa_SetSecret *r)
3111 {
3112
3113         struct dcesrv_handle *h;
3114         struct lsa_secret_state *secret_state;
3115         struct ldb_message *msg;
3116         DATA_BLOB session_key;
3117         DATA_BLOB crypt_secret, secret;
3118         struct ldb_val val;
3119         int ret;
3120         NTSTATUS status = NT_STATUS_OK;
3121
3122         struct timeval now = timeval_current();
3123         NTTIME nt_now = timeval_to_nttime(&now);
3124
3125         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3126
3127         secret_state = h->data;
3128
3129         msg = ldb_msg_new(mem_ctx);
3130         if (msg == NULL) {
3131                 return NT_STATUS_NO_MEMORY;
3132         }
3133
3134         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3135         if (!msg->dn) {
3136                 return NT_STATUS_NO_MEMORY;
3137         }
3138         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3139         if (!NT_STATUS_IS_OK(status)) {
3140                 return status;
3141         }
3142
3143         if (r->in.old_val) {
3144                 /* Decrypt */
3145                 crypt_secret.data = r->in.old_val->data;
3146                 crypt_secret.length = r->in.old_val->size;
3147                 
3148                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3149                 if (!NT_STATUS_IS_OK(status)) {
3150                         return status;
3151                 }
3152                 
3153                 val.data = secret.data;
3154                 val.length = secret.length;
3155                 
3156                 /* set value */
3157                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3158                         return NT_STATUS_NO_MEMORY; 
3159                 }
3160                 
3161                 /* set old value mtime */
3162                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3163                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3164                         return NT_STATUS_NO_MEMORY; 
3165                 }
3166
3167         } else {
3168                 /* If the old value is not set, then migrate the
3169                  * current value to the old value */
3170                 const struct ldb_val *old_val;
3171                 NTTIME last_set_time;
3172                 struct ldb_message **res;
3173                 const char *attrs[] = {
3174                         "currentValue",
3175                         "lastSetTime",
3176                         NULL
3177                 };
3178                 
3179                 /* search for the secret record */
3180                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3181                                       secret_state->secret_dn, &res, attrs);
3182                 if (ret == 0) {
3183                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3184                 }
3185                 
3186                 if (ret != 1) {
3187                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3188                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3189                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3190                 }
3191                 
3192                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3193                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3194                 
3195                 if (old_val) {
3196                         /* set old value */
3197                         if (ldb_msg_add_value(msg, "priorValue",
3198                                               old_val, NULL) != LDB_SUCCESS) {
3199                                 return NT_STATUS_NO_MEMORY; 
3200                         }
3201                 } else {
3202                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
3203                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3204                                 return NT_STATUS_NO_MEMORY;
3205                         }
3206                         
3207                 }
3208                 
3209                 /* set old value mtime */
3210                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3211                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3212                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3213                                 return NT_STATUS_NO_MEMORY; 
3214                         }
3215                 } else {
3216                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3217                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3218                                 return NT_STATUS_NO_MEMORY; 
3219                         }
3220                 }
3221         }
3222
3223         if (r->in.new_val) {
3224                 /* Decrypt */
3225                 crypt_secret.data = r->in.new_val->data;
3226                 crypt_secret.length = r->in.new_val->size;
3227                 
3228                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3229                 if (!NT_STATUS_IS_OK(status)) {
3230                         return status;
3231                 }
3232                 
3233                 val.data = secret.data;
3234                 val.length = secret.length;
3235                 
3236                 /* set value */
3237                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3238                         return NT_STATUS_NO_MEMORY; 
3239                 }
3240                 
3241                 /* set new value mtime */
3242                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3243                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3244                         return NT_STATUS_NO_MEMORY; 
3245                 }
3246                 
3247         } else {
3248                 /* NULL out the NEW value */
3249                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3250                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3251                         return NT_STATUS_NO_MEMORY; 
3252                 }
3253                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
3254                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3255                         return NT_STATUS_NO_MEMORY;
3256                 }
3257         }
3258
3259         /* modify the samdb record */
3260         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3261         if (ret != LDB_SUCCESS) {
3262                 /* we really need samdb.c to return NTSTATUS */
3263                 return NT_STATUS_UNSUCCESSFUL;
3264         }
3265
3266         return NT_STATUS_OK;
3267 }
3268
3269
3270 /* 
3271   lsa_QuerySecret 
3272 */
3273 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3274                                 struct lsa_QuerySecret *r)
3275 {
3276         struct dcesrv_handle *h;
3277         struct lsa_secret_state *secret_state;
3278         struct ldb_message *msg;
3279         DATA_BLOB session_key;
3280         DATA_BLOB crypt_secret, secret;
3281         int ret;
3282         struct ldb_message **res;
3283         const char *attrs[] = {
3284                 "currentValue",
3285                 "priorValue",
3286                 "lastSetTime",
3287                 "priorSetTime", 
3288                 NULL
3289         };
3290
3291         NTSTATUS nt_status;
3292
3293         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3294
3295         /* Ensure user is permitted to read this... */
3296         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3297         {
3298         case SECURITY_SYSTEM:
3299         case SECURITY_ADMINISTRATOR:
3300                 break;
3301         default:
3302                 /* Users and annonymous are not allowed to read secrets */
3303                 return NT_STATUS_ACCESS_DENIED;
3304         }
3305
3306         secret_state = h->data;
3307
3308         /* pull all the user attributes */
3309         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3310                               secret_state->secret_dn, &res, attrs);
3311         if (ret != 1) {
3312                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3313         }
3314         msg = res[0];
3315         
3316         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3317         if (!NT_STATUS_IS_OK(nt_status)) {
3318                 return nt_status;
3319         }
3320         
3321         if (r->in.old_val) {
3322                 const struct ldb_val *prior_val;
3323                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3324                 if (!r->out.old_val) {
3325                         return NT_STATUS_NO_MEMORY;
3326                 }
3327                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3328                 
3329                 if (prior_val && prior_val->length) {
3330                         secret.data = prior_val->data;
3331                         secret.length = prior_val->length;
3332                 
3333                         /* Encrypt */
3334                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3335                         if (!crypt_secret.length) {
3336                                 return NT_STATUS_NO_MEMORY;
3337                         }
3338                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3339                         if (!r->out.old_val->buf) {
3340                                 return NT_STATUS_NO_MEMORY;
3341                         }
3342                         r->out.old_val->buf->size = crypt_secret.length;
3343                         r->out.old_val->buf->length = crypt_secret.length;
3344                         r->out.old_val->buf->data = crypt_secret.data;
3345                 }
3346         }
3347         
3348         if (r->in.old_mtime) {
3349                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3350                 if (!r->out.old_mtime) {
3351                         return NT_STATUS_NO_MEMORY;
3352                 }
3353                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3354         }
3355         
3356         if (r->in.new_val) {
3357                 const struct ldb_val *new_val;
3358                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3359                 if (!r->out.new_val) {
3360                         return NT_STATUS_NO_MEMORY;
3361                 }
3362
3363                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3364                 
3365                 if (new_val && new_val->length) {
3366                         secret.data = new_val->data;
3367                         secret.length = new_val->length;
3368                 
3369                         /* Encrypt */
3370                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3371                         if (!crypt_secret.length) {
3372                                 return NT_STATUS_NO_MEMORY;
3373                         }
3374                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3375                         if (!r->out.new_val->buf) {
3376                                 return NT_STATUS_NO_MEMORY;
3377                         }
3378                         r->out.new_val->buf->length = crypt_secret.length;
3379                         r->out.new_val->buf->size = crypt_secret.length;
3380                         r->out.new_val->buf->data = crypt_secret.data;
3381                 }
3382         }
3383         
3384         if (r->in.new_mtime) {
3385                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3386                 if (!r->out.new_mtime) {
3387                         return NT_STATUS_NO_MEMORY;
3388                 }
3389                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3390         }
3391         
3392         return NT_STATUS_OK;
3393 }
3394
3395
3396 /* 
3397   lsa_LookupPrivValue
3398 */
3399 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
3400                                     TALLOC_CTX *mem_ctx,
3401                                     struct lsa_LookupPrivValue *r)
3402 {
3403         struct dcesrv_handle *h;
3404         struct lsa_policy_state *state;
3405         int id;
3406
3407         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3408
3409         state = h->data;
3410
3411         id = sec_privilege_id(r->in.name->string);
3412         if (id == SEC_PRIV_INVALID) {
3413                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3414         }
3415
3416         r->out.luid->low = id;
3417         r->out.luid->high = 0;
3418
3419         return NT_STATUS_OK;    
3420 }
3421
3422
3423 /* 
3424   lsa_LookupPrivName 
3425 */
3426 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
3427                                    TALLOC_CTX *mem_ctx,
3428                                    struct lsa_LookupPrivName *r)
3429 {
3430         struct dcesrv_handle *h;
3431         struct lsa_policy_state *state;
3432         struct lsa_StringLarge *name;
3433         const char *privname;
3434
3435         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3436
3437         state = h->data;
3438
3439         if (r->in.luid->high != 0) {
3440                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3441         }
3442
3443         privname = sec_privilege_name(r->in.luid->low);
3444         if (privname == NULL) {
3445                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3446         }
3447
3448         name = talloc(mem_ctx, struct lsa_StringLarge);
3449         if (name == NULL) {
3450                 return NT_STATUS_NO_MEMORY;
3451         }
3452
3453         name->string = privname;
3454
3455         *r->out.name = name;
3456
3457         return NT_STATUS_OK;    
3458 }
3459
3460
3461 /* 
3462   lsa_LookupPrivDisplayName
3463 */
3464 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
3465                                           TALLOC_CTX *mem_ctx,
3466                                           struct lsa_LookupPrivDisplayName *r)
3467 {
3468         struct dcesrv_handle *h;
3469         struct lsa_policy_state *state;
3470         struct lsa_StringLarge *disp_name = NULL;
3471         enum sec_privilege id;
3472
3473         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3474
3475         state = h->data;
3476
3477         id = sec_privilege_id(r->in.name->string);
3478         if (id == SEC_PRIV_INVALID) {
3479                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3480         }
3481
3482         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3483         if (disp_name == NULL) {
3484                 return NT_STATUS_NO_MEMORY;
3485         }
3486
3487         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3488         if (disp_name->string == NULL) {
3489                 return NT_STATUS_INTERNAL_ERROR;
3490         }
3491
3492         *r->out.disp_name = disp_name;
3493         *r->out.returned_language_id = 0;
3494
3495         return NT_STATUS_OK;
3496 }
3497
3498
3499 /* 
3500   lsa_EnumAccountsWithUserRight
3501 */
3502 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
3503                                               TALLOC_CTX *mem_ctx,
3504                                               struct lsa_EnumAccountsWithUserRight *r)
3505 {
3506         struct dcesrv_handle *h;
3507         struct lsa_policy_state *state;
3508         int ret, i;
3509         struct ldb_message **res;
3510         const char * const attrs[] = { "objectSid", NULL};
3511         const char *privname;
3512
3513         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3514
3515         state = h->data;
3516
3517         if (r->in.name == NULL) {
3518                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3519         } 
3520
3521         privname = r->in.name->string;
3522         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3523                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3524         }
3525
3526         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
3527                            "privilege=%s", privname);
3528         if (ret < 0) {
3529                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3530         }
3531         if (ret == 0) {
3532                 return NT_STATUS_NO_MORE_ENTRIES;
3533         }
3534
3535         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3536         if (r->out.sids->sids == NULL) {
3537                 return NT_STATUS_NO_MEMORY;
3538         }
3539         for (i=0;i<ret;i++) {
3540                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3541                                                                 res[i], "objectSid");
3542                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3543         }
3544         r->out.sids->num_sids = ret;
3545
3546         return NT_STATUS_OK;
3547 }
3548
3549
3550 /* 
3551   lsa_AddAccountRights
3552 */
3553 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
3554                                      TALLOC_CTX *mem_ctx,
3555                                      struct lsa_AddAccountRights *r)
3556 {
3557         struct dcesrv_handle *h;
3558         struct lsa_policy_state *state;
3559
3560         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3561
3562         state = h->data;
3563
3564         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3565                                           LDB_FLAG_MOD_ADD,
3566                                           r->in.sid, r->in.rights);
3567 }
3568
3569
3570 /* 
3571   lsa_RemoveAccountRights
3572 */
3573 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
3574                                         TALLOC_CTX *mem_ctx,
3575                                         struct lsa_RemoveAccountRights *r)
3576 {
3577         struct dcesrv_handle *h;
3578         struct lsa_policy_state *state;
3579
3580         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3581
3582         state = h->data;
3583
3584         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3585                                           LDB_FLAG_MOD_DELETE,
3586                                           r->in.sid, r->in.rights);
3587 }
3588
3589
3590 /* 
3591   lsa_StorePrivateData
3592 */
3593 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3594                        struct lsa_StorePrivateData *r)
3595 {
3596         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3597 }
3598
3599
3600 /* 
3601   lsa_RetrievePrivateData
3602 */
3603 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3604                        struct lsa_RetrievePrivateData *r)
3605 {
3606         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3607 }
3608
3609
3610 /* 
3611   lsa_GetUserName
3612 */
3613 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3614                                 struct lsa_GetUserName *r)
3615 {
3616         NTSTATUS status = NT_STATUS_OK;
3617         const char *account_name;
3618         const char *authority_name;
3619         struct lsa_String *_account_name;
3620         struct lsa_String *_authority_name = NULL;
3621
3622         /* this is what w2k3 does */
3623         r->out.account_name = r->in.account_name;
3624         r->out.authority_name = r->in.authority_name;
3625
3626         if (r->in.account_name
3627             && *r->in.account_name
3628             /* && *(*r->in.account_name)->string */
3629             ) {
3630                 return NT_STATUS_INVALID_PARAMETER;
3631         }
3632
3633         if (r->in.authority_name
3634             && *r->in.authority_name
3635             /* && *(*r->in.authority_name)->string */
3636             ) {
3637                 return NT_STATUS_INVALID_PARAMETER;
3638         }
3639
3640         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3641         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3642
3643         _account_name = talloc(mem_ctx, struct lsa_String);
3644         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3645         _account_name->string = account_name;
3646
3647         if (r->in.authority_name) {
3648                 _authority_name = talloc(mem_ctx, struct lsa_String);
3649                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3650                 _authority_name->string = authority_name;
3651         }
3652
3653         *r->out.account_name = _account_name;
3654         if (r->out.authority_name) {
3655                 *r->out.authority_name = _authority_name;
3656         }
3657
3658         return status;
3659 }
3660
3661 /*
3662   lsa_SetInfoPolicy2
3663 */
3664 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3665                                    TALLOC_CTX *mem_ctx,
3666                                    struct lsa_SetInfoPolicy2 *r)
3667 {
3668         /* need to support these */
3669         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3670 }
3671
3672 /*
3673   lsa_QueryDomainInformationPolicy
3674 */
3675 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3676                                                  TALLOC_CTX *mem_ctx,
3677                                                  struct lsa_QueryDomainInformationPolicy *r)
3678 {
3679         union lsa_DomainInformationPolicy *info;
3680
3681         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3682         if (!info) {
3683                 return NT_STATUS_NO_MEMORY;
3684         }
3685
3686         switch (r->in.level) {
3687         case LSA_DOMAIN_INFO_POLICY_EFS:
3688                 talloc_free(info);
3689                 *r->out.info = NULL;
3690                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3691         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3692         {
3693                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3694                 struct smb_krb5_context *smb_krb5_context;
3695                 int ret = smb_krb5_init_context(mem_ctx, 
3696                                                         dce_call->event_ctx, 
3697                                                         dce_call->conn->dce_ctx->lp_ctx,
3698                                                         &smb_krb5_context);
3699                 if (ret != 0) {
3700                         talloc_free(info);
3701                         *r->out.info = NULL;
3702                         return NT_STATUS_INTERNAL_ERROR;
3703                 }
3704                 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3705                                smb_krb5_context,
3706                                k);
3707                 talloc_free(smb_krb5_context);
3708                 *r->out.info = info;
3709                 return NT_STATUS_OK;
3710         }
3711         default:
3712                 talloc_free(info);
3713                 *r->out.info = NULL;
3714                 return NT_STATUS_INVALID_INFO_CLASS;
3715         }
3716 }
3717
3718 /*
3719   lsa_SetDomInfoPolicy
3720 */
3721 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3722                                               TALLOC_CTX *mem_ctx,
3723                                               struct lsa_SetDomainInformationPolicy *r)
3724 {
3725         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3726 }
3727
3728 /*
3729   lsa_TestCall
3730 */
3731 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3732                              TALLOC_CTX *mem_ctx,
3733                              struct lsa_TestCall *r)
3734 {
3735         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3736 }
3737
3738 /* 
3739   lsa_CREDRWRITE 
3740 */
3741 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3742                        struct lsa_CREDRWRITE *r)
3743 {
3744         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3745 }
3746
3747
3748 /* 
3749   lsa_CREDRREAD 
3750 */
3751 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3752                        struct lsa_CREDRREAD *r)
3753 {
3754         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3755 }
3756
3757
3758 /* 
3759   lsa_CREDRENUMERATE 
3760 */
3761 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3762                        struct lsa_CREDRENUMERATE *r)
3763 {
3764         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3765 }
3766
3767
3768 /* 
3769   lsa_CREDRWRITEDOMAINCREDENTIALS 
3770 */
3771 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3772                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3773 {
3774         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3775 }
3776
3777
3778 /* 
3779   lsa_CREDRREADDOMAINCREDENTIALS 
3780 */
3781 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3782                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3783 {
3784         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3785 }
3786
3787
3788 /* 
3789   lsa_CREDRDELETE 
3790 */
3791 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3792                        struct lsa_CREDRDELETE *r)
3793 {
3794         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3795 }
3796
3797
3798 /* 
3799   lsa_CREDRGETTARGETINFO 
3800 */
3801 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3802                        struct lsa_CREDRGETTARGETINFO *r)
3803 {
3804         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3805 }
3806
3807
3808 /* 
3809   lsa_CREDRPROFILELOADED 
3810 */
3811 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3812                        struct lsa_CREDRPROFILELOADED *r)
3813 {
3814         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3815 }
3816
3817
3818 /* 
3819   lsa_CREDRGETSESSIONTYPES 
3820 */
3821 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3822                        struct lsa_CREDRGETSESSIONTYPES *r)
3823 {
3824         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3825 }
3826
3827
3828 /* 
3829   lsa_LSARREGISTERAUDITEVENT 
3830 */
3831 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3832                        struct lsa_LSARREGISTERAUDITEVENT *r)
3833 {
3834         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3835 }
3836
3837
3838 /* 
3839   lsa_LSARGENAUDITEVENT 
3840 */
3841 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3842                        struct lsa_LSARGENAUDITEVENT *r)
3843 {
3844         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3845 }
3846
3847
3848 /* 
3849   lsa_LSARUNREGISTERAUDITEVENT 
3850 */
3851 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3852                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3853 {
3854         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3855 }
3856
3857
3858 /* 
3859   lsa_lsaRQueryForestTrustInformation 
3860 */
3861 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3862                        struct lsa_lsaRQueryForestTrustInformation *r)
3863 {
3864         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3865 }
3866
3867 #define DNS_CMP_MATCH 0
3868 #define DNS_CMP_FIRST_IS_CHILD 1
3869 #define DNS_CMP_SECOND_IS_CHILD 2
3870 #define DNS_CMP_NO_MATCH 3
3871
3872 /* this function assumes names are well formed DNS names.
3873  * it doesn't validate them */
3874 static int dns_cmp(const char *s1, size_t l1,
3875                    const char *s2, size_t l2)
3876 {
3877         const char *p1, *p2;
3878         size_t t1, t2;
3879         int cret;
3880
3881         if (l1 == l2) {
3882                 if (strcasecmp_m(s1, s2) == 0) {
3883                         return DNS_CMP_MATCH;
3884                 }
3885                 return DNS_CMP_NO_MATCH;
3886         }
3887
3888         if (l1 > l2) {
3889                 p1 = s1;
3890                 p2 = s2;
3891                 t1 = l1;
3892                 t2 = l2;
3893                 cret = DNS_CMP_FIRST_IS_CHILD;
3894         } else {
3895                 p1 = s2;
3896                 p2 = s1;
3897                 t1 = l2;
3898                 t2 = l1;
3899                 cret = DNS_CMP_SECOND_IS_CHILD;
3900         }
3901
3902         if (p1[t1 - t2 - 1] != '.') {
3903                 return DNS_CMP_NO_MATCH;
3904         }
3905
3906         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3907                 return cret;
3908         }
3909
3910         return DNS_CMP_NO_MATCH;
3911 }
3912
3913 /* decode all TDOs forest trust info blobs */
3914 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3915                             struct ldb_message *msg,
3916                             struct ForestTrustInfo *info)
3917 {
3918         const struct ldb_val *ft_blob;
3919         enum ndr_err_code ndr_err;
3920
3921         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3922         if (!ft_blob || !ft_blob->data) {
3923                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3924         }
3925         /* ldb_val is equivalent to DATA_BLOB */
3926         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3927                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3928         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3929                 return NT_STATUS_INVALID_DOMAIN_STATE;
3930         }
3931
3932         return NT_STATUS_OK;
3933 }
3934
3935 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3936                             struct ForestTrustInfo *fti)
3937 {
3938         struct ForestTrustDataDomainInfo *info;
3939         struct ForestTrustInfoRecord *rec;
3940
3941         fti->version = 1;
3942         fti->count = 2;
3943         fti->records = talloc_array(fti,
3944                                     struct ForestTrustInfoRecordArmor, 2);
3945         if (!fti->records) {
3946                 return NT_STATUS_NO_MEMORY;
3947         }
3948
3949         /* TLN info */
3950         rec = &fti->records[0].record;
3951
3952         rec->flags = 0;
3953         rec->timestamp = 0;
3954         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3955
3956         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3957         if (!rec->data.name.string) {
3958                 return NT_STATUS_NO_MEMORY;
3959         }
3960         rec->data.name.size = strlen(rec->data.name.string);
3961
3962         /* DOMAIN info */
3963         rec = &fti->records[1].record;
3964
3965         rec->flags = 0;
3966         rec->timestamp = 0;
3967         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3968
3969         info = &rec->data.info;
3970
3971         info->sid = *ps->domain_sid;
3972         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3973         if (!info->dns_name.string) {
3974                 return NT_STATUS_NO_MEMORY;
3975         }
3976         info->dns_name.size = strlen(info->dns_name.string);
3977         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3978         if (!info->netbios_name.string) {
3979                 return NT_STATUS_NO_MEMORY;
3980         }
3981         info->netbios_name.size = strlen(info->netbios_name.string);
3982
3983         return NT_STATUS_OK;
3984 }
3985
3986 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3987                              struct lsa_ForestTrustInformation *lfti,
3988                              struct ForestTrustInfo *fti)
3989 {
3990         struct lsa_ForestTrustRecord *lrec;
3991         struct ForestTrustInfoRecord *rec;
3992         struct lsa_StringLarge *tln;
3993         struct lsa_ForestTrustDomainInfo *info;
3994         uint32_t i;
3995
3996         fti->version = 1;
3997         fti->count = lfti->count;
3998         fti->records = talloc_array(mem_ctx,
3999                                     struct ForestTrustInfoRecordArmor,
4000                                     fti->count);
4001         if (!fti->records) {
4002                 return NT_STATUS_NO_MEMORY;
4003         }
4004         for (i = 0; i < fti->count; i++) {
4005                 lrec = lfti->entries[i];
4006                 rec = &fti->records[i].record;
4007
4008                 rec->flags = lrec->flags;
4009                 rec->timestamp = lrec->time;
4010                 rec->type = lrec->type;
4011
4012                 switch (lrec->type) {
4013                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4014                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4015                         tln = &lrec->forest_trust_data.top_level_name;
4016                         rec->data.name.string =
4017                                 talloc_strdup(mem_ctx, tln->string);
4018                         if (!rec->data.name.string) {
4019                                 return NT_STATUS_NO_MEMORY;
4020                         }
4021                         rec->data.name.size = strlen(rec->data.name.string);
4022                         break;
4023                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4024                         info = &lrec->forest_trust_data.domain_info;
4025                         rec->data.info.sid = *info->domain_sid;
4026                         rec->data.info.dns_name.string =
4027                                 talloc_strdup(mem_ctx,
4028                                             info->dns_domain_name.string);
4029                         if (!rec->data.info.dns_name.string) {
4030                                 return NT_STATUS_NO_MEMORY;
4031                         }
4032                         rec->data.info.dns_name.size =
4033                                 strlen(rec->data.info.dns_name.string);
4034                         rec->data.info.netbios_name.string =
4035                                 talloc_strdup(mem_ctx,
4036                                             info->netbios_domain_name.string);
4037                         if (!rec->data.info.netbios_name.string) {
4038                                 return NT_STATUS_NO_MEMORY;
4039                         }
4040                         rec->data.info.netbios_name.size =
4041                                 strlen(rec->data.info.netbios_name.string);
4042                         break;
4043                 default:
4044                         return NT_STATUS_INVALID_DOMAIN_STATE;
4045                 }
4046         }
4047
4048         return NT_STATUS_OK;
4049 }
4050
4051 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4052                               uint32_t idx, uint32_t collision_type,
4053                               uint32_t conflict_type, const char *tdo_name);
4054
4055 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4056                               const char *tdo_name,
4057                               struct ForestTrustInfo *tdo_fti,
4058                               struct ForestTrustInfo *new_fti,
4059                               struct lsa_ForestTrustCollisionInfo *c_info)
4060 {
4061         struct ForestTrustInfoRecord *nrec;
4062         struct ForestTrustInfoRecord *trec;
4063         const char *dns_name;
4064         const char *nb_name;
4065         struct dom_sid *sid;
4066         const char *tname;
4067         size_t dns_len;
4068         size_t nb_len;
4069         size_t tlen;
4070         NTSTATUS nt_status;
4071         uint32_t new_fti_idx;
4072         uint32_t i;
4073         /* use always TDO type, until we understand when Xref can be used */
4074         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4075         bool tln_conflict;
4076         bool sid_conflict;
4077         bool nb_conflict;
4078         bool exclusion;
4079         bool ex_rule;
4080         int ret;
4081
4082         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4083
4084                 nrec = &new_fti->records[new_fti_idx].record;
4085                 dns_name = NULL;
4086                 tln_conflict = false;
4087                 sid_conflict = false;
4088                 nb_conflict = false;
4089                 exclusion = false;
4090
4091                 switch (nrec->type) {
4092                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4093                         /* exclusions do not conflict by definition */
4094                         break;
4095
4096                 case FOREST_TRUST_TOP_LEVEL_NAME:
4097                         dns_name = nrec->data.name.string;
4098                         dns_len = nrec->data.name.size;
4099                         break;
4100
4101                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4102                         dns_name = nrec->data.info.dns_name.string;
4103                         dns_len = nrec->data.info.dns_name.size;
4104                         nb_name = nrec->data.info.netbios_name.string;
4105                         nb_len = nrec->data.info.netbios_name.size;
4106                         sid = &nrec->data.info.sid;
4107                         break;
4108                 }
4109
4110                 if (!dns_name) continue;
4111
4112                 /* check if this is already taken and not excluded */
4113                 for (i = 0; i < tdo_fti->count; i++) {
4114                         trec = &tdo_fti->records[i].record;
4115
4116                         switch (trec->type) {
4117                         case FOREST_TRUST_TOP_LEVEL_NAME:
4118                                 ex_rule = false;
4119                                 tname = trec->data.name.string;
4120                                 tlen = trec->data.name.size;
4121                                 break;
4122                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4123                                 ex_rule = true;
4124                                 tname = trec->data.name.string;
4125                                 tlen = trec->data.name.size;
4126                                 break;
4127                         case FOREST_TRUST_DOMAIN_INFO:
4128                                 ex_rule = false;
4129                                 tname = trec->data.info.dns_name.string;
4130                                 tlen = trec->data.info.dns_name.size;
4131                         }
4132                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4133                         switch (ret) {
4134                         case DNS_CMP_MATCH:
4135                                 /* if it matches exclusion,
4136                                  * it doesn't conflict */
4137                                 if (ex_rule) {
4138                                         exclusion = true;
4139                                         break;
4140                                 }
4141                                 /* fall through */
4142                         case DNS_CMP_FIRST_IS_CHILD:
4143                         case DNS_CMP_SECOND_IS_CHILD:
4144                                 tln_conflict = true;
4145                                 /* fall through */
4146                         default:
4147                                 break;
4148                         }
4149
4150                         /* explicit exclusion, no dns name conflict here */
4151                         if (exclusion) {
4152                                 tln_conflict = false;
4153                         }
4154
4155                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4156                                 continue;
4157                         }
4158
4159                         /* also test for domain info */
4160                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4161                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4162                                 sid_conflict = true;
4163                         }
4164                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4165                             strcasecmp_m(trec->data.info.netbios_name.string,
4166                                          nb_name) == 0) {
4167                                 nb_conflict = true;
4168                         }
4169                 }
4170
4171                 if (tln_conflict) {
4172                         nt_status = add_collision(c_info, new_fti_idx,
4173                                                   collision_type,
4174                                                   LSA_TLN_DISABLED_CONFLICT,
4175                                                   tdo_name);
4176                 }
4177                 if (sid_conflict) {
4178                         nt_status = add_collision(c_info, new_fti_idx,
4179                                                   collision_type,
4180                                                   LSA_SID_DISABLED_CONFLICT,
4181                                                   tdo_name);
4182                 }
4183                 if (nb_conflict) {
4184                         nt_status = add_collision(c_info, new_fti_idx,
4185                                                   collision_type,
4186                                                   LSA_NB_DISABLED_CONFLICT,
4187                                                   tdo_name);
4188                 }
4189         }
4190
4191         return NT_STATUS_OK;
4192 }
4193
4194 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4195                               uint32_t idx, uint32_t collision_type,
4196                               uint32_t conflict_type, const char *tdo_name)
4197 {
4198         struct lsa_ForestTrustCollisionRecord **es;
4199         uint32_t i = c_info->count;
4200
4201         es = talloc_realloc(c_info, c_info->entries,
4202                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4203         if (!es) {
4204                 return NT_STATUS_NO_MEMORY;
4205         }
4206         c_info->entries = es;
4207         c_info->count = i + 1;
4208
4209         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4210         if (!es[i]) {
4211                 return NT_STATUS_NO_MEMORY;
4212         }
4213
4214         es[i]->index = idx;
4215         es[i]->type = collision_type;
4216         es[i]->flags.flags = conflict_type;
4217         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4218         if (!es[i]->name.string) {
4219                 return NT_STATUS_NO_MEMORY;
4220         }
4221         es[i]->name.size = strlen(es[i]->name.string);
4222
4223         return NT_STATUS_OK;
4224 }
4225
4226 /*
4227   lsa_lsaRSetForestTrustInformation
4228 */
4229 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4230                                                          TALLOC_CTX *mem_ctx,
4231                                                          struct lsa_lsaRSetForestTrustInformation *r)
4232 {
4233         struct dcesrv_handle *h;
4234         struct lsa_policy_state *p_state;
4235         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4236                                       "msDS-TrustForestTrustInfo", NULL };
4237         struct ldb_message **dom_res = NULL;
4238         struct ldb_dn *tdo_dn;
4239         struct ldb_message *msg;
4240         int num_res, i;
4241         const char *td_name;
4242         uint32_t trust_attributes;
4243         struct lsa_ForestTrustCollisionInfo *c_info;
4244         struct ForestTrustInfo *nfti;
4245         struct ForestTrustInfo *fti;
4246         DATA_BLOB ft_blob;
4247         enum ndr_err_code ndr_err;
4248         NTSTATUS nt_status;
4249         bool am_rodc;
4250         int ret;
4251
4252         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4253
4254         p_state = h->data;
4255
4256         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4257                 return NT_STATUS_INVALID_DOMAIN_STATE;
4258         }
4259
4260         /* abort if we are not a PDC */
4261         if (!samdb_is_pdc(p_state->sam_ldb)) {
4262                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4263         }
4264
4265         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4266         if (ret == LDB_SUCCESS && am_rodc) {
4267                 return NT_STATUS_NO_SUCH_DOMAIN;
4268         }
4269
4270         /* check caller has TRUSTED_SET_AUTH */
4271
4272         /* fetch all trusted domain objects */
4273         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4274                                p_state->system_dn,
4275                                &dom_res, trust_attrs,
4276                                "(objectclass=trustedDomain)");
4277         if (num_res == 0) {
4278                 return NT_STATUS_NO_SUCH_DOMAIN;
4279         }
4280
4281         for (i = 0; i < num_res; i++) {
4282                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4283                                                       "trustPartner", NULL);
4284                 if (!td_name) {
4285                         return NT_STATUS_INVALID_DOMAIN_STATE;
4286                 }
4287                 if (strcasecmp_m(td_name,
4288                                  r->in.trusted_domain_name->string) == 0) {
4289                         break;
4290                 }
4291         }
4292         if (i >= num_res) {
4293                 return NT_STATUS_NO_SUCH_DOMAIN;
4294         }
4295
4296         tdo_dn = dom_res[i]->dn;
4297
4298         trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4299                                                      "trustAttributes", 0);
4300         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4301                 return NT_STATUS_INVALID_PARAMETER;
4302         }
4303
4304         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4305                 return NT_STATUS_INVALID_PARAMETER;
4306         }
4307
4308         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4309         if (!nfti) {
4310                 return NT_STATUS_NO_MEMORY;
4311         }
4312
4313         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4314         if (!NT_STATUS_IS_OK(nt_status)) {
4315                 return nt_status;
4316         }
4317
4318         c_info = talloc_zero(r->out.collision_info,
4319                              struct lsa_ForestTrustCollisionInfo);
4320         if (!c_info) {
4321                 return NT_STATUS_NO_MEMORY;
4322         }
4323
4324         /* first check own info, then other domains */
4325         fti = talloc(mem_ctx, struct ForestTrustInfo);
4326         if (!fti) {
4327                 return NT_STATUS_NO_MEMORY;
4328         }
4329
4330         nt_status = own_ft_info(p_state, fti);
4331         if (!NT_STATUS_IS_OK(nt_status)) {
4332                 return nt_status;
4333         }
4334
4335         nt_status = check_ft_info(c_info, p_state->domain_dns,
4336                                   fti, nfti, c_info);
4337         if (!NT_STATUS_IS_OK(nt_status)) {
4338                 return nt_status;
4339         }
4340
4341         for (i = 0; i < num_res; i++) {
4342                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4343                 if (!fti) {
4344                         return NT_STATUS_NO_MEMORY;
4345                 }
4346
4347                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4348                 if (!NT_STATUS_IS_OK(nt_status)) {
4349                         if (NT_STATUS_EQUAL(nt_status,
4350                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4351                                 continue;
4352                         }
4353                         return nt_status;
4354                 }
4355
4356                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4357                                                       "trustPartner", NULL);
4358                 if (!td_name) {
4359                         return NT_STATUS_INVALID_DOMAIN_STATE;
4360                 }
4361
4362                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4363                 if (!NT_STATUS_IS_OK(nt_status)) {
4364                         return nt_status;
4365                 }
4366         }
4367
4368         *r->out.collision_info = c_info;
4369
4370         if (r->in.check_only != 0) {
4371                 return NT_STATUS_OK;
4372         }
4373
4374         /* not just a check, write info back */
4375
4376         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4377                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4378         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4379                 return NT_STATUS_INVALID_PARAMETER;
4380         }
4381
4382         msg = ldb_msg_new(mem_ctx);
4383         if (msg == NULL) {
4384                 return NT_STATUS_NO_MEMORY;
4385         }
4386
4387         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4388         if (!msg->dn) {
4389                 return NT_STATUS_NO_MEMORY;
4390         }
4391
4392         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4393                                 LDB_FLAG_MOD_REPLACE, NULL);
4394         if (ret != LDB_SUCCESS) {
4395                 return NT_STATUS_NO_MEMORY;
4396         }
4397         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4398                                 &ft_blob, NULL);
4399         if (ret != LDB_SUCCESS) {
4400                 return NT_STATUS_NO_MEMORY;
4401         }
4402
4403         ret = ldb_modify(p_state->sam_ldb, msg);
4404         if (ret != LDB_SUCCESS) {
4405                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4406                           ldb_errstring(p_state->sam_ldb)));
4407
4408                 switch (ret) {
4409                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4410                         return NT_STATUS_ACCESS_DENIED;
4411                 default:
4412                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4413                 }
4414         }
4415
4416         return NT_STATUS_OK;
4417 }
4418
4419 /* 
4420   lsa_CREDRRENAME 
4421 */
4422 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4423                        struct lsa_CREDRRENAME *r)
4424 {
4425         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4426 }
4427
4428
4429
4430 /* 
4431   lsa_LSAROPENPOLICYSCE 
4432 */
4433 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4434                        struct lsa_LSAROPENPOLICYSCE *r)
4435 {
4436         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4437 }
4438
4439
4440 /* 
4441   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
4442 */
4443 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4444                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4445 {
4446         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4447 }
4448
4449
4450 /* 
4451   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
4452 */
4453 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4454                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4455 {
4456         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4457 }
4458
4459
4460 /* 
4461   lsa_LSARADTREPORTSECURITYEVENT 
4462 */
4463 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4464                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4465 {
4466         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4467 }
4468
4469
4470 /* include the generated boilerplate */
4471 #include "librpc/gen_ndr/ndr_lsa_s.c"
4472
4473
4474
4475 /*****************************************
4476 NOTE! The remaining calls below were
4477 removed in w2k3, so the DCESRV_FAULT()
4478 replies are the correct implementation. Do
4479 not try and fill these in with anything else
4480 ******************************************/
4481
4482 /* 
4483   dssetup_DsRoleDnsNameToFlatName 
4484 */
4485 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4486                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4487 {
4488         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4489 }
4490
4491
4492 /* 
4493   dssetup_DsRoleDcAsDc 
4494 */
4495 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4496                              struct dssetup_DsRoleDcAsDc *r)
4497 {
4498         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4499 }
4500
4501
4502 /* 
4503   dssetup_DsRoleDcAsReplica 
4504 */
4505 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4506                                   struct dssetup_DsRoleDcAsReplica *r)
4507 {
4508         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4509 }
4510
4511
4512 /* 
4513   dssetup_DsRoleDemoteDc 
4514 */
4515 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4516                                struct dssetup_DsRoleDemoteDc *r)
4517 {
4518         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4519 }
4520
4521
4522 /* 
4523   dssetup_DsRoleGetDcOperationProgress 
4524 */
4525 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4526                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4527 {
4528         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4529 }
4530
4531
4532 /* 
4533   dssetup_DsRoleGetDcOperationResults 
4534 */
4535 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4536                                             struct dssetup_DsRoleGetDcOperationResults *r)
4537 {
4538         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4539 }
4540
4541
4542 /* 
4543   dssetup_DsRoleCancel 
4544 */
4545 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4546                              struct dssetup_DsRoleCancel *r)
4547 {
4548         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4549 }
4550
4551
4552 /* 
4553   dssetup_DsRoleServerSaveStateForUpgrade 
4554 */
4555 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4556                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4557 {
4558         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4559 }
4560
4561
4562 /* 
4563   dssetup_DsRoleUpgradeDownlevelServer 
4564 */
4565 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4566                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4567 {
4568         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4569 }
4570
4571
4572 /* 
4573   dssetup_DsRoleAbortDownlevelServerUpgrade 
4574 */
4575 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4576                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4577 {
4578         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4579 }
4580
4581
4582 /* include the generated boilerplate */
4583 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4584
4585 NTSTATUS dcerpc_server_lsa_init(void)
4586 {
4587         NTSTATUS ret;
4588         
4589         ret = dcerpc_server_dssetup_init();
4590         if (!NT_STATUS_IS_OK(ret)) {
4591                 return ret;
4592         }
4593         ret = dcerpc_server_lsarpc_init();
4594         if (!NT_STATUS_IS_OK(ret)) {
4595                 return ret;
4596         }
4597         return ret;
4598 }