47f54442dba0998338e53ca120f7d59df6e47956
[samba.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
33 /*
34   this type allows us to distinguish handle types
35 */
36
37 /*
38   state associated with a lsa_OpenAccount() operation
39 */
40 struct lsa_account_state {
41         struct lsa_policy_state *policy;
42         uint32_t access_mask;
43         struct dom_sid *account_sid;
44 };
45
46
47 /*
48   state associated with a lsa_OpenSecret() operation
49 */
50 struct lsa_secret_state {
51         struct lsa_policy_state *policy;
52         uint32_t access_mask;
53         struct ldb_dn *secret_dn;
54         struct ldb_context *sam_ldb;
55         bool global;
56 };
57
58 /*
59   state associated with a lsa_OpenTrustedDomain() operation
60 */
61 struct lsa_trusted_domain_state {
62         struct lsa_policy_state *policy;
63         uint32_t access_mask;
64         struct ldb_dn *trusted_domain_dn;
65         struct ldb_dn *trusted_domain_user_dn;
66 };
67
68 /*
69   this is based on the samba3 function make_lsa_object_sd()
70   It uses the same logic, but with samba4 helper functions
71  */
72 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx, 
73                                     struct security_descriptor **sd,
74                                     struct dom_sid *sid, 
75                                     uint32_t sid_access)
76 {
77         NTSTATUS status;
78         uint32_t rid;
79         struct dom_sid *domain_sid, *domain_admins_sid;
80         const char *domain_admins_sid_str, *sidstr;
81         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
82
83         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
84         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
85
86         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
87         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
88
89         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
90         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
91         
92         sidstr = dom_sid_string(tmp_ctx, sid);
93         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
94                                                       
95         *sd = security_descriptor_dacl_create(mem_ctx,
96                                               0, sidstr, NULL,
97
98                                               SID_WORLD,
99                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
100                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
101                                               
102                                               SID_BUILTIN_ADMINISTRATORS,
103                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
104                                               SEC_GENERIC_ALL, 0,
105                                               
106                                               SID_BUILTIN_ACCOUNT_OPERATORS,
107                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
108                                               SEC_GENERIC_ALL, 0,
109                                               
110                                               domain_admins_sid_str,
111                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
112                                               SEC_GENERIC_ALL, 0,
113
114                                               sidstr,
115                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
116                                               sid_access, 0,
117
118                                               NULL);
119         talloc_free(tmp_ctx);
120
121         NT_STATUS_HAVE_NO_MEMORY(*sd);
122
123         return NT_STATUS_OK;
124 }
125
126
127 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
128                                       TALLOC_CTX *mem_ctx,
129                                       struct lsa_EnumAccountRights *r);
130
131 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
132                                            TALLOC_CTX *mem_ctx,
133                                            struct lsa_policy_state *state,
134                                            int ldb_flag,
135                                            struct dom_sid *sid,
136                                            const struct lsa_RightSet *rights);
137
138 /* 
139   lsa_Close 
140 */
141 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
142                           struct lsa_Close *r)
143 {
144         struct dcesrv_handle *h;
145
146         *r->out.handle = *r->in.handle;
147
148         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
149
150         talloc_free(h);
151
152         ZERO_STRUCTP(r->out.handle);
153
154         return NT_STATUS_OK;
155 }
156
157
158 /* 
159   lsa_Delete 
160 */
161 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
162                            struct lsa_Delete *r)
163 {
164         return NT_STATUS_NOT_SUPPORTED;
165 }
166
167
168 /* 
169   lsa_DeleteObject
170 */
171 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
172                        struct lsa_DeleteObject *r)
173 {
174         struct dcesrv_handle *h;
175         int ret;
176
177         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
178
179         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
180                 struct lsa_secret_state *secret_state = h->data;
181
182                 /* Ensure user is permitted to delete this... */
183                 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
184                 {
185                 case SECURITY_SYSTEM:
186                 case SECURITY_ADMINISTRATOR:
187                         break;
188                 default:
189                         /* Users and annonymous are not allowed delete things */
190                         return NT_STATUS_ACCESS_DENIED;
191                 }
192
193                 ret = ldb_delete(secret_state->sam_ldb, 
194                                  secret_state->secret_dn);
195                 talloc_free(h);
196                 if (ret != LDB_SUCCESS) {
197                         return NT_STATUS_INVALID_HANDLE;
198                 }
199
200                 ZERO_STRUCTP(r->out.handle);
201
202                 return NT_STATUS_OK;
203         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
204                 struct lsa_trusted_domain_state *trusted_domain_state = 
205                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
206                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
207                 if (ret != LDB_SUCCESS) {
208                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
209                 }
210
211                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
212                                  trusted_domain_state->trusted_domain_dn);
213                 if (ret != LDB_SUCCESS) {
214                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
215                         return NT_STATUS_INVALID_HANDLE;
216                 }
217
218                 if (trusted_domain_state->trusted_domain_user_dn) {
219                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
220                                          trusted_domain_state->trusted_domain_user_dn);
221                         if (ret != LDB_SUCCESS) {
222                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
223                                 return NT_STATUS_INVALID_HANDLE;
224                         }
225                 }
226
227                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
228                 if (ret != LDB_SUCCESS) {
229                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
230                 }
231                 talloc_free(h);
232                 ZERO_STRUCTP(r->out.handle);
233
234                 return NT_STATUS_OK;
235         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
236                 struct lsa_RightSet *rights;
237                 struct lsa_account_state *astate;
238                 struct lsa_EnumAccountRights r2;
239                 NTSTATUS status;
240
241                 rights = talloc(mem_ctx, struct lsa_RightSet);
242
243                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
244                 
245                 astate = h->data;
246
247                 r2.in.handle = &astate->policy->handle->wire_handle;
248                 r2.in.sid = astate->account_sid;
249                 r2.out.rights = rights;
250
251                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
252                    but we have a LSA_HANDLE_ACCOUNT here, so this call
253                    will always fail */
254                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
255                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
256                         return NT_STATUS_OK;
257                 }
258
259                 if (!NT_STATUS_IS_OK(status)) {
260                         return status;
261                 }
262
263                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
264                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
265                                                     r2.out.rights);
266                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
267                         return NT_STATUS_OK;
268                 }
269
270                 if (!NT_STATUS_IS_OK(status)) {
271                         return status;
272                 }
273
274                 ZERO_STRUCTP(r->out.handle);
275         } 
276         
277         return NT_STATUS_INVALID_HANDLE;
278 }
279
280
281 /* 
282   lsa_EnumPrivs 
283 */
284 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
285                               struct lsa_EnumPrivs *r)
286 {
287         struct dcesrv_handle *h;
288         struct lsa_policy_state *state;
289         uint32_t i;
290         const char *privname;
291
292         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
293
294         state = h->data;
295
296         i = *r->in.resume_handle;
297         if (i == 0) i = 1;
298
299         while ((privname = sec_privilege_name(i)) &&
300                r->out.privs->count < r->in.max_count) {
301                 struct lsa_PrivEntry *e;
302
303                 r->out.privs->privs = talloc_realloc(r->out.privs,
304                                                        r->out.privs->privs, 
305                                                        struct lsa_PrivEntry, 
306                                                        r->out.privs->count+1);
307                 if (r->out.privs->privs == NULL) {
308                         return NT_STATUS_NO_MEMORY;
309                 }
310                 e = &r->out.privs->privs[r->out.privs->count];
311                 e->luid.low = i;
312                 e->luid.high = 0;
313                 e->name.string = privname;
314                 r->out.privs->count++;
315                 i++;
316         }
317
318         *r->out.resume_handle = i;
319
320         return NT_STATUS_OK;
321 }
322
323
324 /* 
325   lsa_QuerySecObj 
326 */
327 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
328                                          struct lsa_QuerySecurity *r)
329 {
330         struct dcesrv_handle *h;
331         struct security_descriptor *sd;
332         NTSTATUS status;
333         struct dom_sid *sid;
334
335         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
336
337         sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
338
339         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
340                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
341         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
342                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 
343                                              LSA_ACCOUNT_ALL_ACCESS);
344         } else {
345                 return NT_STATUS_INVALID_HANDLE;
346         }
347         NT_STATUS_NOT_OK_RETURN(status);
348
349         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
350         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
351
352         (*r->out.sdbuf)->sd = sd;
353         
354         return NT_STATUS_OK;
355 }
356
357
358 /* 
359   lsa_SetSecObj 
360 */
361 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
362                               struct lsa_SetSecObj *r)
363 {
364         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
365 }
366
367
368 /* 
369   lsa_ChangePassword 
370 */
371 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
372                                    struct lsa_ChangePassword *r)
373 {
374         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
375 }
376
377 /* 
378   dssetup_DsRoleGetPrimaryDomainInformation 
379
380   This is not an LSA call, but is the only call left on the DSSETUP
381   pipe (after the pipe was truncated), and needs lsa_get_policy_state
382 */
383 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
384                                                  TALLOC_CTX *mem_ctx,
385                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
386 {
387         union dssetup_DsRoleInfo *info;
388
389         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
390         W_ERROR_HAVE_NO_MEMORY(info);
391
392         switch (r->in.level) {
393         case DS_ROLE_BASIC_INFORMATION:
394         {
395                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
396                 uint32_t flags = 0;
397                 const char *domain = NULL;
398                 const char *dns_domain = NULL;
399                 const char *forest = NULL;
400                 struct GUID domain_guid;
401                 struct lsa_policy_state *state;
402
403                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
404                 if (!NT_STATUS_IS_OK(status)) {
405                         return ntstatus_to_werror(status);
406                 }
407
408                 ZERO_STRUCT(domain_guid);
409
410                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
411                 case ROLE_STANDALONE:
412                         role            = DS_ROLE_STANDALONE_SERVER;
413                         break;
414                 case ROLE_DOMAIN_MEMBER:
415                         role            = DS_ROLE_MEMBER_SERVER;
416                         break;
417                 case ROLE_DOMAIN_CONTROLLER:
418                         if (samdb_is_pdc(state->sam_ldb)) {
419                                 role    = DS_ROLE_PRIMARY_DC;
420                         } else {
421                                 role    = DS_ROLE_BACKUP_DC;
422                         }
423                         break;
424                 }
425
426                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
427                 case ROLE_STANDALONE:
428                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
429                         W_ERROR_HAVE_NO_MEMORY(domain);
430                         break;
431                 case ROLE_DOMAIN_MEMBER:
432                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
433                         W_ERROR_HAVE_NO_MEMORY(domain);
434                         /* TODO: what is with dns_domain and forest and guid? */
435                         break;
436                 case ROLE_DOMAIN_CONTROLLER:
437                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
438
439                         if (state->mixed_domain == 1) {
440                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
441                         }
442                         
443                         domain          = state->domain_name;
444                         dns_domain      = state->domain_dns;
445                         forest          = state->forest_dns;
446
447                         domain_guid     = state->domain_guid;
448                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
449                         break;
450                 }
451
452                 info->basic.role        = role; 
453                 info->basic.flags       = flags;
454                 info->basic.domain      = domain;
455                 info->basic.dns_domain  = dns_domain;
456                 info->basic.forest      = forest;
457                 info->basic.domain_guid = domain_guid;
458
459                 r->out.info = info;
460                 return WERR_OK;
461         }
462         case DS_ROLE_UPGRADE_STATUS:
463         {
464                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
465                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
466
467                 r->out.info = info;
468                 return WERR_OK;
469         }
470         case DS_ROLE_OP_STATUS:
471         {
472                 info->opstatus.status = DS_ROLE_OP_IDLE;
473
474                 r->out.info = info;
475                 return WERR_OK;
476         }
477         default:
478                 return WERR_INVALID_PARAM;
479         }
480
481         return WERR_INVALID_PARAM;
482 }
483
484 /*
485   fill in the AccountDomain info
486 */
487 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
488                                        struct lsa_DomainInfo *info)
489 {
490         info->name.string = state->domain_name;
491         info->sid         = state->domain_sid;
492
493         return NT_STATUS_OK;
494 }
495
496 /*
497   fill in the DNS domain info
498 */
499 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
500                              struct lsa_DnsDomainInfo *info)
501 {
502         info->name.string = state->domain_name;
503         info->sid         = state->domain_sid;
504         info->dns_domain.string = state->domain_dns;
505         info->dns_forest.string = state->forest_dns;
506         info->domain_guid       = state->domain_guid;
507
508         return NT_STATUS_OK;
509 }
510
511 /* 
512   lsa_QueryInfoPolicy2
513 */
514 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
515                                      struct lsa_QueryInfoPolicy2 *r)
516 {
517         struct lsa_policy_state *state;
518         struct dcesrv_handle *h;
519         union lsa_PolicyInformation *info;
520
521         *r->out.info = NULL;
522
523         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
524
525         state = h->data;
526
527         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
528         if (!info) {
529                 return NT_STATUS_NO_MEMORY;
530         }
531         *r->out.info = info;
532
533         switch (r->in.level) {
534         case LSA_POLICY_INFO_AUDIT_LOG:
535                 /* we don't need to fill in any of this */
536                 ZERO_STRUCT(info->audit_log);
537                 return NT_STATUS_OK;
538         case LSA_POLICY_INFO_AUDIT_EVENTS:
539                 /* we don't need to fill in any of this */
540                 ZERO_STRUCT(info->audit_events);
541                 return NT_STATUS_OK;
542         case LSA_POLICY_INFO_PD:
543                 /* we don't need to fill in any of this */
544                 ZERO_STRUCT(info->pd);
545                 return NT_STATUS_OK;
546
547         case LSA_POLICY_INFO_DOMAIN:
548                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
549         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
550                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
551         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
552                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
553
554         case LSA_POLICY_INFO_ROLE:
555                 info->role.role = LSA_ROLE_PRIMARY;
556                 return NT_STATUS_OK;
557
558         case LSA_POLICY_INFO_DNS:
559         case LSA_POLICY_INFO_DNS_INT:
560                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
561
562         case LSA_POLICY_INFO_REPLICA:
563                 ZERO_STRUCT(info->replica);
564                 return NT_STATUS_OK;
565
566         case LSA_POLICY_INFO_QUOTA:
567                 ZERO_STRUCT(info->quota);
568                 return NT_STATUS_OK;
569
570         case LSA_POLICY_INFO_MOD:
571         case LSA_POLICY_INFO_AUDIT_FULL_SET:
572         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
573                 /* windows gives INVALID_PARAMETER */
574                 *r->out.info = NULL;
575                 return NT_STATUS_INVALID_PARAMETER;
576         }
577
578         *r->out.info = NULL;
579         return NT_STATUS_INVALID_INFO_CLASS;
580 }
581
582 /* 
583   lsa_QueryInfoPolicy 
584 */
585 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
586                                     struct lsa_QueryInfoPolicy *r)
587 {
588         struct lsa_QueryInfoPolicy2 r2;
589         NTSTATUS status;
590
591         ZERO_STRUCT(r2);
592
593         r2.in.handle = r->in.handle;
594         r2.in.level = r->in.level;
595         r2.out.info = r->out.info;
596         
597         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
598
599         return status;
600 }
601
602 /* 
603   lsa_SetInfoPolicy 
604 */
605 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
606                                   struct lsa_SetInfoPolicy *r)
607 {
608         /* need to support this */
609         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
610 }
611
612
613 /* 
614   lsa_ClearAuditLog 
615 */
616 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
617                                   struct lsa_ClearAuditLog *r)
618 {
619         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
620 }
621
622
623 /* 
624   lsa_CreateAccount 
625
626   This call does not seem to have any long-term effects, hence no database operations
627
628   we need to talk to the MS product group to find out what this account database means!
629
630   answer is that the lsa database is totally separate from the SAM and
631   ldap databases. We are going to need a separate ldb to store these
632   accounts. The SIDs on this account bear no relation to the SIDs in
633   AD
634 */
635 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636                                   struct lsa_CreateAccount *r)
637 {
638         struct lsa_account_state *astate;
639
640         struct lsa_policy_state *state;
641         struct dcesrv_handle *h, *ah;
642
643         ZERO_STRUCTP(r->out.acct_handle);
644
645         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
646
647         state = h->data;
648
649         astate = talloc(dce_call->conn, struct lsa_account_state);
650         if (astate == NULL) {
651                 return NT_STATUS_NO_MEMORY;
652         }
653
654         astate->account_sid = dom_sid_dup(astate, r->in.sid);
655         if (astate->account_sid == NULL) {
656                 talloc_free(astate);
657                 return NT_STATUS_NO_MEMORY;
658         }
659         
660         astate->policy = talloc_reference(astate, state);
661         astate->access_mask = r->in.access_mask;
662
663         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
664         if (!ah) {
665                 talloc_free(astate);
666                 return NT_STATUS_NO_MEMORY;
667         }
668
669         ah->data = talloc_steal(ah, astate);
670
671         *r->out.acct_handle = ah->wire_handle;
672
673         return NT_STATUS_OK;
674 }
675
676
677 /* 
678   lsa_EnumAccounts 
679 */
680 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681                                  struct lsa_EnumAccounts *r)
682 {
683         struct dcesrv_handle *h;
684         struct lsa_policy_state *state;
685         int ret;
686         struct ldb_message **res;
687         const char * const attrs[] = { "objectSid", NULL};
688         uint32_t count, i;
689
690         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
691
692         state = h->data;
693
694         /* NOTE: This call must only return accounts that have at least
695            one privilege set 
696         */
697         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
698                            "(&(objectSid=*)(privilege=*))");
699         if (ret < 0) {
700                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
701         }
702
703         if (*r->in.resume_handle >= ret) {
704                 return NT_STATUS_NO_MORE_ENTRIES;
705         }
706
707         count = ret - *r->in.resume_handle;
708         if (count > r->in.num_entries) {
709                 count = r->in.num_entries;
710         }
711
712         if (count == 0) {
713                 return NT_STATUS_NO_MORE_ENTRIES;
714         }
715
716         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
717         if (r->out.sids->sids == NULL) {
718                 return NT_STATUS_NO_MEMORY;
719         }
720
721         for (i=0;i<count;i++) {
722                 r->out.sids->sids[i].sid = 
723                         samdb_result_dom_sid(r->out.sids->sids, 
724                                              res[i + *r->in.resume_handle],
725                                              "objectSid");
726                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
727         }
728
729         r->out.sids->num_sids = count;
730         *r->out.resume_handle = count + *r->in.resume_handle;
731
732         return NT_STATUS_OK;
733         
734 }
735
736 /* This decrypts and returns Trusted Domain Auth Information Internal data */
737 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
738                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
739                                        struct trustDomainPasswords *auth_struct)
740 {
741         DATA_BLOB session_key = data_blob(NULL, 0);
742         enum ndr_err_code ndr_err;
743         NTSTATUS nt_status;
744
745         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
746         if (!NT_STATUS_IS_OK(nt_status)) {
747                 return nt_status;
748         }
749
750         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
751         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
752                                        lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
753                                        auth_struct,
754                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
755         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
756                 return NT_STATUS_INVALID_PARAMETER;
757         }
758
759         return NT_STATUS_OK;
760 }
761
762 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
763                                          TALLOC_CTX *mem_ctx,
764                                          struct trustCurrentPasswords *iopw,
765                                          DATA_BLOB *trustauth_blob)
766 {
767         uint32_t i;
768         struct trustAuthInOutBlob ioblob;
769         enum ndr_err_code ndr_err;
770
771         ioblob.count = iopw->count;
772         ioblob.current = talloc(mem_ctx,
773                                 struct AuthenticationInformationArray);
774         if (!ioblob.current) {
775                 return NT_STATUS_NO_MEMORY;
776         }
777
778         ioblob.current->array = *iopw->current;
779         if (!ioblob.current->array) {
780                 return NT_STATUS_NO_MEMORY;
781         }
782
783         ioblob.previous = talloc(mem_ctx,
784                                  struct AuthenticationInformationArray);
785         if (!ioblob.previous) {
786                 return NT_STATUS_NO_MEMORY;
787         }
788         ioblob.previous->array = talloc_array(mem_ctx,
789                                         struct AuthenticationInformation,
790                                         ioblob.count);
791         if (!ioblob.previous->array) {
792                 return NT_STATUS_NO_MEMORY;
793         }
794
795         for (i = 0; i < ioblob.count; i++) {
796                 ioblob.previous->array[i].LastUpdateTime = 0;
797                 ioblob.previous->array[i].AuthType = 0;
798         }
799         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
800                                        lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
801                                        &ioblob,
802                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
803         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
804                 return NT_STATUS_INVALID_PARAMETER;
805         }
806
807         return NT_STATUS_OK;
808 }
809
810 /*
811   lsa_CreateTrustedDomainEx2
812 */
813 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
814                                                     TALLOC_CTX *mem_ctx,
815                                                     struct lsa_CreateTrustedDomainEx2 *r,
816                                                     int op)
817 {
818         struct dcesrv_handle *policy_handle;
819         struct lsa_policy_state *policy_state;
820         struct lsa_trusted_domain_state *trusted_domain_state;
821         struct dcesrv_handle *handle;
822         struct ldb_message **msgs, *msg, *msg_user;
823         const char *attrs[] = {
824                 NULL
825         };
826         const char *netbios_name;
827         const char *dns_name;
828         const char *name;
829         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
830         struct trustDomainPasswords auth_struct;
831         int ret;
832         NTSTATUS nt_status;
833         struct ldb_context *sam_ldb;
834
835         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
836         ZERO_STRUCTP(r->out.trustdom_handle);
837
838         policy_state = policy_handle->data;
839         sam_ldb = policy_state->sam_ldb;
840
841         netbios_name = r->in.info->netbios_name.string;
842         if (!netbios_name) {
843                 return NT_STATUS_INVALID_PARAMETER;
844         }
845
846         dns_name = r->in.info->domain_name.string;
847
848         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
849         if (!trusted_domain_state) {
850                 return NT_STATUS_NO_MEMORY;
851         }
852         trusted_domain_state->policy = policy_state;
853
854         if (strcasecmp(netbios_name, "BUILTIN") == 0
855             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
856             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
857                 return NT_STATUS_INVALID_PARAMETER;;
858         }
859
860         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
861             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
862             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
863             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
864             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
865                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
866         }
867
868         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
869         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
870                 /* No secrets are created at this time, for this function */
871                 auth_struct.outgoing.count = 0;
872                 auth_struct.incoming.count = 0;
873         } else {
874                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
875                                             r->in.auth_info->auth_blob.size);
876                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
877                                                    &auth_blob, &auth_struct);
878                 if (!NT_STATUS_IS_OK(nt_status)) {
879                         return nt_status;
880                 }
881
882                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
883                         if (auth_struct.incoming.count > 1) {
884                                 return NT_STATUS_INVALID_PARAMETER;
885                         }
886                 }
887         }
888
889         if (auth_struct.incoming.count) {
890                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
891                                                      &auth_struct.incoming,
892                                                      &trustAuthIncoming);
893                 if (!NT_STATUS_IS_OK(nt_status)) {
894                         return nt_status;
895                 }
896         } else {
897                 trustAuthIncoming = data_blob(NULL, 0);
898         }
899
900         if (auth_struct.outgoing.count) {
901                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
902                                                      &auth_struct.outgoing,
903                                                      &trustAuthOutgoing);
904                 if (!NT_STATUS_IS_OK(nt_status)) {
905                         return nt_status;
906                 }
907         } else {
908                 trustAuthOutgoing = data_blob(NULL, 0);
909         }
910
911         ret = ldb_transaction_start(sam_ldb);
912         if (ret != LDB_SUCCESS) {
913                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
914         }
915
916         if (dns_name) {
917                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
918                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
919                 /* search for the trusted_domain record */
920                 ret = gendb_search(sam_ldb,
921                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
922                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
923                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
924                 if (ret > 0) {
925                         ldb_transaction_cancel(sam_ldb);
926                         return NT_STATUS_OBJECT_NAME_COLLISION;
927                 }
928         } else {
929                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
930                 /* search for the trusted_domain record */
931                 ret = gendb_search(sam_ldb,
932                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
933                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
934                                    netbios_encoded, netbios_encoded, netbios_encoded);
935                 if (ret > 0) {
936                         ldb_transaction_cancel(sam_ldb);
937                         return NT_STATUS_OBJECT_NAME_COLLISION;
938                 }
939         }
940
941         if (ret < 0 ) {
942                 ldb_transaction_cancel(sam_ldb);
943                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
944         }
945
946         name = dns_name ? dns_name : netbios_name;
947
948         msg = ldb_msg_new(mem_ctx);
949         if (msg == NULL) {
950                 return NT_STATUS_NO_MEMORY;
951         }
952
953         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
954         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
955                         ldb_transaction_cancel(sam_ldb);
956                 return NT_STATUS_NO_MEMORY;
957         }
958
959         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
960
961         if (r->in.info->sid) {
962                 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
963                 if (ret != LDB_SUCCESS) {
964                         ldb_transaction_cancel(sam_ldb);
965                         return NT_STATUS_INVALID_PARAMETER;
966                 }
967         }
968
969         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
970
971         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
972
973         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
974
975         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
976
977         if (dns_name) {
978                 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
979         }
980
981         if (trustAuthIncoming.data) {
982                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
983                 if (ret != LDB_SUCCESS) {
984                         ldb_transaction_cancel(sam_ldb);
985                         return NT_STATUS_NO_MEMORY;
986                 }
987         }
988         if (trustAuthOutgoing.data) {
989                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
990                 if (ret != LDB_SUCCESS) {
991                         ldb_transaction_cancel(sam_ldb);
992                         return NT_STATUS_NO_MEMORY;
993                 }
994         }
995
996         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
997
998         /* create the trusted_domain */
999         ret = ldb_add(sam_ldb, msg);
1000         switch (ret) {
1001         case  LDB_SUCCESS:
1002                 break;
1003         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1004                 ldb_transaction_cancel(sam_ldb);
1005                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1006                          ldb_dn_get_linearized(msg->dn),
1007                          ldb_errstring(sam_ldb)));
1008                 return NT_STATUS_DOMAIN_EXISTS;
1009         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1010                 ldb_transaction_cancel(sam_ldb);
1011                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1012                          ldb_dn_get_linearized(msg->dn),
1013                          ldb_errstring(sam_ldb)));
1014                 return NT_STATUS_ACCESS_DENIED;
1015         default:
1016                 ldb_transaction_cancel(sam_ldb);
1017                 DEBUG(0,("Failed to create user record %s: %s\n",
1018                          ldb_dn_get_linearized(msg->dn),
1019                          ldb_errstring(sam_ldb)));
1020                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1021         }
1022
1023         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1024                 msg_user = ldb_msg_new(mem_ctx);
1025                 if (msg_user == NULL) {
1026                         ldb_transaction_cancel(sam_ldb);
1027                         return NT_STATUS_NO_MEMORY;
1028                 }
1029
1030                 /* Inbound trusts must also create a cn=users object to match */
1031
1032                 trusted_domain_state->trusted_domain_user_dn = msg_user->dn
1033                         = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
1034                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
1035                         ldb_transaction_cancel(sam_ldb);
1036                         return NT_STATUS_NO_MEMORY;
1037                 }
1038
1039                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
1040                         ldb_transaction_cancel(sam_ldb);
1041                         return NT_STATUS_NO_MEMORY;
1042                 }
1043
1044                 ldb_msg_add_string(msg_user, "objectClass", "user");
1045
1046                 ldb_msg_add_steal_string(msg_user, "samAccountName",
1047                                          talloc_asprintf(mem_ctx, "%s$", netbios_name));
1048
1049                 if (samdb_msg_add_uint(sam_ldb, mem_ctx, msg_user,
1050                                        "userAccountControl",
1051                                        UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) {
1052                         ldb_transaction_cancel(sam_ldb);
1053                         return NT_STATUS_NO_MEMORY;
1054                 }
1055
1056                 if (auth_struct.incoming.count) {
1057                         uint32_t i;
1058                         for (i=0; i < auth_struct.incoming.count; i++ ) {
1059                                 if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
1060                                         samdb_msg_add_hash(sam_ldb,
1061                                                            mem_ctx, msg_user, "unicodePwd",
1062                                                            &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
1063                                 } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
1064                                         DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
1065                                                                                  auth_struct.incoming.current[i]->AuthInfo.clear.size);
1066                                         ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
1067                                         if (ret != LDB_SUCCESS) {
1068                                                 ldb_transaction_cancel(sam_ldb);
1069                                                 return NT_STATUS_NO_MEMORY;
1070                                         }
1071                                 }
1072                         }
1073                 }
1074
1075                 /* create the cn=users trusted_domain account */
1076                 ret = ldb_add(sam_ldb, msg_user);
1077                 switch (ret) {
1078                 case  LDB_SUCCESS:
1079                         break;
1080                 case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1081                         ldb_transaction_cancel(sam_ldb);
1082                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1083                                  ldb_dn_get_linearized(msg_user->dn),
1084                                  ldb_errstring(sam_ldb)));
1085                         return NT_STATUS_DOMAIN_EXISTS;
1086                 case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1087                         ldb_transaction_cancel(sam_ldb);
1088                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1089                                  ldb_dn_get_linearized(msg_user->dn),
1090                                  ldb_errstring(sam_ldb)));
1091                         return NT_STATUS_ACCESS_DENIED;
1092                 default:
1093                         ldb_transaction_cancel(sam_ldb);
1094                         DEBUG(0,("Failed to create user record %s: %s\n",
1095                                  ldb_dn_get_linearized(msg_user->dn),
1096                                  ldb_errstring(sam_ldb)));
1097                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1098                 }
1099         }
1100
1101         ret = ldb_transaction_commit(sam_ldb);
1102         if (ret != LDB_SUCCESS) {
1103                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1104         }
1105
1106         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1107         if (!handle) {
1108                 return NT_STATUS_NO_MEMORY;
1109         }
1110
1111         handle->data = talloc_steal(handle, trusted_domain_state);
1112
1113         trusted_domain_state->access_mask = r->in.access_mask;
1114         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1115
1116         *r->out.trustdom_handle = handle->wire_handle;
1117
1118         return NT_STATUS_OK;
1119 }
1120
1121 /*
1122   lsa_CreateTrustedDomainEx2
1123 */
1124 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1125                                            TALLOC_CTX *mem_ctx,
1126                                            struct lsa_CreateTrustedDomainEx2 *r)
1127 {
1128         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1129 }
1130 /*
1131   lsa_CreateTrustedDomainEx
1132 */
1133 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1134                                           TALLOC_CTX *mem_ctx,
1135                                           struct lsa_CreateTrustedDomainEx *r)
1136 {
1137         struct lsa_CreateTrustedDomainEx2 r2;
1138
1139         r2.in.policy_handle = r->in.policy_handle;
1140         r2.in.info = r->in.info;
1141         r2.in.auth_info = r->in.auth_info;
1142         r2.out.trustdom_handle = r->out.trustdom_handle;
1143         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1144 }
1145
1146 /* 
1147   lsa_CreateTrustedDomain 
1148 */
1149 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150                                         struct lsa_CreateTrustedDomain *r)
1151 {
1152         struct lsa_CreateTrustedDomainEx2 r2;
1153
1154         r2.in.policy_handle = r->in.policy_handle;
1155         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1156         if (!r2.in.info) {
1157                 return NT_STATUS_NO_MEMORY;
1158         }
1159
1160         r2.in.info->domain_name.string = NULL;
1161         r2.in.info->netbios_name = r->in.info->name;
1162         r2.in.info->sid = r->in.info->sid;
1163         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1164         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1165         r2.in.info->trust_attributes = 0;
1166         
1167         r2.in.access_mask = r->in.access_mask;
1168         r2.out.trustdom_handle = r->out.trustdom_handle;
1169
1170         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1171                          
1172 }
1173
1174 /* 
1175   lsa_OpenTrustedDomain
1176 */
1177 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1178                                       struct lsa_OpenTrustedDomain *r)
1179 {
1180         struct dcesrv_handle *policy_handle;
1181         
1182         struct lsa_policy_state *policy_state;
1183         struct lsa_trusted_domain_state *trusted_domain_state;
1184         struct dcesrv_handle *handle;
1185         struct ldb_message **msgs;
1186         const char *attrs[] = {
1187                 "trustDirection",
1188                 "flatname",
1189                 NULL
1190         };
1191
1192         const char *sid_string;
1193         int ret;
1194
1195         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1196         ZERO_STRUCTP(r->out.trustdom_handle);
1197         policy_state = policy_handle->data;
1198
1199         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1200         if (!trusted_domain_state) {
1201                 return NT_STATUS_NO_MEMORY;
1202         }
1203         trusted_domain_state->policy = policy_state;
1204
1205         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1206         if (!sid_string) {
1207                 return NT_STATUS_NO_MEMORY;
1208         }
1209
1210         /* search for the trusted_domain record */
1211         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1212                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1213                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
1214                            sid_string);
1215         if (ret == 0) {
1216                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1217         }
1218         
1219         if (ret != 1) {
1220                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1221                          ldb_dn_get_linearized(policy_state->system_dn)));
1222                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1223         }
1224
1225         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1226
1227         trusted_domain_state->trusted_domain_user_dn = NULL;
1228
1229         if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1230                 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1231                 /* search for the trusted_domain record */
1232                 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1233                                    mem_ctx, policy_state->domain_dn, &msgs, attrs,
1234                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))", 
1235                                    flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1236                 if (ret == 1) {
1237                         trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1238                 }
1239         }
1240         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1241         if (!handle) {
1242                 return NT_STATUS_NO_MEMORY;
1243         }
1244         
1245         handle->data = talloc_steal(handle, trusted_domain_state);
1246         
1247         trusted_domain_state->access_mask = r->in.access_mask;
1248         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1249         
1250         *r->out.trustdom_handle = handle->wire_handle;
1251         
1252         return NT_STATUS_OK;
1253 }
1254
1255
1256 /*
1257   lsa_OpenTrustedDomainByName
1258 */
1259 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1260                                             TALLOC_CTX *mem_ctx,
1261                                             struct lsa_OpenTrustedDomainByName *r)
1262 {
1263         struct dcesrv_handle *policy_handle;
1264
1265         struct lsa_policy_state *policy_state;
1266         struct lsa_trusted_domain_state *trusted_domain_state;
1267         struct dcesrv_handle *handle;
1268         struct ldb_message **msgs;
1269         const char *attrs[] = {
1270                 NULL
1271         };
1272         char *td_name;
1273         int ret;
1274
1275         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1276         ZERO_STRUCTP(r->out.trustdom_handle);
1277         policy_state = policy_handle->data;
1278
1279         if (!r->in.name.string) {
1280                 return NT_STATUS_INVALID_PARAMETER;
1281         }
1282
1283         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1284         if (!trusted_domain_state) {
1285                 return NT_STATUS_NO_MEMORY;
1286         }
1287         trusted_domain_state->policy = policy_state;
1288
1289         /* search for the trusted_domain record */
1290         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1291         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1292                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1293                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1294                              "(objectclass=trustedDomain))",
1295                            td_name, td_name, td_name);
1296         if (ret == 0) {
1297                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1298         }
1299
1300         if (ret != 1) {
1301                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1302                          ldb_dn_get_linearized(policy_state->system_dn)));
1303                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1304         }
1305
1306         /* TODO: perform access checks */
1307
1308         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1309
1310         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1311         if (!handle) {
1312                 return NT_STATUS_NO_MEMORY;
1313         }
1314
1315         handle->data = talloc_steal(handle, trusted_domain_state);
1316
1317         trusted_domain_state->access_mask = r->in.access_mask;
1318         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1319
1320         *r->out.trustdom_handle = handle->wire_handle;
1321
1322         return NT_STATUS_OK;
1323 }
1324
1325
1326
1327 /* 
1328   lsa_SetTrustedDomainInfo
1329 */
1330 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1331                                          struct lsa_SetTrustedDomainInfo *r)
1332 {
1333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1334 }
1335
1336
1337
1338 /* 
1339   lsa_SetInfomrationTrustedDomain
1340 */
1341 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
1342                                                 TALLOC_CTX *mem_ctx,
1343                                                 struct lsa_SetInformationTrustedDomain *r)
1344 {
1345         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1346 }
1347
1348
1349 /* 
1350   lsa_DeleteTrustedDomain
1351 */
1352 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1353                                       struct lsa_DeleteTrustedDomain *r)
1354 {
1355         NTSTATUS status;
1356         struct lsa_OpenTrustedDomain opn;
1357         struct lsa_DeleteObject del;
1358         struct dcesrv_handle *h;
1359
1360         opn.in.handle = r->in.handle;
1361         opn.in.sid = r->in.dom_sid;
1362         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1363         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1364         if (!opn.out.trustdom_handle) {
1365                 return NT_STATUS_NO_MEMORY;
1366         }
1367         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1368         if (!NT_STATUS_IS_OK(status)) {
1369                 return status;
1370         }
1371
1372         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1373         talloc_steal(mem_ctx, h);
1374
1375         del.in.handle = opn.out.trustdom_handle;
1376         del.out.handle = opn.out.trustdom_handle;
1377         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1378         if (!NT_STATUS_IS_OK(status)) {
1379                 return status;
1380         }
1381         return NT_STATUS_OK;
1382 }
1383
1384 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1385                                      struct ldb_message *msg, 
1386                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1387 {
1388         info_ex->domain_name.string
1389                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1390         info_ex->netbios_name.string
1391                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1392         info_ex->sid 
1393                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1394         info_ex->trust_direction
1395                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1396         info_ex->trust_type
1397                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1398         info_ex->trust_attributes
1399                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1400         return NT_STATUS_OK;
1401 }
1402
1403 /* 
1404   lsa_QueryTrustedDomainInfo
1405 */
1406 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1407                                            struct lsa_QueryTrustedDomainInfo *r)
1408 {
1409         union lsa_TrustedDomainInfo *info = NULL;
1410         struct dcesrv_handle *h;
1411         struct lsa_trusted_domain_state *trusted_domain_state;
1412         struct ldb_message *msg;
1413         int ret;
1414         struct ldb_message **res;
1415         const char *attrs[] = {
1416                 "flatname", 
1417                 "trustPartner",
1418                 "securityIdentifier",
1419                 "trustDirection",
1420                 "trustType",
1421                 "trustAttributes", 
1422                 "msDs-supportedEncryptionTypes",
1423                 NULL
1424         };
1425
1426         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1427
1428         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1429
1430         /* pull all the user attributes */
1431         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1432                               trusted_domain_state->trusted_domain_dn, &res, attrs);
1433         if (ret != 1) {
1434                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1435         }
1436         msg = res[0];
1437         
1438         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
1439         if (!info) {
1440                 return NT_STATUS_NO_MEMORY;
1441         }
1442         *r->out.info = info;
1443
1444         switch (r->in.level) {
1445         case LSA_TRUSTED_DOMAIN_INFO_NAME:
1446                 info->name.netbios_name.string
1447                         = samdb_result_string(msg, "flatname", NULL);                                      
1448                 break;
1449         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1450                 info->posix_offset.posix_offset
1451                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1452                 break;
1453 #if 0  /* Win2k3 doesn't implement this */
1454         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
1455                 r->out.info->info_basic.netbios_name.string 
1456                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1457                 r->out.info->info_basic.sid
1458                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1459                 break;
1460 #endif
1461         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1462                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
1463
1464         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1465                 ZERO_STRUCT(info->full_info);
1466                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
1467
1468         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
1469                 ZERO_STRUCT(info->full_info2_internal);
1470                 info->full_info2_internal.posix_offset.posix_offset
1471                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1472                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
1473                 
1474         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1475                 info->enc_types.enc_types
1476                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
1477                 break;
1478
1479         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
1480         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
1481                 /* oops, we don't want to return the info after all */
1482                 talloc_free(info);
1483                 *r->out.info = NULL;
1484                 return NT_STATUS_INVALID_PARAMETER;
1485         default:
1486                 /* oops, we don't want to return the info after all */
1487                 talloc_free(info);
1488                 *r->out.info = NULL;
1489                 return NT_STATUS_INVALID_INFO_CLASS;
1490         }
1491
1492         return NT_STATUS_OK;
1493 }
1494
1495
1496 /* 
1497   lsa_QueryTrustedDomainInfoBySid
1498 */
1499 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1500                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
1501 {
1502         NTSTATUS status;
1503         struct lsa_OpenTrustedDomain opn;
1504         struct lsa_QueryTrustedDomainInfo query;
1505         struct dcesrv_handle *h;
1506
1507         opn.in.handle = r->in.handle;
1508         opn.in.sid = r->in.dom_sid;
1509         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1510         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1511         if (!opn.out.trustdom_handle) {
1512                 return NT_STATUS_NO_MEMORY;
1513         }
1514         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1515         if (!NT_STATUS_IS_OK(status)) {
1516                 return status;
1517         }
1518
1519         /* Ensure this handle goes away at the end of this call */
1520         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1521         talloc_steal(mem_ctx, h);
1522
1523         query.in.trustdom_handle = opn.out.trustdom_handle;
1524         query.in.level = r->in.level;
1525         query.out.info = r->out.info;
1526         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1527         if (!NT_STATUS_IS_OK(status)) {
1528                 return status;
1529         }
1530
1531         return NT_STATUS_OK;
1532 }
1533
1534 /*
1535   lsa_SetTrustedDomainInfoByName
1536 */
1537 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1538                                                TALLOC_CTX *mem_ctx,
1539                                                struct lsa_SetTrustedDomainInfoByName *r)
1540 {
1541         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1542 }
1543
1544 /* 
1545    lsa_QueryTrustedDomainInfoByName
1546 */
1547 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1548                                                  TALLOC_CTX *mem_ctx,
1549                                                  struct lsa_QueryTrustedDomainInfoByName *r)
1550 {
1551         NTSTATUS status;
1552         struct lsa_OpenTrustedDomainByName opn;
1553         struct lsa_QueryTrustedDomainInfo query;
1554         struct dcesrv_handle *h;
1555
1556         opn.in.handle = r->in.handle;
1557         opn.in.name = *r->in.trusted_domain;
1558         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1559         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1560         if (!opn.out.trustdom_handle) {
1561                 return NT_STATUS_NO_MEMORY;
1562         }
1563         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
1564         if (!NT_STATUS_IS_OK(status)) {
1565                 return status;
1566         }
1567         
1568         /* Ensure this handle goes away at the end of this call */
1569         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1570         talloc_steal(mem_ctx, h);
1571
1572         query.in.trustdom_handle = opn.out.trustdom_handle;
1573         query.in.level = r->in.level;
1574         query.out.info = r->out.info;
1575         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 return status;
1578         }
1579         
1580         return NT_STATUS_OK;
1581 }
1582
1583 /*
1584   lsa_CloseTrustedDomainEx 
1585 */
1586 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
1587                                          TALLOC_CTX *mem_ctx,
1588                                          struct lsa_CloseTrustedDomainEx *r)
1589 {
1590         /* The result of a bad hair day from an IDL programmer?  Not
1591          * implmented in Win2k3.  You should always just lsa_Close
1592          * anyway. */
1593         return NT_STATUS_NOT_IMPLEMENTED;
1594 }
1595
1596
1597 /*
1598   comparison function for sorting lsa_DomainInformation array
1599 */
1600 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
1601 {
1602         return strcasecmp_m(e1->name.string, e2->name.string);
1603 }
1604
1605 /* 
1606   lsa_EnumTrustDom 
1607 */
1608 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1609                                  struct lsa_EnumTrustDom *r)
1610 {
1611         struct dcesrv_handle *policy_handle;
1612         struct lsa_DomainInfo *entries;
1613         struct lsa_policy_state *policy_state;
1614         struct ldb_message **domains;
1615         const char *attrs[] = {
1616                 "flatname", 
1617                 "securityIdentifier",
1618                 NULL
1619         };
1620
1621
1622         int count, i;
1623
1624         *r->out.resume_handle = 0;
1625
1626         r->out.domains->domains = NULL;
1627         r->out.domains->count = 0;
1628
1629         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1630
1631         policy_state = policy_handle->data;
1632
1633         /* search for all users in this domain. This could possibly be cached and 
1634            resumed based on resume_key */
1635         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1636                              "objectclass=trustedDomain");
1637         if (count < 0) {
1638                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1639         }
1640
1641         /* convert to lsa_TrustInformation format */
1642         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
1643         if (!entries) {
1644                 return NT_STATUS_NO_MEMORY;
1645         }
1646         for (i=0;i<count;i++) {
1647                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
1648                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
1649         }
1650
1651         /* sort the results by name */
1652         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
1653
1654         if (*r->in.resume_handle >= count) {
1655                 *r->out.resume_handle = -1;
1656
1657                 return NT_STATUS_NO_MORE_ENTRIES;
1658         }
1659
1660         /* return the rest, limit by max_size. Note that we 
1661            use the w2k3 element size value of 60 */
1662         r->out.domains->count = count - *r->in.resume_handle;
1663         r->out.domains->count = MIN(r->out.domains->count, 
1664                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1665
1666         r->out.domains->domains = entries + *r->in.resume_handle;
1667         r->out.domains->count = r->out.domains->count;
1668
1669         if (r->out.domains->count < count - *r->in.resume_handle) {
1670                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1671                 return STATUS_MORE_ENTRIES;
1672         }
1673
1674         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
1675          * always be larger than the previous input resume handle, in
1676          * particular when hitting the last query it is vital to set the
1677          * resume handle correctly to avoid infinite client loops, as
1678          * seen e.g. with Windows XP SP3 when resume handle is 0 and
1679          * status is NT_STATUS_OK - gd */
1680
1681         *r->out.resume_handle = (uint32_t)-1;
1682
1683         return NT_STATUS_OK;
1684 }
1685
1686 /*
1687   comparison function for sorting lsa_DomainInformation array
1688 */
1689 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1690 {
1691         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1692 }
1693
1694 /* 
1695   lsa_EnumTrustedDomainsEx 
1696 */
1697 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1698                                         struct lsa_EnumTrustedDomainsEx *r)
1699 {
1700         struct dcesrv_handle *policy_handle;
1701         struct lsa_TrustDomainInfoInfoEx *entries;
1702         struct lsa_policy_state *policy_state;
1703         struct ldb_message **domains;
1704         const char *attrs[] = {
1705                 "flatname", 
1706                 "trustPartner",
1707                 "securityIdentifier",
1708                 "trustDirection",
1709                 "trustType",
1710                 "trustAttributes", 
1711                 NULL
1712         };
1713         NTSTATUS nt_status;
1714
1715         int count, i;
1716
1717         *r->out.resume_handle = 0;
1718
1719         r->out.domains->domains = NULL;
1720         r->out.domains->count = 0;
1721
1722         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1723
1724         policy_state = policy_handle->data;
1725
1726         /* search for all users in this domain. This could possibly be cached and 
1727            resumed based on resume_key */
1728         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1729                              "objectclass=trustedDomain");
1730         if (count < 0) {
1731                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1732         }
1733
1734         /* convert to lsa_DomainInformation format */
1735         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1736         if (!entries) {
1737                 return NT_STATUS_NO_MEMORY;
1738         }
1739         for (i=0;i<count;i++) {
1740                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1741                 if (!NT_STATUS_IS_OK(nt_status)) {
1742                         return nt_status;
1743                 }
1744         }
1745
1746         /* sort the results by name */
1747         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
1748
1749         if (*r->in.resume_handle >= count) {
1750                 *r->out.resume_handle = -1;
1751
1752                 return NT_STATUS_NO_MORE_ENTRIES;
1753         }
1754
1755         /* return the rest, limit by max_size. Note that we 
1756            use the w2k3 element size value of 60 */
1757         r->out.domains->count = count - *r->in.resume_handle;
1758         r->out.domains->count = MIN(r->out.domains->count, 
1759                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1760
1761         r->out.domains->domains = entries + *r->in.resume_handle;
1762         r->out.domains->count = r->out.domains->count;
1763
1764         if (r->out.domains->count < count - *r->in.resume_handle) {
1765                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1766                 return STATUS_MORE_ENTRIES;
1767         }
1768
1769         return NT_STATUS_OK;
1770 }
1771
1772
1773 /* 
1774   lsa_OpenAccount 
1775 */
1776 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1777                                 struct lsa_OpenAccount *r)
1778 {
1779         struct dcesrv_handle *h, *ah;
1780         struct lsa_policy_state *state;
1781         struct lsa_account_state *astate;
1782
1783         ZERO_STRUCTP(r->out.acct_handle);
1784
1785         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1786
1787         state = h->data;
1788
1789         astate = talloc(dce_call->conn, struct lsa_account_state);
1790         if (astate == NULL) {
1791                 return NT_STATUS_NO_MEMORY;
1792         }
1793
1794         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1795         if (astate->account_sid == NULL) {
1796                 talloc_free(astate);
1797                 return NT_STATUS_NO_MEMORY;
1798         }
1799         
1800         astate->policy = talloc_reference(astate, state);
1801         astate->access_mask = r->in.access_mask;
1802
1803         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1804         if (!ah) {
1805                 talloc_free(astate);
1806                 return NT_STATUS_NO_MEMORY;
1807         }
1808
1809         ah->data = talloc_steal(ah, astate);
1810
1811         *r->out.acct_handle = ah->wire_handle;
1812
1813         return NT_STATUS_OK;
1814 }
1815
1816
1817 /* 
1818   lsa_EnumPrivsAccount 
1819 */
1820 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1821                                      TALLOC_CTX *mem_ctx,
1822                                      struct lsa_EnumPrivsAccount *r)
1823 {
1824         struct dcesrv_handle *h;
1825         struct lsa_account_state *astate;
1826         int ret;
1827         unsigned int i;
1828         struct ldb_message **res;
1829         const char * const attrs[] = { "privilege", NULL};
1830         struct ldb_message_element *el;
1831         const char *sidstr;
1832         struct lsa_PrivilegeSet *privs;
1833
1834         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1835
1836         astate = h->data;
1837
1838         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1839         if (privs == NULL) {
1840                 return NT_STATUS_NO_MEMORY;
1841         }
1842         privs->count = 0;
1843         privs->unknown = 0;
1844         privs->set = NULL;
1845
1846         *r->out.privs = privs;
1847
1848         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1849         if (sidstr == NULL) {
1850                 return NT_STATUS_NO_MEMORY;
1851         }
1852
1853         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
1854                            "objectSid=%s", sidstr);
1855         if (ret < 0) {
1856                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1857         }
1858         if (ret != 1) {
1859                 return NT_STATUS_OK;
1860         }
1861
1862         el = ldb_msg_find_element(res[0], "privilege");
1863         if (el == NULL || el->num_values == 0) {
1864                 return NT_STATUS_OK;
1865         }
1866
1867         privs->set = talloc_array(privs,
1868                                   struct lsa_LUIDAttribute, el->num_values);
1869         if (privs->set == NULL) {
1870                 return NT_STATUS_NO_MEMORY;
1871         }
1872
1873         for (i=0;i<el->num_values;i++) {
1874                 int id = sec_privilege_id((const char *)el->values[i].data);
1875                 if (id == -1) {
1876                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1877                 }
1878                 privs->set[i].attribute = 0;
1879                 privs->set[i].luid.low = id;
1880                 privs->set[i].luid.high = 0;
1881         }
1882
1883         privs->count = el->num_values;
1884
1885         return NT_STATUS_OK;
1886 }
1887
1888 /* 
1889   lsa_EnumAccountRights 
1890 */
1891 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1892                                       TALLOC_CTX *mem_ctx,
1893                                       struct lsa_EnumAccountRights *r)
1894 {
1895         struct dcesrv_handle *h;
1896         struct lsa_policy_state *state;
1897         int ret;
1898         unsigned int i;
1899         struct ldb_message **res;
1900         const char * const attrs[] = { "privilege", NULL};
1901         const char *sidstr;
1902         struct ldb_message_element *el;
1903
1904         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1905
1906         state = h->data;
1907
1908         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1909         if (sidstr == NULL) {
1910                 return NT_STATUS_NO_MEMORY;
1911         }
1912
1913         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
1914                            "(&(objectSid=%s)(privilege=*))", sidstr);
1915         if (ret == 0) {
1916                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1917         }
1918         if (ret != 1) {
1919                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1920                           dom_sid_string(mem_ctx, r->in.sid),
1921                           ldb_errstring(state->pdb)));
1922                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1923         }
1924
1925         el = ldb_msg_find_element(res[0], "privilege");
1926         if (el == NULL || el->num_values == 0) {
1927                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1928         }
1929
1930         r->out.rights->count = el->num_values;
1931         r->out.rights->names = talloc_array(r->out.rights, 
1932                                             struct lsa_StringLarge, r->out.rights->count);
1933         if (r->out.rights->names == NULL) {
1934                 return NT_STATUS_NO_MEMORY;
1935         }
1936
1937         for (i=0;i<el->num_values;i++) {
1938                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1939         }
1940
1941         return NT_STATUS_OK;
1942 }
1943
1944
1945
1946 /* 
1947   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1948 */
1949 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1950                                            TALLOC_CTX *mem_ctx,
1951                                            struct lsa_policy_state *state,
1952                                            int ldb_flag,
1953                                            struct dom_sid *sid,
1954                                            const struct lsa_RightSet *rights)
1955 {
1956         const char *sidstr, *sidndrstr;
1957         struct ldb_message *msg;
1958         struct ldb_message_element *el;
1959         int ret;
1960         uint32_t i;
1961         struct lsa_EnumAccountRights r2;
1962         char *dnstr;
1963
1964         if (security_session_user_level(dce_call->conn->auth_state.session_info) < 
1965             SECURITY_ADMINISTRATOR) {
1966                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
1967                 return NT_STATUS_ACCESS_DENIED;
1968         }
1969
1970         msg = ldb_msg_new(mem_ctx);
1971         if (msg == NULL) {
1972                 return NT_STATUS_NO_MEMORY;
1973         }
1974
1975         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
1976         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
1977
1978         sidstr = dom_sid_string(msg, sid);
1979         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
1980
1981         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
1982         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
1983
1984         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
1985         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
1986
1987         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1988                 NTSTATUS status;
1989
1990                 r2.in.handle = &state->handle->wire_handle;
1991                 r2.in.sid = sid;
1992                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1993
1994                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1995                 if (!NT_STATUS_IS_OK(status)) {
1996                         ZERO_STRUCTP(r2.out.rights);
1997                 }
1998         }
1999
2000         for (i=0;i<rights->count;i++) {
2001                 if (sec_privilege_id(rights->names[i].string) == -1) {
2002                         talloc_free(msg);
2003                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2004                 }
2005
2006                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2007                         uint32_t j;
2008                         for (j=0;j<r2.out.rights->count;j++) {
2009                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
2010                                                rights->names[i].string) == 0) {
2011                                         break;
2012                                 }
2013                         }
2014                         if (j != r2.out.rights->count) continue;
2015                 }
2016
2017                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2018                 if (ret != LDB_SUCCESS) {
2019                         talloc_free(msg);
2020                         return NT_STATUS_NO_MEMORY;
2021                 }
2022         }
2023
2024         el = ldb_msg_find_element(msg, "privilege");
2025         if (!el) {
2026                 talloc_free(msg);
2027                 return NT_STATUS_OK;
2028         }
2029
2030         el->flags = ldb_flag;
2031
2032         ret = ldb_modify(state->pdb, msg);
2033         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2034                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2035                         talloc_free(msg);
2036                         return NT_STATUS_NO_MEMORY;
2037                 }
2038                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2039                 ret = ldb_add(state->pdb, msg);         
2040         }
2041         if (ret != LDB_SUCCESS) {
2042                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2043                         talloc_free(msg);
2044                         return NT_STATUS_OK;
2045                 }
2046                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2047                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2048                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2049                 talloc_free(msg);
2050                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2051         }
2052
2053         talloc_free(msg);
2054         return NT_STATUS_OK;
2055 }
2056
2057 /* 
2058   lsa_AddPrivilegesToAccount
2059 */
2060 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2061                                            struct lsa_AddPrivilegesToAccount *r)
2062 {
2063         struct lsa_RightSet rights;
2064         struct dcesrv_handle *h;
2065         struct lsa_account_state *astate;
2066         uint32_t i;
2067
2068         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2069
2070         astate = h->data;
2071
2072         rights.count = r->in.privs->count;
2073         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2074         if (rights.names == NULL) {
2075                 return NT_STATUS_NO_MEMORY;
2076         }
2077         for (i=0;i<rights.count;i++) {
2078                 int id = r->in.privs->set[i].luid.low;
2079                 if (r->in.privs->set[i].luid.high) {
2080                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2081                 }
2082                 rights.names[i].string = sec_privilege_name(id);
2083                 if (rights.names[i].string == NULL) {
2084                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2085                 }
2086         }
2087
2088         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2089                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2090                                           &rights);
2091 }
2092
2093
2094 /* 
2095   lsa_RemovePrivilegesFromAccount
2096 */
2097 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2098                                                 struct lsa_RemovePrivilegesFromAccount *r)
2099 {
2100         struct lsa_RightSet *rights;
2101         struct dcesrv_handle *h;
2102         struct lsa_account_state *astate;
2103         uint32_t i;
2104
2105         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2106
2107         astate = h->data;
2108
2109         rights = talloc(mem_ctx, struct lsa_RightSet);
2110
2111         if (r->in.remove_all == 1 && 
2112             r->in.privs == NULL) {
2113                 struct lsa_EnumAccountRights r2;
2114                 NTSTATUS status;
2115
2116                 r2.in.handle = &astate->policy->handle->wire_handle;
2117                 r2.in.sid = astate->account_sid;
2118                 r2.out.rights = rights;
2119
2120                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2121                 if (!NT_STATUS_IS_OK(status)) {
2122                         return status;
2123                 }
2124
2125                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2126                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2127                                                   r2.out.rights);
2128         }
2129
2130         if (r->in.remove_all != 0) {
2131                 return NT_STATUS_INVALID_PARAMETER;
2132         }
2133
2134         rights->count = r->in.privs->count;
2135         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2136         if (rights->names == NULL) {
2137                 return NT_STATUS_NO_MEMORY;
2138         }
2139         for (i=0;i<rights->count;i++) {
2140                 int id = r->in.privs->set[i].luid.low;
2141                 if (r->in.privs->set[i].luid.high) {
2142                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2143                 }
2144                 rights->names[i].string = sec_privilege_name(id);
2145                 if (rights->names[i].string == NULL) {
2146                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2147                 }
2148         }
2149
2150         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2151                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2152                                           rights);
2153 }
2154
2155
2156 /* 
2157   lsa_GetQuotasForAccount
2158 */
2159 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2160                        struct lsa_GetQuotasForAccount *r)
2161 {
2162         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2163 }
2164
2165
2166 /* 
2167   lsa_SetQuotasForAccount
2168 */
2169 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2170                        struct lsa_SetQuotasForAccount *r)
2171 {
2172         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2173 }
2174
2175
2176 /* 
2177   lsa_GetSystemAccessAccount
2178 */
2179 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2180                        struct lsa_GetSystemAccessAccount *r)
2181 {
2182         uint32_t i;
2183         NTSTATUS status;
2184         struct lsa_EnumPrivsAccount enumPrivs;
2185         struct lsa_PrivilegeSet *privs;
2186
2187         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2188         if (!privs) {
2189                 return NT_STATUS_NO_MEMORY;
2190         }
2191         privs->count = 0;
2192         privs->unknown = 0;
2193         privs->set = NULL;
2194
2195         enumPrivs.in.handle = r->in.handle;
2196         enumPrivs.out.privs = &privs;
2197
2198         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2199         if (!NT_STATUS_IS_OK(status)) {
2200                 return status;
2201         }       
2202
2203         *(r->out.access_mask) = 0x00000000;
2204
2205         for (i = 0; i < privs->count; i++) {
2206                 int priv = privs->set[i].luid.low;
2207
2208                 switch (priv) {
2209                 case SEC_PRIV_INTERACTIVE_LOGON:
2210                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2211                         break;
2212                 case SEC_PRIV_NETWORK_LOGON:
2213                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2214                         break;
2215                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2216                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2217                         break;
2218                 }
2219         }
2220
2221         return NT_STATUS_OK;
2222 }
2223
2224
2225 /* 
2226   lsa_SetSystemAccessAccount
2227 */
2228 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2229                        struct lsa_SetSystemAccessAccount *r)
2230 {
2231         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2232 }
2233
2234
2235 /* 
2236   lsa_CreateSecret 
2237 */
2238 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2239                                  struct lsa_CreateSecret *r)
2240 {
2241         struct dcesrv_handle *policy_handle;
2242         struct lsa_policy_state *policy_state;
2243         struct lsa_secret_state *secret_state;
2244         struct dcesrv_handle *handle;
2245         struct ldb_message **msgs, *msg;
2246         const char *attrs[] = {
2247                 NULL
2248         };
2249
2250         const char *name;
2251
2252         int ret;
2253
2254         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2255         ZERO_STRUCTP(r->out.sec_handle);
2256         
2257         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2258         {
2259         case SECURITY_SYSTEM:
2260         case SECURITY_ADMINISTRATOR:
2261                 break;
2262         default:
2263                 /* Users and annonymous are not allowed create secrets */
2264                 return NT_STATUS_ACCESS_DENIED;
2265         }
2266
2267         policy_state = policy_handle->data;
2268
2269         if (!r->in.name.string) {
2270                 return NT_STATUS_INVALID_PARAMETER;
2271         }
2272         
2273         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2274         if (!secret_state) {
2275                 return NT_STATUS_NO_MEMORY;
2276         }
2277         secret_state->policy = policy_state;
2278
2279         msg = ldb_msg_new(mem_ctx);
2280         if (msg == NULL) {
2281                 return NT_STATUS_NO_MEMORY;
2282         }
2283
2284         if (strncmp("G$", r->in.name.string, 2) == 0) {
2285                 const char *name2;
2286                 name = &r->in.name.string[2];
2287                         /* 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) */
2288                 secret_state->sam_ldb = talloc_reference(secret_state, 
2289                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx))); 
2290                 secret_state->global = true;
2291
2292                 if (strlen(name) < 1) {
2293                         return NT_STATUS_INVALID_PARAMETER;
2294                 }
2295
2296                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2297                 /* search for the secret record */
2298                 ret = gendb_search(secret_state->sam_ldb,
2299                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2300                                    "(&(cn=%s)(objectclass=secret))", 
2301                                    name2);
2302                 if (ret > 0) {
2303                         return NT_STATUS_OBJECT_NAME_COLLISION;
2304                 }
2305                 
2306                 if (ret < 0) {
2307                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2308                                  name2, ldb_errstring(secret_state->sam_ldb)));
2309                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2310                 }
2311
2312                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2313                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2314                         return NT_STATUS_NO_MEMORY;
2315                 }
2316                 
2317                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2318         
2319         } else {
2320                 secret_state->global = false;
2321
2322                 name = r->in.name.string;
2323                 if (strlen(name) < 1) {
2324                         return NT_STATUS_INVALID_PARAMETER;
2325                 }
2326
2327                 secret_state->sam_ldb = talloc_reference(secret_state, 
2328                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2329                 /* search for the secret record */
2330                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2331                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2332                                    &msgs, attrs,
2333                                    "(&(cn=%s)(objectclass=secret))", 
2334                                    ldb_binary_encode_string(mem_ctx, name));
2335                 if (ret > 0) {
2336                         return NT_STATUS_OBJECT_NAME_COLLISION;
2337                 }
2338                 
2339                 if (ret < 0) {
2340                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2341                                  name, ldb_errstring(secret_state->sam_ldb)));
2342                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2343                 }
2344
2345                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2346                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2347         } 
2348
2349         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2350         
2351         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2352
2353         /* create the secret */
2354         ret = ldb_add(secret_state->sam_ldb, msg);
2355         if (ret != LDB_SUCCESS) {
2356                 DEBUG(0,("Failed to create secret record %s: %s\n",
2357                          ldb_dn_get_linearized(msg->dn), 
2358                          ldb_errstring(secret_state->sam_ldb)));
2359                 return NT_STATUS_ACCESS_DENIED;
2360         }
2361
2362         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2363         if (!handle) {
2364                 return NT_STATUS_NO_MEMORY;
2365         }
2366         
2367         handle->data = talloc_steal(handle, secret_state);
2368         
2369         secret_state->access_mask = r->in.access_mask;
2370         secret_state->policy = talloc_reference(secret_state, policy_state);
2371         
2372         *r->out.sec_handle = handle->wire_handle;
2373         
2374         return NT_STATUS_OK;
2375 }
2376
2377
2378 /* 
2379   lsa_OpenSecret 
2380 */
2381 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2382                                struct lsa_OpenSecret *r)
2383 {
2384         struct dcesrv_handle *policy_handle;
2385         
2386         struct lsa_policy_state *policy_state;
2387         struct lsa_secret_state *secret_state;
2388         struct dcesrv_handle *handle;
2389         struct ldb_message **msgs;
2390         const char *attrs[] = {
2391                 NULL
2392         };
2393
2394         const char *name;
2395
2396         int ret;
2397
2398         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2399         ZERO_STRUCTP(r->out.sec_handle);
2400         policy_state = policy_handle->data;
2401
2402         if (!r->in.name.string) {
2403                 return NT_STATUS_INVALID_PARAMETER;
2404         }
2405         
2406         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2407         {
2408         case SECURITY_SYSTEM:
2409         case SECURITY_ADMINISTRATOR:
2410                 break;
2411         default:
2412                 /* Users and annonymous are not allowed to access secrets */
2413                 return NT_STATUS_ACCESS_DENIED;
2414         }
2415
2416         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2417         if (!secret_state) {
2418                 return NT_STATUS_NO_MEMORY;
2419         }
2420         secret_state->policy = policy_state;
2421
2422         if (strncmp("G$", r->in.name.string, 2) == 0) {
2423                 name = &r->in.name.string[2];
2424                 /* 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) */
2425                 secret_state->sam_ldb = talloc_reference(secret_state, 
2426                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx))); 
2427                 secret_state->global = true;
2428
2429                 if (strlen(name) < 1) {
2430                         return NT_STATUS_INVALID_PARAMETER;
2431                 }
2432
2433                 /* search for the secret record */
2434                 ret = gendb_search(secret_state->sam_ldb,
2435                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2436                                    "(&(cn=%s Secret)(objectclass=secret))", 
2437                                    ldb_binary_encode_string(mem_ctx, name));
2438                 if (ret == 0) {
2439                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2440                 }
2441                 
2442                 if (ret != 1) {
2443                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2444                                  ldb_dn_get_linearized(policy_state->system_dn)));
2445                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2446                 }
2447         
2448         } else {
2449                 secret_state->global = false;
2450                 secret_state->sam_ldb = talloc_reference(secret_state, 
2451                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2452
2453                 name = r->in.name.string;
2454                 if (strlen(name) < 1) {
2455                         return NT_STATUS_INVALID_PARAMETER;
2456                 }
2457
2458                 /* search for the secret record */
2459                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2460                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2461                                    &msgs, attrs,
2462                                    "(&(cn=%s)(objectclass=secret))", 
2463                                    ldb_binary_encode_string(mem_ctx, name));
2464                 if (ret == 0) {
2465                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2466                 }
2467                 
2468                 if (ret != 1) {
2469                         DEBUG(0,("Found %d records matching CN=%s\n", 
2470                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2471                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2472                 }
2473         } 
2474
2475         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2476         
2477         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2478         if (!handle) {
2479                 return NT_STATUS_NO_MEMORY;
2480         }
2481         
2482         handle->data = talloc_steal(handle, secret_state);
2483         
2484         secret_state->access_mask = r->in.access_mask;
2485         secret_state->policy = talloc_reference(secret_state, policy_state);
2486         
2487         *r->out.sec_handle = handle->wire_handle;
2488         
2489         return NT_STATUS_OK;
2490 }
2491
2492
2493 /* 
2494   lsa_SetSecret 
2495 */
2496 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2497                               struct lsa_SetSecret *r)
2498 {
2499
2500         struct dcesrv_handle *h;
2501         struct lsa_secret_state *secret_state;
2502         struct ldb_message *msg;
2503         DATA_BLOB session_key;
2504         DATA_BLOB crypt_secret, secret;
2505         struct ldb_val val;
2506         int ret;
2507         NTSTATUS status = NT_STATUS_OK;
2508
2509         struct timeval now = timeval_current();
2510         NTTIME nt_now = timeval_to_nttime(&now);
2511
2512         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2513
2514         secret_state = h->data;
2515
2516         msg = ldb_msg_new(mem_ctx);
2517         if (msg == NULL) {
2518                 return NT_STATUS_NO_MEMORY;
2519         }
2520
2521         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2522         if (!msg->dn) {
2523                 return NT_STATUS_NO_MEMORY;
2524         }
2525         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2526         if (!NT_STATUS_IS_OK(status)) {
2527                 return status;
2528         }
2529
2530         if (r->in.old_val) {
2531                 /* Decrypt */
2532                 crypt_secret.data = r->in.old_val->data;
2533                 crypt_secret.length = r->in.old_val->size;
2534                 
2535                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2536                 if (!NT_STATUS_IS_OK(status)) {
2537                         return status;
2538                 }
2539                 
2540                 val.data = secret.data;
2541                 val.length = secret.length;
2542                 
2543                 /* set value */
2544                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2545                                         mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
2546                         return NT_STATUS_NO_MEMORY; 
2547                 }
2548                 
2549                 /* set old value mtime */
2550                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2551                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
2552                         return NT_STATUS_NO_MEMORY; 
2553                 }
2554
2555         } else {
2556                 /* If the old value is not set, then migrate the
2557                  * current value to the old value */
2558                 const struct ldb_val *old_val;
2559                 NTTIME last_set_time;
2560                 struct ldb_message **res;
2561                 const char *attrs[] = {
2562                         "currentValue",
2563                         "lastSetTime",
2564                         NULL
2565                 };
2566                 
2567                 /* search for the secret record */
2568                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2569                                       secret_state->secret_dn, &res, attrs);
2570                 if (ret == 0) {
2571                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2572                 }
2573                 
2574                 if (ret != 1) {
2575                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2576                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2577                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2578                 }
2579                 
2580                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2581                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2582                 
2583                 if (old_val) {
2584                         /* set old value */
2585                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2586                                                 mem_ctx, msg, "priorValue", 
2587                                                 old_val) != 0) {
2588                                 return NT_STATUS_NO_MEMORY; 
2589                         }
2590                 } else {
2591                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2592                                                  mem_ctx, msg, "priorValue")) {
2593                                 return NT_STATUS_NO_MEMORY;
2594                         }
2595                         
2596                 }
2597                 
2598                 /* set old value mtime */
2599                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2600                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2601                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
2602                                 return NT_STATUS_NO_MEMORY; 
2603                         }
2604                 } else {
2605                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2606                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
2607                                 return NT_STATUS_NO_MEMORY; 
2608                         }
2609                 }
2610         }
2611
2612         if (r->in.new_val) {
2613                 /* Decrypt */
2614                 crypt_secret.data = r->in.new_val->data;
2615                 crypt_secret.length = r->in.new_val->size;
2616                 
2617                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2618                 if (!NT_STATUS_IS_OK(status)) {
2619                         return status;
2620                 }
2621                 
2622                 val.data = secret.data;
2623                 val.length = secret.length;
2624                 
2625                 /* set value */
2626                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2627                                         mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
2628                         return NT_STATUS_NO_MEMORY; 
2629                 }
2630                 
2631                 /* set new value mtime */
2632                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2633                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
2634                         return NT_STATUS_NO_MEMORY; 
2635                 }
2636                 
2637         } else {
2638                 /* NULL out the NEW value */
2639                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2640                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
2641                         return NT_STATUS_NO_MEMORY; 
2642                 }
2643                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2644                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
2645                         return NT_STATUS_NO_MEMORY;
2646                 }
2647         }
2648
2649         /* modify the samdb record */
2650         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
2651         if (ret != LDB_SUCCESS) {
2652                 /* we really need samdb.c to return NTSTATUS */
2653                 return NT_STATUS_UNSUCCESSFUL;
2654         }
2655
2656         return NT_STATUS_OK;
2657 }
2658
2659
2660 /* 
2661   lsa_QuerySecret 
2662 */
2663 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2664                                 struct lsa_QuerySecret *r)
2665 {
2666         struct dcesrv_handle *h;
2667         struct lsa_secret_state *secret_state;
2668         struct ldb_message *msg;
2669         DATA_BLOB session_key;
2670         DATA_BLOB crypt_secret, secret;
2671         int ret;
2672         struct ldb_message **res;
2673         const char *attrs[] = {
2674                 "currentValue",
2675                 "priorValue",
2676                 "lastSetTime",
2677                 "priorSetTime", 
2678                 NULL
2679         };
2680
2681         NTSTATUS nt_status;
2682
2683         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2684
2685         /* Ensure user is permitted to read this... */
2686         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2687         {
2688         case SECURITY_SYSTEM:
2689         case SECURITY_ADMINISTRATOR:
2690                 break;
2691         default:
2692                 /* Users and annonymous are not allowed to read secrets */
2693                 return NT_STATUS_ACCESS_DENIED;
2694         }
2695
2696         secret_state = h->data;
2697
2698         /* pull all the user attributes */
2699         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2700                               secret_state->secret_dn, &res, attrs);
2701         if (ret != 1) {
2702                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2703         }
2704         msg = res[0];
2705         
2706         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2707         if (!NT_STATUS_IS_OK(nt_status)) {
2708                 return nt_status;
2709         }
2710         
2711         if (r->in.old_val) {
2712                 const struct ldb_val *prior_val;
2713                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2714                 if (!r->out.old_val) {
2715                         return NT_STATUS_NO_MEMORY;
2716                 }
2717                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2718                 
2719                 if (prior_val && prior_val->length) {
2720                         secret.data = prior_val->data;
2721                         secret.length = prior_val->length;
2722                 
2723                         /* Encrypt */
2724                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2725                         if (!crypt_secret.length) {
2726                                 return NT_STATUS_NO_MEMORY;
2727                         }
2728                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2729                         if (!r->out.old_val->buf) {
2730                                 return NT_STATUS_NO_MEMORY;
2731                         }
2732                         r->out.old_val->buf->size = crypt_secret.length;
2733                         r->out.old_val->buf->length = crypt_secret.length;
2734                         r->out.old_val->buf->data = crypt_secret.data;
2735                 }
2736         }
2737         
2738         if (r->in.old_mtime) {
2739                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2740                 if (!r->out.old_mtime) {
2741                         return NT_STATUS_NO_MEMORY;
2742                 }
2743                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2744         }
2745         
2746         if (r->in.new_val) {
2747                 const struct ldb_val *new_val;
2748                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2749                 if (!r->out.new_val) {
2750                         return NT_STATUS_NO_MEMORY;
2751                 }
2752
2753                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2754                 
2755                 if (new_val && new_val->length) {
2756                         secret.data = new_val->data;
2757                         secret.length = new_val->length;
2758                 
2759                         /* Encrypt */
2760                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2761                         if (!crypt_secret.length) {
2762                                 return NT_STATUS_NO_MEMORY;
2763                         }
2764                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2765                         if (!r->out.new_val->buf) {
2766                                 return NT_STATUS_NO_MEMORY;
2767                         }
2768                         r->out.new_val->buf->length = crypt_secret.length;
2769                         r->out.new_val->buf->size = crypt_secret.length;
2770                         r->out.new_val->buf->data = crypt_secret.data;
2771                 }
2772         }
2773         
2774         if (r->in.new_mtime) {
2775                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2776                 if (!r->out.new_mtime) {
2777                         return NT_STATUS_NO_MEMORY;
2778                 }
2779                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2780         }
2781         
2782         return NT_STATUS_OK;
2783 }
2784
2785
2786 /* 
2787   lsa_LookupPrivValue
2788 */
2789 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2790                                     TALLOC_CTX *mem_ctx,
2791                                     struct lsa_LookupPrivValue *r)
2792 {
2793         struct dcesrv_handle *h;
2794         struct lsa_policy_state *state;
2795         int id;
2796
2797         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2798
2799         state = h->data;
2800
2801         id = sec_privilege_id(r->in.name->string);
2802         if (id == -1) {
2803                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2804         }
2805
2806         r->out.luid->low = id;
2807         r->out.luid->high = 0;
2808
2809         return NT_STATUS_OK;    
2810 }
2811
2812
2813 /* 
2814   lsa_LookupPrivName 
2815 */
2816 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2817                                    TALLOC_CTX *mem_ctx,
2818                                    struct lsa_LookupPrivName *r)
2819 {
2820         struct dcesrv_handle *h;
2821         struct lsa_policy_state *state;
2822         struct lsa_StringLarge *name;
2823         const char *privname;
2824
2825         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2826
2827         state = h->data;
2828
2829         if (r->in.luid->high != 0) {
2830                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2831         }
2832
2833         privname = sec_privilege_name(r->in.luid->low);
2834         if (privname == NULL) {
2835                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2836         }
2837
2838         name = talloc(mem_ctx, struct lsa_StringLarge);
2839         if (name == NULL) {
2840                 return NT_STATUS_NO_MEMORY;
2841         }
2842
2843         name->string = privname;
2844
2845         *r->out.name = name;
2846
2847         return NT_STATUS_OK;    
2848 }
2849
2850
2851 /* 
2852   lsa_LookupPrivDisplayName
2853 */
2854 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2855                                           TALLOC_CTX *mem_ctx,
2856                                           struct lsa_LookupPrivDisplayName *r)
2857 {
2858         struct dcesrv_handle *h;
2859         struct lsa_policy_state *state;
2860         struct lsa_StringLarge *disp_name = NULL;
2861         int id;
2862
2863         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2864
2865         state = h->data;
2866
2867         id = sec_privilege_id(r->in.name->string);
2868         if (id == -1) {
2869                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2870         }
2871
2872         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2873         if (disp_name == NULL) {
2874                 return NT_STATUS_NO_MEMORY;
2875         }
2876
2877         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
2878         if (disp_name->string == NULL) {
2879                 return NT_STATUS_INTERNAL_ERROR;
2880         }
2881
2882         *r->out.disp_name = disp_name;
2883         *r->out.returned_language_id = 0;
2884
2885         return NT_STATUS_OK;
2886 }
2887
2888
2889 /* 
2890   lsa_EnumAccountsWithUserRight
2891 */
2892 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2893                                               TALLOC_CTX *mem_ctx,
2894                                               struct lsa_EnumAccountsWithUserRight *r)
2895 {
2896         struct dcesrv_handle *h;
2897         struct lsa_policy_state *state;
2898         int ret, i;
2899         struct ldb_message **res;
2900         const char * const attrs[] = { "objectSid", NULL};
2901         const char *privname;
2902
2903         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2904
2905         state = h->data;
2906
2907         if (r->in.name == NULL) {
2908                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2909         } 
2910
2911         privname = r->in.name->string;
2912         if (sec_privilege_id(privname) == -1) {
2913                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2914         }
2915
2916         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2917                            "privilege=%s", privname);
2918         if (ret < 0) {
2919                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2920         }
2921         if (ret == 0) {
2922                 return NT_STATUS_NO_MORE_ENTRIES;
2923         }
2924
2925         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2926         if (r->out.sids->sids == NULL) {
2927                 return NT_STATUS_NO_MEMORY;
2928         }
2929         for (i=0;i<ret;i++) {
2930                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2931                                                                 res[i], "objectSid");
2932                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2933         }
2934         r->out.sids->num_sids = ret;
2935
2936         return NT_STATUS_OK;
2937 }
2938
2939
2940 /* 
2941   lsa_AddAccountRights
2942 */
2943 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2944                                      TALLOC_CTX *mem_ctx,
2945                                      struct lsa_AddAccountRights *r)
2946 {
2947         struct dcesrv_handle *h;
2948         struct lsa_policy_state *state;
2949
2950         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2951
2952         state = h->data;
2953
2954         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2955                                           LDB_FLAG_MOD_ADD,
2956                                           r->in.sid, r->in.rights);
2957 }
2958
2959
2960 /* 
2961   lsa_RemoveAccountRights
2962 */
2963 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2964                                         TALLOC_CTX *mem_ctx,
2965                                         struct lsa_RemoveAccountRights *r)
2966 {
2967         struct dcesrv_handle *h;
2968         struct lsa_policy_state *state;
2969
2970         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2971
2972         state = h->data;
2973
2974         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2975                                           LDB_FLAG_MOD_DELETE,
2976                                           r->in.sid, r->in.rights);
2977 }
2978
2979
2980 /* 
2981   lsa_StorePrivateData
2982 */
2983 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2984                        struct lsa_StorePrivateData *r)
2985 {
2986         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2987 }
2988
2989
2990 /* 
2991   lsa_RetrievePrivateData
2992 */
2993 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994                        struct lsa_RetrievePrivateData *r)
2995 {
2996         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2997 }
2998
2999
3000 /* 
3001   lsa_GetUserName
3002 */
3003 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3004                                 struct lsa_GetUserName *r)
3005 {
3006         NTSTATUS status = NT_STATUS_OK;
3007         const char *account_name;
3008         const char *authority_name;
3009         struct lsa_String *_account_name;
3010         struct lsa_String *_authority_name = NULL;
3011
3012         /* this is what w2k3 does */
3013         r->out.account_name = r->in.account_name;
3014         r->out.authority_name = r->in.authority_name;
3015
3016         if (r->in.account_name
3017             && *r->in.account_name
3018             /* && *(*r->in.account_name)->string */
3019             ) {
3020                 return NT_STATUS_INVALID_PARAMETER;
3021         }
3022
3023         if (r->in.authority_name
3024             && *r->in.authority_name
3025             /* && *(*r->in.authority_name)->string */
3026             ) {
3027                 return NT_STATUS_INVALID_PARAMETER;
3028         }
3029
3030         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3031         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3032
3033         _account_name = talloc(mem_ctx, struct lsa_String);
3034         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3035         _account_name->string = account_name;
3036
3037         if (r->in.authority_name) {
3038                 _authority_name = talloc(mem_ctx, struct lsa_String);
3039                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3040                 _authority_name->string = authority_name;
3041         }
3042
3043         *r->out.account_name = _account_name;
3044         if (r->out.authority_name) {
3045                 *r->out.authority_name = _authority_name;
3046         }
3047
3048         return status;
3049 }
3050
3051 /*
3052   lsa_SetInfoPolicy2
3053 */
3054 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3055                                    TALLOC_CTX *mem_ctx,
3056                                    struct lsa_SetInfoPolicy2 *r)
3057 {
3058         /* need to support these */
3059         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3060 }
3061
3062 /*
3063   lsa_QueryDomainInformationPolicy
3064 */
3065 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3066                                                  TALLOC_CTX *mem_ctx,
3067                                                  struct lsa_QueryDomainInformationPolicy *r)
3068 {
3069         union lsa_DomainInformationPolicy *info;
3070
3071         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3072         if (!info) {
3073                 return NT_STATUS_NO_MEMORY;
3074         }
3075
3076         switch (r->in.level) {
3077         case LSA_DOMAIN_INFO_POLICY_EFS:
3078                 talloc_free(info);
3079                 *r->out.info = NULL;
3080                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3081         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3082         {
3083                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3084                 struct smb_krb5_context *smb_krb5_context;
3085                 int ret = smb_krb5_init_context(mem_ctx, 
3086                                                         dce_call->event_ctx, 
3087                                                         dce_call->conn->dce_ctx->lp_ctx,
3088                                                         &smb_krb5_context);
3089                 if (ret != 0) {
3090                         talloc_free(info);
3091                         *r->out.info = NULL;
3092                         return NT_STATUS_INTERNAL_ERROR;
3093                 }
3094                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3095                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3096                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3097                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3098                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3099                 talloc_free(smb_krb5_context);
3100                 *r->out.info = info;
3101                 return NT_STATUS_OK;
3102         }
3103         default:
3104                 talloc_free(info);
3105                 *r->out.info = NULL;
3106                 return NT_STATUS_INVALID_INFO_CLASS;
3107         }
3108 }
3109
3110 /*
3111   lsa_SetDomInfoPolicy
3112 */
3113 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3114                                               TALLOC_CTX *mem_ctx,
3115                                               struct lsa_SetDomainInformationPolicy *r)
3116 {
3117         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3118 }
3119
3120 /*
3121   lsa_TestCall
3122 */
3123 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3124                              TALLOC_CTX *mem_ctx,
3125                              struct lsa_TestCall *r)
3126 {
3127         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3128 }
3129
3130 /* 
3131   lsa_CREDRWRITE 
3132 */
3133 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3134                        struct lsa_CREDRWRITE *r)
3135 {
3136         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3137 }
3138
3139
3140 /* 
3141   lsa_CREDRREAD 
3142 */
3143 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3144                        struct lsa_CREDRREAD *r)
3145 {
3146         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3147 }
3148
3149
3150 /* 
3151   lsa_CREDRENUMERATE 
3152 */
3153 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3154                        struct lsa_CREDRENUMERATE *r)
3155 {
3156         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3157 }
3158
3159
3160 /* 
3161   lsa_CREDRWRITEDOMAINCREDENTIALS 
3162 */
3163 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3164                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3165 {
3166         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3167 }
3168
3169
3170 /* 
3171   lsa_CREDRREADDOMAINCREDENTIALS 
3172 */
3173 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3174                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3175 {
3176         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3177 }
3178
3179
3180 /* 
3181   lsa_CREDRDELETE 
3182 */
3183 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3184                        struct lsa_CREDRDELETE *r)
3185 {
3186         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3187 }
3188
3189
3190 /* 
3191   lsa_CREDRGETTARGETINFO 
3192 */
3193 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3194                        struct lsa_CREDRGETTARGETINFO *r)
3195 {
3196         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3197 }
3198
3199
3200 /* 
3201   lsa_CREDRPROFILELOADED 
3202 */
3203 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3204                        struct lsa_CREDRPROFILELOADED *r)
3205 {
3206         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3207 }
3208
3209
3210 /* 
3211   lsa_CREDRGETSESSIONTYPES 
3212 */
3213 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3214                        struct lsa_CREDRGETSESSIONTYPES *r)
3215 {
3216         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3217 }
3218
3219
3220 /* 
3221   lsa_LSARREGISTERAUDITEVENT 
3222 */
3223 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3224                        struct lsa_LSARREGISTERAUDITEVENT *r)
3225 {
3226         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3227 }
3228
3229
3230 /* 
3231   lsa_LSARGENAUDITEVENT 
3232 */
3233 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3234                        struct lsa_LSARGENAUDITEVENT *r)
3235 {
3236         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3237 }
3238
3239
3240 /* 
3241   lsa_LSARUNREGISTERAUDITEVENT 
3242 */
3243 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3244                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3245 {
3246         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3247 }
3248
3249
3250 /* 
3251   lsa_lsaRQueryForestTrustInformation 
3252 */
3253 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3254                        struct lsa_lsaRQueryForestTrustInformation *r)
3255 {
3256         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3257 }
3258
3259
3260 /* 
3261   lsa_lsaRSetForestTrustInformation
3262 */
3263 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3264                        struct lsa_lsaRSetForestTrustInformation *r)
3265 {
3266         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3267 }
3268
3269
3270 /* 
3271   lsa_CREDRRENAME 
3272 */
3273 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3274                        struct lsa_CREDRRENAME *r)
3275 {
3276         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3277 }
3278
3279
3280
3281 /* 
3282   lsa_LSAROPENPOLICYSCE 
3283 */
3284 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3285                        struct lsa_LSAROPENPOLICYSCE *r)
3286 {
3287         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3288 }
3289
3290
3291 /* 
3292   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
3293 */
3294 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3295                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
3296 {
3297         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3298 }
3299
3300
3301 /* 
3302   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
3303 */
3304 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3305                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
3306 {
3307         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3308 }
3309
3310
3311 /* 
3312   lsa_LSARADTREPORTSECURITYEVENT 
3313 */
3314 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3315                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
3316 {
3317         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3318 }
3319
3320
3321 /* include the generated boilerplate */
3322 #include "librpc/gen_ndr/ndr_lsa_s.c"
3323
3324
3325
3326 /*****************************************
3327 NOTE! The remaining calls below were
3328 removed in w2k3, so the DCESRV_FAULT()
3329 replies are the correct implementation. Do
3330 not try and fill these in with anything else
3331 ******************************************/
3332
3333 /* 
3334   dssetup_DsRoleDnsNameToFlatName 
3335 */
3336 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3337                                         struct dssetup_DsRoleDnsNameToFlatName *r)
3338 {
3339         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3340 }
3341
3342
3343 /* 
3344   dssetup_DsRoleDcAsDc 
3345 */
3346 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3347                              struct dssetup_DsRoleDcAsDc *r)
3348 {
3349         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3350 }
3351
3352
3353 /* 
3354   dssetup_DsRoleDcAsReplica 
3355 */
3356 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3357                                   struct dssetup_DsRoleDcAsReplica *r)
3358 {
3359         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3360 }
3361
3362
3363 /* 
3364   dssetup_DsRoleDemoteDc 
3365 */
3366 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3367                                struct dssetup_DsRoleDemoteDc *r)
3368 {
3369         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3370 }
3371
3372
3373 /* 
3374   dssetup_DsRoleGetDcOperationProgress 
3375 */
3376 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3377                                              struct dssetup_DsRoleGetDcOperationProgress *r)
3378 {
3379         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3380 }
3381
3382
3383 /* 
3384   dssetup_DsRoleGetDcOperationResults 
3385 */
3386 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3387                                             struct dssetup_DsRoleGetDcOperationResults *r)
3388 {
3389         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3390 }
3391
3392
3393 /* 
3394   dssetup_DsRoleCancel 
3395 */
3396 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3397                              struct dssetup_DsRoleCancel *r)
3398 {
3399         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3400 }
3401
3402
3403 /* 
3404   dssetup_DsRoleServerSaveStateForUpgrade 
3405 */
3406 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3407                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
3408 {
3409         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3410 }
3411
3412
3413 /* 
3414   dssetup_DsRoleUpgradeDownlevelServer 
3415 */
3416 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3417                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
3418 {
3419         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3420 }
3421
3422
3423 /* 
3424   dssetup_DsRoleAbortDownlevelServerUpgrade 
3425 */
3426 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3427                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
3428 {
3429         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3430 }
3431
3432
3433 /* include the generated boilerplate */
3434 #include "librpc/gen_ndr/ndr_dssetup_s.c"
3435
3436 NTSTATUS dcerpc_server_lsa_init(void)
3437 {
3438         NTSTATUS ret;
3439         
3440         ret = dcerpc_server_dssetup_init();
3441         if (!NT_STATUS_IS_OK(ret)) {
3442                 return ret;
3443         }
3444         ret = dcerpc_server_lsarpc_init();
3445         if (!NT_STATUS_IS_OK(ret)) {
3446                 return ret;
3447         }
3448         return ret;
3449 }