s4:lsa cleanup trailing spaces and tabs
[kamenim/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         int 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, i;
686         struct ldb_message **res;
687         const char * const attrs[] = { "objectSid", NULL};
688         uint32_t count;
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_NO_SUCH_USER;
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
737 /*
738   lsa_CreateTrustedDomainEx2
739 */
740 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
741                                                     TALLOC_CTX *mem_ctx,
742                                                     struct lsa_CreateTrustedDomainEx2 *r,
743                                                     int op)
744 {
745         struct dcesrv_handle *policy_handle;
746         struct lsa_policy_state *policy_state;
747         struct lsa_trusted_domain_state *trusted_domain_state;
748         struct dcesrv_handle *handle;
749         struct ldb_message **msgs, *msg, *msg_user;
750         const char *attrs[] = {
751                 NULL
752         };
753         const char *netbios_name;
754         const char *dns_name;
755         const char *name;
756         DATA_BLOB session_key = data_blob(NULL, 0);
757         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
758         struct trustDomainPasswords auth_struct;
759         int ret;
760         NTSTATUS nt_status;
761         enum ndr_err_code ndr_err;
762
763         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
764         ZERO_STRUCTP(r->out.trustdom_handle);
765
766         policy_state = policy_handle->data;
767
768         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
769         if (!NT_STATUS_IS_OK(nt_status)) {
770                 return nt_status;
771         }
772
773         netbios_name = r->in.info->netbios_name.string;
774         if (!netbios_name) {
775                 return NT_STATUS_INVALID_PARAMETER;
776         }
777
778         dns_name = r->in.info->domain_name.string;
779
780         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
781         if (!trusted_domain_state) {
782                 return NT_STATUS_NO_MEMORY;
783         }
784         trusted_domain_state->policy = policy_state;
785
786         if (strcasecmp(netbios_name, "BUILTIN") == 0
787             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
788             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
789                 return NT_STATUS_INVALID_PARAMETER;;
790         }
791
792         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
793             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
794             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
795             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
796             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
797                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
798         }
799
800         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
801         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
802                 /* No secrets are created at this time, for this function */
803                 auth_struct.outgoing.count = 0;
804                 auth_struct.incoming.count = 0;
805         } else {
806                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size);
807                 arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
808                 ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx,
809                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
810                                                &auth_struct,
811                                                (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
812                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
813                         return NT_STATUS_INVALID_PARAMETER;
814                 }
815
816                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
817                         if (auth_struct.incoming.count > 1) {
818                                 return NT_STATUS_INVALID_PARAMETER;
819                         }
820                 }
821         }
822
823         if (auth_struct.incoming.count) {
824                 int i;
825                 struct trustAuthInOutBlob incoming;
826
827                 incoming.count = auth_struct.incoming.count;
828                 incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
829                 if (!incoming.current) {
830                         return NT_STATUS_NO_MEMORY;
831                 }
832
833                 incoming.current->array = *auth_struct.incoming.current;
834                 if (!incoming.current->array) {
835                         return NT_STATUS_NO_MEMORY;
836                 }
837
838                 incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
839                 if (!incoming.previous) {
840                         return NT_STATUS_NO_MEMORY;
841                 }
842                 incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
843                 if (!incoming.previous->array) {
844                         return NT_STATUS_NO_MEMORY;
845                 }
846
847                 for (i = 0; i < incoming.count; i++) {
848                         incoming.previous->array[i].LastUpdateTime = 0;
849                         incoming.previous->array[i].AuthType = 0;
850                 }
851                 ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx,
852                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
853                                                &incoming,
854                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
855                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
856                         return NT_STATUS_INVALID_PARAMETER;
857                 }
858         } else {
859                 trustAuthIncoming = data_blob(NULL, 0);
860         }
861
862         if (auth_struct.outgoing.count) {
863                 int i;
864                 struct trustAuthInOutBlob outgoing;
865
866                 outgoing.count = auth_struct.outgoing.count;
867                 outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
868                 if (!outgoing.current) {
869                         return NT_STATUS_NO_MEMORY;
870                 }
871
872                 outgoing.current->array = *auth_struct.outgoing.current;
873                 if (!outgoing.current->array) {
874                         return NT_STATUS_NO_MEMORY;
875                 }
876
877                 outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
878                 if (!outgoing.previous) {
879                         return NT_STATUS_NO_MEMORY;
880                 }
881                 outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
882                 if (!outgoing.previous->array) {
883                         return NT_STATUS_NO_MEMORY;
884                 }
885
886                 for (i = 0; i < outgoing.count; i++) {
887                         outgoing.previous->array[i].LastUpdateTime = 0;
888                         outgoing.previous->array[i].AuthType = 0;
889                 }
890                 ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx,
891                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
892                                                &outgoing,
893                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
894                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
895                         return NT_STATUS_INVALID_PARAMETER;
896                 }
897         } else {
898                 trustAuthOutgoing = data_blob(NULL, 0);
899         }
900
901         ret = ldb_transaction_start(policy_state->sam_ldb);
902         if (ret != LDB_SUCCESS) {
903                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
904         }
905
906         if (dns_name) {
907                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
908                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
909                 /* search for the trusted_domain record */
910                 ret = gendb_search(policy_state->sam_ldb,
911                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
912                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
913                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
914                 if (ret > 0) {
915                         ldb_transaction_cancel(policy_state->sam_ldb);
916                         return NT_STATUS_OBJECT_NAME_COLLISION;
917                 }
918         } else {
919                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
920                 /* search for the trusted_domain record */
921                 ret = gendb_search(policy_state->sam_ldb,
922                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
923                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
924                                    netbios_encoded, netbios_encoded, netbios_encoded);
925                 if (ret > 0) {
926                         ldb_transaction_cancel(policy_state->sam_ldb);
927                         return NT_STATUS_OBJECT_NAME_COLLISION;
928                 }
929         }
930
931         if (ret < 0 ) {
932                 ldb_transaction_cancel(policy_state->sam_ldb);
933                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
934         }
935
936         name = dns_name ? dns_name : netbios_name;
937
938         msg = ldb_msg_new(mem_ctx);
939         if (msg == NULL) {
940                 return NT_STATUS_NO_MEMORY;
941         }
942
943         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
944         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
945                         ldb_transaction_cancel(policy_state->sam_ldb);
946                 return NT_STATUS_NO_MEMORY;
947         }
948
949         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name);
950
951         if (r->in.info->sid) {
952                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
953                 if (!sid_string) {
954                         ldb_transaction_cancel(policy_state->sam_ldb);
955                         return NT_STATUS_NO_MEMORY;
956                 }
957
958                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
959         }
960
961         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
962
963         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
964
965         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
966
967         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
968
969         if (dns_name) {
970                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
971         }
972
973         if (trustAuthIncoming.data) {
974                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
975                 if (ret != LDB_SUCCESS) {
976                         ldb_transaction_cancel(policy_state->sam_ldb);
977                         return NT_STATUS_NO_MEMORY;
978                 }
979         }
980         if (trustAuthOutgoing.data) {
981                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
982                 if (ret != LDB_SUCCESS) {
983                         ldb_transaction_cancel(policy_state->sam_ldb);
984                         return NT_STATUS_NO_MEMORY;
985                 }
986         }
987
988         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
989
990         /* create the trusted_domain */
991         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
992         switch (ret) {
993         case  LDB_SUCCESS:
994                 break;
995         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
996                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
997                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
998                          ldb_dn_get_linearized(msg->dn),
999                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1000                 return NT_STATUS_DOMAIN_EXISTS;
1001         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1002                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1003                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1004                          ldb_dn_get_linearized(msg->dn),
1005                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1006                 return NT_STATUS_ACCESS_DENIED;
1007         default:
1008                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1009                 DEBUG(0,("Failed to create user record %s: %s\n",
1010                          ldb_dn_get_linearized(msg->dn),
1011                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1012                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1013         }
1014
1015         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1016                 msg_user = ldb_msg_new(mem_ctx);
1017                 if (msg_user == NULL) {
1018                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1019                         return NT_STATUS_NO_MEMORY;
1020                 }
1021
1022                 /* Inbound trusts must also create a cn=users object to match */
1023
1024                 trusted_domain_state->trusted_domain_user_dn = msg_user->dn
1025                         = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
1026                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
1027                         ldb_transaction_cancel(policy_state->sam_ldb);
1028                         return NT_STATUS_NO_MEMORY;
1029                 }
1030
1031                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
1032                         ldb_transaction_cancel(policy_state->sam_ldb);
1033                         return NT_STATUS_NO_MEMORY;
1034                 }
1035
1036                 ldb_msg_add_string(msg_user, "objectClass", "user");
1037
1038                 ldb_msg_add_steal_string(msg_user, "samAccountName",
1039                                          talloc_asprintf(mem_ctx, "%s$", netbios_name));
1040
1041                 if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user,
1042                                        "userAccountControl",
1043                                        UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) {
1044                         ldb_transaction_cancel(policy_state->sam_ldb);
1045                         return NT_STATUS_NO_MEMORY;
1046                 }
1047
1048                 if (auth_struct.incoming.count) {
1049                         int i;
1050                         for (i=0; i < auth_struct.incoming.count; i++ ) {
1051                                 if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
1052                                         samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
1053                                                            mem_ctx, msg_user, "unicodePwd",
1054                                                            &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
1055                                 } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
1056                                         DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
1057                                                                                  auth_struct.incoming.current[i]->AuthInfo.clear.size);
1058                                         ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
1059                                         if (ret != LDB_SUCCESS) {
1060                                                 ldb_transaction_cancel(policy_state->sam_ldb);
1061                                                 return NT_STATUS_NO_MEMORY;
1062                                         }
1063                                 }
1064                         }
1065                 }
1066
1067                 /* create the cn=users trusted_domain account */
1068                 ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg_user);
1069                 switch (ret) {
1070                 case  LDB_SUCCESS:
1071                         break;
1072                 case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1073                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1074                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1075                                  ldb_dn_get_linearized(msg_user->dn),
1076                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1077                         return NT_STATUS_DOMAIN_EXISTS;
1078                 case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1079                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1080                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1081                                  ldb_dn_get_linearized(msg_user->dn),
1082                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1083                         return NT_STATUS_ACCESS_DENIED;
1084                 default:
1085                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1086                         DEBUG(0,("Failed to create user record %s: %s\n",
1087                                  ldb_dn_get_linearized(msg_user->dn),
1088                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1089                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1090                 }
1091         }
1092
1093         ret = ldb_transaction_commit(policy_state->sam_ldb);
1094         if (ret != LDB_SUCCESS) {
1095                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1096         }
1097
1098         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1099         if (!handle) {
1100                 return NT_STATUS_NO_MEMORY;
1101         }
1102
1103         handle->data = talloc_steal(handle, trusted_domain_state);
1104
1105         trusted_domain_state->access_mask = r->in.access_mask;
1106         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1107
1108         *r->out.trustdom_handle = handle->wire_handle;
1109
1110         return NT_STATUS_OK;
1111 }
1112
1113 /*
1114   lsa_CreateTrustedDomainEx2
1115 */
1116 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1117                                            TALLOC_CTX *mem_ctx,
1118                                            struct lsa_CreateTrustedDomainEx2 *r)
1119 {
1120         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1121 }
1122 /*
1123   lsa_CreateTrustedDomainEx
1124 */
1125 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1126                                           TALLOC_CTX *mem_ctx,
1127                                           struct lsa_CreateTrustedDomainEx *r)
1128 {
1129         struct lsa_CreateTrustedDomainEx2 r2;
1130
1131         r2.in.policy_handle = r->in.policy_handle;
1132         r2.in.info = r->in.info;
1133         r2.in.auth_info = r->in.auth_info;
1134         r2.out.trustdom_handle = r->out.trustdom_handle;
1135         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1136 }
1137
1138 /* 
1139   lsa_CreateTrustedDomain 
1140 */
1141 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1142                                         struct lsa_CreateTrustedDomain *r)
1143 {
1144         struct lsa_CreateTrustedDomainEx2 r2;
1145
1146         r2.in.policy_handle = r->in.policy_handle;
1147         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1148         if (!r2.in.info) {
1149                 return NT_STATUS_NO_MEMORY;
1150         }
1151
1152         r2.in.info->domain_name.string = NULL;
1153         r2.in.info->netbios_name = r->in.info->name;
1154         r2.in.info->sid = r->in.info->sid;
1155         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1156         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1157         r2.in.info->trust_attributes = 0;
1158         
1159         r2.in.access_mask = r->in.access_mask;
1160         r2.out.trustdom_handle = r->out.trustdom_handle;
1161
1162         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1163                          
1164 }
1165
1166 /* 
1167   lsa_OpenTrustedDomain
1168 */
1169 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1170                                       struct lsa_OpenTrustedDomain *r)
1171 {
1172         struct dcesrv_handle *policy_handle;
1173         
1174         struct lsa_policy_state *policy_state;
1175         struct lsa_trusted_domain_state *trusted_domain_state;
1176         struct dcesrv_handle *handle;
1177         struct ldb_message **msgs;
1178         const char *attrs[] = {
1179                 "trustDirection",
1180                 "flatname",
1181                 NULL
1182         };
1183
1184         const char *sid_string;
1185         int ret;
1186
1187         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1188         ZERO_STRUCTP(r->out.trustdom_handle);
1189         policy_state = policy_handle->data;
1190
1191         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1192         if (!trusted_domain_state) {
1193                 return NT_STATUS_NO_MEMORY;
1194         }
1195         trusted_domain_state->policy = policy_state;
1196
1197         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1198         if (!sid_string) {
1199                 return NT_STATUS_NO_MEMORY;
1200         }
1201
1202         /* search for the trusted_domain record */
1203         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1204                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1205                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
1206                            sid_string);
1207         if (ret == 0) {
1208                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1209         }
1210         
1211         if (ret != 1) {
1212                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1213                          ldb_dn_get_linearized(policy_state->system_dn)));
1214                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1215         }
1216
1217         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1218
1219         trusted_domain_state->trusted_domain_user_dn = NULL;
1220
1221         if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1222                 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1223                 /* search for the trusted_domain record */
1224                 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1225                                    mem_ctx, policy_state->domain_dn, &msgs, attrs,
1226                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))", 
1227                                    flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1228                 if (ret == 1) {
1229                         trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1230                 }
1231         }
1232         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1233         if (!handle) {
1234                 return NT_STATUS_NO_MEMORY;
1235         }
1236         
1237         handle->data = talloc_steal(handle, trusted_domain_state);
1238         
1239         trusted_domain_state->access_mask = r->in.access_mask;
1240         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1241         
1242         *r->out.trustdom_handle = handle->wire_handle;
1243         
1244         return NT_STATUS_OK;
1245 }
1246
1247
1248 /*
1249   lsa_OpenTrustedDomainByName
1250 */
1251 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1252                                             TALLOC_CTX *mem_ctx,
1253                                             struct lsa_OpenTrustedDomainByName *r)
1254 {
1255         struct dcesrv_handle *policy_handle;
1256
1257         struct lsa_policy_state *policy_state;
1258         struct lsa_trusted_domain_state *trusted_domain_state;
1259         struct dcesrv_handle *handle;
1260         struct ldb_message **msgs;
1261         const char *attrs[] = {
1262                 NULL
1263         };
1264         char *td_name;
1265         int ret;
1266
1267         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1268         ZERO_STRUCTP(r->out.trustdom_handle);
1269         policy_state = policy_handle->data;
1270
1271         if (!r->in.name.string) {
1272                 return NT_STATUS_INVALID_PARAMETER;
1273         }
1274
1275         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1276         if (!trusted_domain_state) {
1277                 return NT_STATUS_NO_MEMORY;
1278         }
1279         trusted_domain_state->policy = policy_state;
1280
1281         /* search for the trusted_domain record */
1282         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1283         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1284                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1285                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1286                              "(objectclass=trustedDomain))",
1287                            td_name, td_name, td_name);
1288         if (ret == 0) {
1289                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1290         }
1291
1292         if (ret != 1) {
1293                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1294                          ldb_dn_get_linearized(policy_state->system_dn)));
1295                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1296         }
1297
1298         /* TODO: perform access checks */
1299
1300         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1301
1302         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1303         if (!handle) {
1304                 return NT_STATUS_NO_MEMORY;
1305         }
1306
1307         handle->data = talloc_steal(handle, trusted_domain_state);
1308
1309         trusted_domain_state->access_mask = r->in.access_mask;
1310         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1311
1312         *r->out.trustdom_handle = handle->wire_handle;
1313
1314         return NT_STATUS_OK;
1315 }
1316
1317
1318
1319 /* 
1320   lsa_SetTrustedDomainInfo
1321 */
1322 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1323                                          struct lsa_SetTrustedDomainInfo *r)
1324 {
1325         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1326 }
1327
1328
1329
1330 /* 
1331   lsa_SetInfomrationTrustedDomain
1332 */
1333 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
1334                                                 TALLOC_CTX *mem_ctx,
1335                                                 struct lsa_SetInformationTrustedDomain *r)
1336 {
1337         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1338 }
1339
1340
1341 /* 
1342   lsa_DeleteTrustedDomain
1343 */
1344 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1345                                       struct lsa_DeleteTrustedDomain *r)
1346 {
1347         NTSTATUS status;
1348         struct lsa_OpenTrustedDomain opn;
1349         struct lsa_DeleteObject del;
1350         struct dcesrv_handle *h;
1351
1352         opn.in.handle = r->in.handle;
1353         opn.in.sid = r->in.dom_sid;
1354         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1355         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1356         if (!opn.out.trustdom_handle) {
1357                 return NT_STATUS_NO_MEMORY;
1358         }
1359         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1360         if (!NT_STATUS_IS_OK(status)) {
1361                 return status;
1362         }
1363
1364         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1365         talloc_steal(mem_ctx, h);
1366
1367         del.in.handle = opn.out.trustdom_handle;
1368         del.out.handle = opn.out.trustdom_handle;
1369         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1370         if (!NT_STATUS_IS_OK(status)) {
1371                 return status;
1372         }
1373         return NT_STATUS_OK;
1374 }
1375
1376 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1377                                      struct ldb_message *msg, 
1378                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1379 {
1380         info_ex->domain_name.string
1381                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1382         info_ex->netbios_name.string
1383                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1384         info_ex->sid 
1385                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1386         info_ex->trust_direction
1387                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1388         info_ex->trust_type
1389                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1390         info_ex->trust_attributes
1391                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1392         return NT_STATUS_OK;
1393 }
1394
1395 /* 
1396   lsa_QueryTrustedDomainInfo
1397 */
1398 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1399                                            struct lsa_QueryTrustedDomainInfo *r)
1400 {
1401         union lsa_TrustedDomainInfo *info = NULL;
1402         struct dcesrv_handle *h;
1403         struct lsa_trusted_domain_state *trusted_domain_state;
1404         struct ldb_message *msg;
1405         int ret;
1406         struct ldb_message **res;
1407         const char *attrs[] = {
1408                 "flatname", 
1409                 "trustPartner",
1410                 "securityIdentifier",
1411                 "trustDirection",
1412                 "trustType",
1413                 "trustAttributes", 
1414                 "msDs-supportedEncryptionTypes",
1415                 NULL
1416         };
1417
1418         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1419
1420         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1421
1422         /* pull all the user attributes */
1423         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1424                               trusted_domain_state->trusted_domain_dn, &res, attrs);
1425         if (ret != 1) {
1426                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1427         }
1428         msg = res[0];
1429         
1430         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
1431         if (!info) {
1432                 return NT_STATUS_NO_MEMORY;
1433         }
1434         *r->out.info = info;
1435
1436         switch (r->in.level) {
1437         case LSA_TRUSTED_DOMAIN_INFO_NAME:
1438                 info->name.netbios_name.string
1439                         = samdb_result_string(msg, "flatname", NULL);                                      
1440                 break;
1441         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1442                 info->posix_offset.posix_offset
1443                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1444                 break;
1445 #if 0  /* Win2k3 doesn't implement this */
1446         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
1447                 r->out.info->info_basic.netbios_name.string 
1448                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1449                 r->out.info->info_basic.sid
1450                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1451                 break;
1452 #endif
1453         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1454                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
1455
1456         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1457                 ZERO_STRUCT(info->full_info);
1458                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
1459
1460         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
1461                 ZERO_STRUCT(info->full_info2_internal);
1462                 info->full_info2_internal.posix_offset.posix_offset
1463                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1464                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
1465                 
1466         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1467                 info->enc_types.enc_types
1468                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
1469                 break;
1470
1471         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
1472         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
1473                 /* oops, we don't want to return the info after all */
1474                 talloc_free(info);
1475                 *r->out.info = NULL;
1476                 return NT_STATUS_INVALID_PARAMETER;
1477         default:
1478                 /* oops, we don't want to return the info after all */
1479                 talloc_free(info);
1480                 *r->out.info = NULL;
1481                 return NT_STATUS_INVALID_INFO_CLASS;
1482         }
1483
1484         return NT_STATUS_OK;
1485 }
1486
1487
1488 /* 
1489   lsa_QueryTrustedDomainInfoBySid
1490 */
1491 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1492                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
1493 {
1494         NTSTATUS status;
1495         struct lsa_OpenTrustedDomain opn;
1496         struct lsa_QueryTrustedDomainInfo query;
1497         struct dcesrv_handle *h;
1498
1499         opn.in.handle = r->in.handle;
1500         opn.in.sid = r->in.dom_sid;
1501         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1502         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1503         if (!opn.out.trustdom_handle) {
1504                 return NT_STATUS_NO_MEMORY;
1505         }
1506         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1507         if (!NT_STATUS_IS_OK(status)) {
1508                 return status;
1509         }
1510
1511         /* Ensure this handle goes away at the end of this call */
1512         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1513         talloc_steal(mem_ctx, h);
1514
1515         query.in.trustdom_handle = opn.out.trustdom_handle;
1516         query.in.level = r->in.level;
1517         query.out.info = r->out.info;
1518         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1519         if (!NT_STATUS_IS_OK(status)) {
1520                 return status;
1521         }
1522
1523         return NT_STATUS_OK;
1524 }
1525
1526 /*
1527   lsa_SetTrustedDomainInfoByName
1528 */
1529 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1530                                                TALLOC_CTX *mem_ctx,
1531                                                struct lsa_SetTrustedDomainInfoByName *r)
1532 {
1533         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1534 }
1535
1536 /* 
1537    lsa_QueryTrustedDomainInfoByName
1538 */
1539 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1540                                                  TALLOC_CTX *mem_ctx,
1541                                                  struct lsa_QueryTrustedDomainInfoByName *r)
1542 {
1543         NTSTATUS status;
1544         struct lsa_OpenTrustedDomainByName opn;
1545         struct lsa_QueryTrustedDomainInfo query;
1546         struct dcesrv_handle *h;
1547
1548         opn.in.handle = r->in.handle;
1549         opn.in.name = *r->in.trusted_domain;
1550         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1551         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1552         if (!opn.out.trustdom_handle) {
1553                 return NT_STATUS_NO_MEMORY;
1554         }
1555         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
1556         if (!NT_STATUS_IS_OK(status)) {
1557                 return status;
1558         }
1559         
1560         /* Ensure this handle goes away at the end of this call */
1561         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1562         talloc_steal(mem_ctx, h);
1563
1564         query.in.trustdom_handle = opn.out.trustdom_handle;
1565         query.in.level = r->in.level;
1566         query.out.info = r->out.info;
1567         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1568         if (!NT_STATUS_IS_OK(status)) {
1569                 return status;
1570         }
1571         
1572         return NT_STATUS_OK;
1573 }
1574
1575 /*
1576   lsa_CloseTrustedDomainEx 
1577 */
1578 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
1579                                          TALLOC_CTX *mem_ctx,
1580                                          struct lsa_CloseTrustedDomainEx *r)
1581 {
1582         /* The result of a bad hair day from an IDL programmer?  Not
1583          * implmented in Win2k3.  You should always just lsa_Close
1584          * anyway. */
1585         return NT_STATUS_NOT_IMPLEMENTED;
1586 }
1587
1588
1589 /*
1590   comparison function for sorting lsa_DomainInformation array
1591 */
1592 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
1593 {
1594         return strcasecmp_m(e1->name.string, e2->name.string);
1595 }
1596
1597 /* 
1598   lsa_EnumTrustDom 
1599 */
1600 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1601                                  struct lsa_EnumTrustDom *r)
1602 {
1603         struct dcesrv_handle *policy_handle;
1604         struct lsa_DomainInfo *entries;
1605         struct lsa_policy_state *policy_state;
1606         struct ldb_message **domains;
1607         const char *attrs[] = {
1608                 "flatname", 
1609                 "securityIdentifier",
1610                 NULL
1611         };
1612
1613
1614         int count, i;
1615
1616         *r->out.resume_handle = 0;
1617
1618         r->out.domains->domains = NULL;
1619         r->out.domains->count = 0;
1620
1621         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1622
1623         policy_state = policy_handle->data;
1624
1625         /* search for all users in this domain. This could possibly be cached and 
1626            resumed based on resume_key */
1627         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1628                              "objectclass=trustedDomain");
1629         if (count == -1) {
1630                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1631         }
1632
1633         /* convert to lsa_TrustInformation format */
1634         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
1635         if (!entries) {
1636                 return NT_STATUS_NO_MEMORY;
1637         }
1638         for (i=0;i<count;i++) {
1639                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
1640                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
1641         }
1642
1643         /* sort the results by name */
1644         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
1645
1646         if (*r->in.resume_handle >= count) {
1647                 *r->out.resume_handle = -1;
1648
1649                 return NT_STATUS_NO_MORE_ENTRIES;
1650         }
1651
1652         /* return the rest, limit by max_size. Note that we 
1653            use the w2k3 element size value of 60 */
1654         r->out.domains->count = count - *r->in.resume_handle;
1655         r->out.domains->count = MIN(r->out.domains->count, 
1656                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1657
1658         r->out.domains->domains = entries + *r->in.resume_handle;
1659         r->out.domains->count = r->out.domains->count;
1660
1661         if (r->out.domains->count < count - *r->in.resume_handle) {
1662                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1663                 return STATUS_MORE_ENTRIES;
1664         }
1665
1666         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
1667          * always be larger than the previous input resume handle, in
1668          * particular when hitting the last query it is vital to set the
1669          * resume handle correctly to avoid infinite client loops, as
1670          * seen e.g. with Windows XP SP3 when resume handle is 0 and
1671          * status is NT_STATUS_OK - gd */
1672
1673         *r->out.resume_handle = (uint32_t)-1;
1674
1675         return NT_STATUS_OK;
1676 }
1677
1678 /*
1679   comparison function for sorting lsa_DomainInformation array
1680 */
1681 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1682 {
1683         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1684 }
1685
1686 /* 
1687   lsa_EnumTrustedDomainsEx 
1688 */
1689 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1690                                         struct lsa_EnumTrustedDomainsEx *r)
1691 {
1692         struct dcesrv_handle *policy_handle;
1693         struct lsa_TrustDomainInfoInfoEx *entries;
1694         struct lsa_policy_state *policy_state;
1695         struct ldb_message **domains;
1696         const char *attrs[] = {
1697                 "flatname", 
1698                 "trustPartner",
1699                 "securityIdentifier",
1700                 "trustDirection",
1701                 "trustType",
1702                 "trustAttributes", 
1703                 NULL
1704         };
1705         NTSTATUS nt_status;
1706
1707         int count, i;
1708
1709         *r->out.resume_handle = 0;
1710
1711         r->out.domains->domains = NULL;
1712         r->out.domains->count = 0;
1713
1714         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1715
1716         policy_state = policy_handle->data;
1717
1718         /* search for all users in this domain. This could possibly be cached and 
1719            resumed based on resume_key */
1720         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1721                              "objectclass=trustedDomain");
1722         if (count == -1) {
1723                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1724         }
1725
1726         /* convert to lsa_DomainInformation format */
1727         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1728         if (!entries) {
1729                 return NT_STATUS_NO_MEMORY;
1730         }
1731         for (i=0;i<count;i++) {
1732                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1733                 if (!NT_STATUS_IS_OK(nt_status)) {
1734                         return nt_status;
1735                 }
1736         }
1737
1738         /* sort the results by name */
1739         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
1740
1741         if (*r->in.resume_handle >= count) {
1742                 *r->out.resume_handle = -1;
1743
1744                 return NT_STATUS_NO_MORE_ENTRIES;
1745         }
1746
1747         /* return the rest, limit by max_size. Note that we 
1748            use the w2k3 element size value of 60 */
1749         r->out.domains->count = count - *r->in.resume_handle;
1750         r->out.domains->count = MIN(r->out.domains->count, 
1751                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1752
1753         r->out.domains->domains = entries + *r->in.resume_handle;
1754         r->out.domains->count = r->out.domains->count;
1755
1756         if (r->out.domains->count < count - *r->in.resume_handle) {
1757                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1758                 return STATUS_MORE_ENTRIES;
1759         }
1760
1761         return NT_STATUS_OK;
1762 }
1763
1764
1765 /* 
1766   lsa_OpenAccount 
1767 */
1768 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1769                                 struct lsa_OpenAccount *r)
1770 {
1771         struct dcesrv_handle *h, *ah;
1772         struct lsa_policy_state *state;
1773         struct lsa_account_state *astate;
1774
1775         ZERO_STRUCTP(r->out.acct_handle);
1776
1777         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1778
1779         state = h->data;
1780
1781         astate = talloc(dce_call->conn, struct lsa_account_state);
1782         if (astate == NULL) {
1783                 return NT_STATUS_NO_MEMORY;
1784         }
1785
1786         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1787         if (astate->account_sid == NULL) {
1788                 talloc_free(astate);
1789                 return NT_STATUS_NO_MEMORY;
1790         }
1791         
1792         astate->policy = talloc_reference(astate, state);
1793         astate->access_mask = r->in.access_mask;
1794
1795         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1796         if (!ah) {
1797                 talloc_free(astate);
1798                 return NT_STATUS_NO_MEMORY;
1799         }
1800
1801         ah->data = talloc_steal(ah, astate);
1802
1803         *r->out.acct_handle = ah->wire_handle;
1804
1805         return NT_STATUS_OK;
1806 }
1807
1808
1809 /* 
1810   lsa_EnumPrivsAccount 
1811 */
1812 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1813                                      TALLOC_CTX *mem_ctx,
1814                                      struct lsa_EnumPrivsAccount *r)
1815 {
1816         struct dcesrv_handle *h;
1817         struct lsa_account_state *astate;
1818         int ret, i;
1819         struct ldb_message **res;
1820         const char * const attrs[] = { "privilege", NULL};
1821         struct ldb_message_element *el;
1822         const char *sidstr;
1823         struct lsa_PrivilegeSet *privs;
1824
1825         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1826
1827         astate = h->data;
1828
1829         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1830         if (privs == NULL) {
1831                 return NT_STATUS_NO_MEMORY;
1832         }
1833         privs->count = 0;
1834         privs->unknown = 0;
1835         privs->set = NULL;
1836
1837         *r->out.privs = privs;
1838
1839         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1840         if (sidstr == NULL) {
1841                 return NT_STATUS_NO_MEMORY;
1842         }
1843
1844         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
1845                            "objectSid=%s", sidstr);
1846         if (ret != 1) {
1847                 return NT_STATUS_OK;
1848         }
1849
1850         el = ldb_msg_find_element(res[0], "privilege");
1851         if (el == NULL || el->num_values == 0) {
1852                 return NT_STATUS_OK;
1853         }
1854
1855         privs->set = talloc_array(privs,
1856                                   struct lsa_LUIDAttribute, el->num_values);
1857         if (privs->set == NULL) {
1858                 return NT_STATUS_NO_MEMORY;
1859         }
1860
1861         for (i=0;i<el->num_values;i++) {
1862                 int id = sec_privilege_id((const char *)el->values[i].data);
1863                 if (id == -1) {
1864                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1865                 }
1866                 privs->set[i].attribute = 0;
1867                 privs->set[i].luid.low = id;
1868                 privs->set[i].luid.high = 0;
1869         }
1870
1871         privs->count = el->num_values;
1872
1873         return NT_STATUS_OK;
1874 }
1875
1876 /* 
1877   lsa_EnumAccountRights 
1878 */
1879 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1880                                       TALLOC_CTX *mem_ctx,
1881                                       struct lsa_EnumAccountRights *r)
1882 {
1883         struct dcesrv_handle *h;
1884         struct lsa_policy_state *state;
1885         int ret, i;
1886         struct ldb_message **res;
1887         const char * const attrs[] = { "privilege", NULL};
1888         const char *sidstr;
1889         struct ldb_message_element *el;
1890
1891         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1892
1893         state = h->data;
1894
1895         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1896         if (sidstr == NULL) {
1897                 return NT_STATUS_NO_MEMORY;
1898         }
1899
1900         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
1901                            "(&(objectSid=%s)(privilege=*))", sidstr);
1902         if (ret == 0) {
1903                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1904         }
1905         if (ret > 1) {
1906                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1907         }
1908         if (ret == -1) {
1909                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1910                           dom_sid_string(mem_ctx, r->in.sid),
1911                           ldb_errstring(state->pdb)));
1912                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1913         }
1914
1915         el = ldb_msg_find_element(res[0], "privilege");
1916         if (el == NULL || el->num_values == 0) {
1917                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1918         }
1919
1920         r->out.rights->count = el->num_values;
1921         r->out.rights->names = talloc_array(r->out.rights, 
1922                                             struct lsa_StringLarge, r->out.rights->count);
1923         if (r->out.rights->names == NULL) {
1924                 return NT_STATUS_NO_MEMORY;
1925         }
1926
1927         for (i=0;i<el->num_values;i++) {
1928                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1929         }
1930
1931         return NT_STATUS_OK;
1932 }
1933
1934
1935
1936 /* 
1937   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1938 */
1939 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1940                                            TALLOC_CTX *mem_ctx,
1941                                            struct lsa_policy_state *state,
1942                                            int ldb_flag,
1943                                            struct dom_sid *sid,
1944                                            const struct lsa_RightSet *rights)
1945 {
1946         const char *sidstr, *sidndrstr;
1947         struct ldb_message *msg;
1948         struct ldb_message_element *el;
1949         int i, ret;
1950         struct lsa_EnumAccountRights r2;
1951         char *dnstr;
1952
1953         if (security_session_user_level(dce_call->conn->auth_state.session_info) < 
1954             SECURITY_ADMINISTRATOR) {
1955                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
1956                 return NT_STATUS_ACCESS_DENIED;
1957         }
1958
1959         msg = ldb_msg_new(mem_ctx);
1960         if (msg == NULL) {
1961                 return NT_STATUS_NO_MEMORY;
1962         }
1963
1964         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
1965         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
1966
1967         sidstr = dom_sid_string(msg, sid);
1968         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
1969
1970         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
1971         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
1972
1973         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
1974         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
1975
1976         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1977                 NTSTATUS status;
1978
1979                 r2.in.handle = &state->handle->wire_handle;
1980                 r2.in.sid = sid;
1981                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1982
1983                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1984                 if (!NT_STATUS_IS_OK(status)) {
1985                         ZERO_STRUCTP(r2.out.rights);
1986                 }
1987         }
1988
1989         for (i=0;i<rights->count;i++) {
1990                 if (sec_privilege_id(rights->names[i].string) == -1) {
1991                         talloc_free(msg);
1992                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1993                 }
1994
1995                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1996                         int j;
1997                         for (j=0;j<r2.out.rights->count;j++) {
1998                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1999                                                rights->names[i].string) == 0) {
2000                                         break;
2001                                 }
2002                         }
2003                         if (j != r2.out.rights->count) continue;
2004                 }
2005
2006                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2007                 if (ret != LDB_SUCCESS) {
2008                         talloc_free(msg);
2009                         return NT_STATUS_NO_MEMORY;
2010                 }
2011         }
2012
2013         el = ldb_msg_find_element(msg, "privilege");
2014         if (!el) {
2015                 talloc_free(msg);
2016                 return NT_STATUS_OK;
2017         }
2018
2019         el->flags = ldb_flag;
2020
2021         ret = ldb_modify(state->pdb, msg);
2022         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2023                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2024                         talloc_free(msg);
2025                         return NT_STATUS_NO_MEMORY;
2026                 }
2027                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2028                 ret = ldb_add(state->pdb, msg);         
2029         }
2030         if (ret != LDB_SUCCESS) {
2031                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2032                         talloc_free(msg);
2033                         return NT_STATUS_OK;
2034                 }
2035                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2036                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2037                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2038                 talloc_free(msg);
2039                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2040         }
2041
2042         talloc_free(msg);
2043         return NT_STATUS_OK;
2044 }
2045
2046 /* 
2047   lsa_AddPrivilegesToAccount
2048 */
2049 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2050                                            struct lsa_AddPrivilegesToAccount *r)
2051 {
2052         struct lsa_RightSet rights;
2053         struct dcesrv_handle *h;
2054         struct lsa_account_state *astate;
2055         int i;
2056
2057         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2058
2059         astate = h->data;
2060
2061         rights.count = r->in.privs->count;
2062         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2063         if (rights.names == NULL) {
2064                 return NT_STATUS_NO_MEMORY;
2065         }
2066         for (i=0;i<rights.count;i++) {
2067                 int id = r->in.privs->set[i].luid.low;
2068                 if (r->in.privs->set[i].luid.high) {
2069                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2070                 }
2071                 rights.names[i].string = sec_privilege_name(id);
2072                 if (rights.names[i].string == NULL) {
2073                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2074                 }
2075         }
2076
2077         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2078                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2079                                           &rights);
2080 }
2081
2082
2083 /* 
2084   lsa_RemovePrivilegesFromAccount
2085 */
2086 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087                                                 struct lsa_RemovePrivilegesFromAccount *r)
2088 {
2089         struct lsa_RightSet *rights;
2090         struct dcesrv_handle *h;
2091         struct lsa_account_state *astate;
2092         int i;
2093
2094         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2095
2096         astate = h->data;
2097
2098         rights = talloc(mem_ctx, struct lsa_RightSet);
2099
2100         if (r->in.remove_all == 1 && 
2101             r->in.privs == NULL) {
2102                 struct lsa_EnumAccountRights r2;
2103                 NTSTATUS status;
2104
2105                 r2.in.handle = &astate->policy->handle->wire_handle;
2106                 r2.in.sid = astate->account_sid;
2107                 r2.out.rights = rights;
2108
2109                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2110                 if (!NT_STATUS_IS_OK(status)) {
2111                         return status;
2112                 }
2113
2114                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2115                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2116                                                   r2.out.rights);
2117         }
2118
2119         if (r->in.remove_all != 0) {
2120                 return NT_STATUS_INVALID_PARAMETER;
2121         }
2122
2123         rights->count = r->in.privs->count;
2124         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2125         if (rights->names == NULL) {
2126                 return NT_STATUS_NO_MEMORY;
2127         }
2128         for (i=0;i<rights->count;i++) {
2129                 int id = r->in.privs->set[i].luid.low;
2130                 if (r->in.privs->set[i].luid.high) {
2131                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2132                 }
2133                 rights->names[i].string = sec_privilege_name(id);
2134                 if (rights->names[i].string == NULL) {
2135                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2136                 }
2137         }
2138
2139         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2140                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2141                                           rights);
2142 }
2143
2144
2145 /* 
2146   lsa_GetQuotasForAccount
2147 */
2148 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2149                        struct lsa_GetQuotasForAccount *r)
2150 {
2151         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2152 }
2153
2154
2155 /* 
2156   lsa_SetQuotasForAccount
2157 */
2158 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2159                        struct lsa_SetQuotasForAccount *r)
2160 {
2161         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2162 }
2163
2164
2165 /* 
2166   lsa_GetSystemAccessAccount
2167 */
2168 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2169                        struct lsa_GetSystemAccessAccount *r)
2170 {
2171         int i;
2172         NTSTATUS status;
2173         struct lsa_EnumPrivsAccount enumPrivs;
2174         struct lsa_PrivilegeSet *privs;
2175
2176         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2177         if (!privs) {
2178                 return NT_STATUS_NO_MEMORY;
2179         }
2180         privs->count = 0;
2181         privs->unknown = 0;
2182         privs->set = NULL;
2183
2184         enumPrivs.in.handle = r->in.handle;
2185         enumPrivs.out.privs = &privs;
2186
2187         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2188         if (!NT_STATUS_IS_OK(status)) {
2189                 return status;
2190         }       
2191
2192         *(r->out.access_mask) = 0x00000000;
2193
2194         for (i = 0; i < privs->count; i++) {
2195                 int priv = privs->set[i].luid.low;
2196
2197                 switch (priv) {
2198                 case SEC_PRIV_INTERACTIVE_LOGON:
2199                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2200                         break;
2201                 case SEC_PRIV_NETWORK_LOGON:
2202                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2203                         break;
2204                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2205                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2206                         break;
2207                 }
2208         }
2209
2210         return NT_STATUS_OK;
2211 }
2212
2213
2214 /* 
2215   lsa_SetSystemAccessAccount
2216 */
2217 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2218                        struct lsa_SetSystemAccessAccount *r)
2219 {
2220         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2221 }
2222
2223
2224 /* 
2225   lsa_CreateSecret 
2226 */
2227 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2228                                  struct lsa_CreateSecret *r)
2229 {
2230         struct dcesrv_handle *policy_handle;
2231         struct lsa_policy_state *policy_state;
2232         struct lsa_secret_state *secret_state;
2233         struct dcesrv_handle *handle;
2234         struct ldb_message **msgs, *msg;
2235         const char *attrs[] = {
2236                 NULL
2237         };
2238
2239         const char *name;
2240
2241         int ret;
2242
2243         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2244         ZERO_STRUCTP(r->out.sec_handle);
2245         
2246         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2247         {
2248         case SECURITY_SYSTEM:
2249         case SECURITY_ADMINISTRATOR:
2250                 break;
2251         default:
2252                 /* Users and annonymous are not allowed create secrets */
2253                 return NT_STATUS_ACCESS_DENIED;
2254         }
2255
2256         policy_state = policy_handle->data;
2257
2258         if (!r->in.name.string) {
2259                 return NT_STATUS_INVALID_PARAMETER;
2260         }
2261         
2262         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2263         if (!secret_state) {
2264                 return NT_STATUS_NO_MEMORY;
2265         }
2266         secret_state->policy = policy_state;
2267
2268         msg = ldb_msg_new(mem_ctx);
2269         if (msg == NULL) {
2270                 return NT_STATUS_NO_MEMORY;
2271         }
2272
2273         if (strncmp("G$", r->in.name.string, 2) == 0) {
2274                 const char *name2;
2275                 name = &r->in.name.string[2];
2276                         /* 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) */
2277                 secret_state->sam_ldb = talloc_reference(secret_state, 
2278                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx))); 
2279                 secret_state->global = true;
2280
2281                 if (strlen(name) < 1) {
2282                         return NT_STATUS_INVALID_PARAMETER;
2283                 }
2284
2285                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2286                 /* search for the secret record */
2287                 ret = gendb_search(secret_state->sam_ldb,
2288                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2289                                    "(&(cn=%s)(objectclass=secret))", 
2290                                    name2);
2291                 if (ret > 0) {
2292                         return NT_STATUS_OBJECT_NAME_COLLISION;
2293                 }
2294                 
2295                 if (ret == -1) {
2296                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2297                                  name2, ldb_errstring(secret_state->sam_ldb)));
2298                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2299                 }
2300
2301                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2302                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2303                         return NT_STATUS_NO_MEMORY;
2304                 }
2305                 
2306                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2307         
2308         } else {
2309                 secret_state->global = false;
2310
2311                 name = r->in.name.string;
2312                 if (strlen(name) < 1) {
2313                         return NT_STATUS_INVALID_PARAMETER;
2314                 }
2315
2316                 secret_state->sam_ldb = talloc_reference(secret_state, 
2317                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2318                 /* search for the secret record */
2319                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2320                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2321                                    &msgs, attrs,
2322                                    "(&(cn=%s)(objectclass=secret))", 
2323                                    ldb_binary_encode_string(mem_ctx, name));
2324                 if (ret > 0) {
2325                         return NT_STATUS_OBJECT_NAME_COLLISION;
2326                 }
2327                 
2328                 if (ret == -1) {
2329                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2330                                  name, ldb_errstring(secret_state->sam_ldb)));
2331                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2332                 }
2333
2334                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2335                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2336         } 
2337
2338         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2339         
2340         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2341
2342         /* create the secret */
2343         ret = ldb_add(secret_state->sam_ldb, msg);
2344         if (ret != LDB_SUCCESS) {
2345                 DEBUG(0,("Failed to create secret record %s: %s\n",
2346                          ldb_dn_get_linearized(msg->dn), 
2347                          ldb_errstring(secret_state->sam_ldb)));
2348                 return NT_STATUS_ACCESS_DENIED;
2349         }
2350
2351         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2352         if (!handle) {
2353                 return NT_STATUS_NO_MEMORY;
2354         }
2355         
2356         handle->data = talloc_steal(handle, secret_state);
2357         
2358         secret_state->access_mask = r->in.access_mask;
2359         secret_state->policy = talloc_reference(secret_state, policy_state);
2360         
2361         *r->out.sec_handle = handle->wire_handle;
2362         
2363         return NT_STATUS_OK;
2364 }
2365
2366
2367 /* 
2368   lsa_OpenSecret 
2369 */
2370 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2371                                struct lsa_OpenSecret *r)
2372 {
2373         struct dcesrv_handle *policy_handle;
2374         
2375         struct lsa_policy_state *policy_state;
2376         struct lsa_secret_state *secret_state;
2377         struct dcesrv_handle *handle;
2378         struct ldb_message **msgs;
2379         const char *attrs[] = {
2380                 NULL
2381         };
2382
2383         const char *name;
2384
2385         int ret;
2386
2387         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2388         ZERO_STRUCTP(r->out.sec_handle);
2389         policy_state = policy_handle->data;
2390
2391         if (!r->in.name.string) {
2392                 return NT_STATUS_INVALID_PARAMETER;
2393         }
2394         
2395         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2396         {
2397         case SECURITY_SYSTEM:
2398         case SECURITY_ADMINISTRATOR:
2399                 break;
2400         default:
2401                 /* Users and annonymous are not allowed to access secrets */
2402                 return NT_STATUS_ACCESS_DENIED;
2403         }
2404
2405         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2406         if (!secret_state) {
2407                 return NT_STATUS_NO_MEMORY;
2408         }
2409         secret_state->policy = policy_state;
2410
2411         if (strncmp("G$", r->in.name.string, 2) == 0) {
2412                 name = &r->in.name.string[2];
2413                 /* 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) */
2414                 secret_state->sam_ldb = talloc_reference(secret_state, 
2415                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx))); 
2416                 secret_state->global = true;
2417
2418                 if (strlen(name) < 1) {
2419                         return NT_STATUS_INVALID_PARAMETER;
2420                 }
2421
2422                 /* search for the secret record */
2423                 ret = gendb_search(secret_state->sam_ldb,
2424                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2425                                    "(&(cn=%s Secret)(objectclass=secret))", 
2426                                    ldb_binary_encode_string(mem_ctx, name));
2427                 if (ret == 0) {
2428                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2429                 }
2430                 
2431                 if (ret != 1) {
2432                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2433                                  ldb_dn_get_linearized(policy_state->system_dn)));
2434                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2435                 }
2436         
2437         } else {
2438                 secret_state->global = false;
2439                 secret_state->sam_ldb = talloc_reference(secret_state, 
2440                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2441
2442                 name = r->in.name.string;
2443                 if (strlen(name) < 1) {
2444                         return NT_STATUS_INVALID_PARAMETER;
2445                 }
2446
2447                 /* search for the secret record */
2448                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2449                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2450                                    &msgs, attrs,
2451                                    "(&(cn=%s)(objectclass=secret))", 
2452                                    ldb_binary_encode_string(mem_ctx, name));
2453                 if (ret == 0) {
2454                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2455                 }
2456                 
2457                 if (ret != 1) {
2458                         DEBUG(0,("Found %d records matching CN=%s\n", 
2459                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2460                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2461                 }
2462         } 
2463
2464         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2465         
2466         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2467         if (!handle) {
2468                 return NT_STATUS_NO_MEMORY;
2469         }
2470         
2471         handle->data = talloc_steal(handle, secret_state);
2472         
2473         secret_state->access_mask = r->in.access_mask;
2474         secret_state->policy = talloc_reference(secret_state, policy_state);
2475         
2476         *r->out.sec_handle = handle->wire_handle;
2477         
2478         return NT_STATUS_OK;
2479 }
2480
2481
2482 /* 
2483   lsa_SetSecret 
2484 */
2485 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2486                               struct lsa_SetSecret *r)
2487 {
2488
2489         struct dcesrv_handle *h;
2490         struct lsa_secret_state *secret_state;
2491         struct ldb_message *msg;
2492         DATA_BLOB session_key;
2493         DATA_BLOB crypt_secret, secret;
2494         struct ldb_val val;
2495         int ret;
2496         NTSTATUS status = NT_STATUS_OK;
2497
2498         struct timeval now = timeval_current();
2499         NTTIME nt_now = timeval_to_nttime(&now);
2500
2501         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2502
2503         secret_state = h->data;
2504
2505         msg = ldb_msg_new(mem_ctx);
2506         if (msg == NULL) {
2507                 return NT_STATUS_NO_MEMORY;
2508         }
2509
2510         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2511         if (!msg->dn) {
2512                 return NT_STATUS_NO_MEMORY;
2513         }
2514         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2515         if (!NT_STATUS_IS_OK(status)) {
2516                 return status;
2517         }
2518
2519         if (r->in.old_val) {
2520                 /* Decrypt */
2521                 crypt_secret.data = r->in.old_val->data;
2522                 crypt_secret.length = r->in.old_val->size;
2523                 
2524                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2525                 if (!NT_STATUS_IS_OK(status)) {
2526                         return status;
2527                 }
2528                 
2529                 val.data = secret.data;
2530                 val.length = secret.length;
2531                 
2532                 /* set value */
2533                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2534                                         mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
2535                         return NT_STATUS_NO_MEMORY; 
2536                 }
2537                 
2538                 /* set old value mtime */
2539                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2540                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
2541                         return NT_STATUS_NO_MEMORY; 
2542                 }
2543
2544         } else {
2545                 /* If the old value is not set, then migrate the
2546                  * current value to the old value */
2547                 const struct ldb_val *old_val;
2548                 NTTIME last_set_time;
2549                 struct ldb_message **res;
2550                 const char *attrs[] = {
2551                         "currentValue",
2552                         "lastSetTime",
2553                         NULL
2554                 };
2555                 
2556                 /* search for the secret record */
2557                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2558                                       secret_state->secret_dn, &res, attrs);
2559                 if (ret == 0) {
2560                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2561                 }
2562                 
2563                 if (ret != 1) {
2564                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2565                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2566                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2567                 }
2568                 
2569                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2570                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2571                 
2572                 if (old_val) {
2573                         /* set old value */
2574                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2575                                                 mem_ctx, msg, "priorValue", 
2576                                                 old_val) != 0) {
2577                                 return NT_STATUS_NO_MEMORY; 
2578                         }
2579                 } else {
2580                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2581                                                  mem_ctx, msg, "priorValue")) {
2582                                 return NT_STATUS_NO_MEMORY;
2583                         }
2584                         
2585                 }
2586                 
2587                 /* set old value mtime */
2588                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2589                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2590                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
2591                                 return NT_STATUS_NO_MEMORY; 
2592                         }
2593                 } else {
2594                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2595                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
2596                                 return NT_STATUS_NO_MEMORY; 
2597                         }
2598                 }
2599         }
2600
2601         if (r->in.new_val) {
2602                 /* Decrypt */
2603                 crypt_secret.data = r->in.new_val->data;
2604                 crypt_secret.length = r->in.new_val->size;
2605                 
2606                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2607                 if (!NT_STATUS_IS_OK(status)) {
2608                         return status;
2609                 }
2610                 
2611                 val.data = secret.data;
2612                 val.length = secret.length;
2613                 
2614                 /* set value */
2615                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2616                                         mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
2617                         return NT_STATUS_NO_MEMORY; 
2618                 }
2619                 
2620                 /* set new value mtime */
2621                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2622                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
2623                         return NT_STATUS_NO_MEMORY; 
2624                 }
2625                 
2626         } else {
2627                 /* NULL out the NEW value */
2628                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2629                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
2630                         return NT_STATUS_NO_MEMORY; 
2631                 }
2632                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2633                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
2634                         return NT_STATUS_NO_MEMORY;
2635                 }
2636         }
2637
2638         /* modify the samdb record */
2639         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
2640         if (ret != LDB_SUCCESS) {
2641                 /* we really need samdb.c to return NTSTATUS */
2642                 return NT_STATUS_UNSUCCESSFUL;
2643         }
2644
2645         return NT_STATUS_OK;
2646 }
2647
2648
2649 /* 
2650   lsa_QuerySecret 
2651 */
2652 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2653                                 struct lsa_QuerySecret *r)
2654 {
2655         struct dcesrv_handle *h;
2656         struct lsa_secret_state *secret_state;
2657         struct ldb_message *msg;
2658         DATA_BLOB session_key;
2659         DATA_BLOB crypt_secret, secret;
2660         int ret;
2661         struct ldb_message **res;
2662         const char *attrs[] = {
2663                 "currentValue",
2664                 "priorValue",
2665                 "lastSetTime",
2666                 "priorSetTime", 
2667                 NULL
2668         };
2669
2670         NTSTATUS nt_status;
2671
2672         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2673
2674         /* Ensure user is permitted to read this... */
2675         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2676         {
2677         case SECURITY_SYSTEM:
2678         case SECURITY_ADMINISTRATOR:
2679                 break;
2680         default:
2681                 /* Users and annonymous are not allowed to read secrets */
2682                 return NT_STATUS_ACCESS_DENIED;
2683         }
2684
2685         secret_state = h->data;
2686
2687         /* pull all the user attributes */
2688         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2689                               secret_state->secret_dn, &res, attrs);
2690         if (ret != 1) {
2691                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2692         }
2693         msg = res[0];
2694         
2695         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2696         if (!NT_STATUS_IS_OK(nt_status)) {
2697                 return nt_status;
2698         }
2699         
2700         if (r->in.old_val) {
2701                 const struct ldb_val *prior_val;
2702                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2703                 if (!r->out.old_val) {
2704                         return NT_STATUS_NO_MEMORY;
2705                 }
2706                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2707                 
2708                 if (prior_val && prior_val->length) {
2709                         secret.data = prior_val->data;
2710                         secret.length = prior_val->length;
2711                 
2712                         /* Encrypt */
2713                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2714                         if (!crypt_secret.length) {
2715                                 return NT_STATUS_NO_MEMORY;
2716                         }
2717                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2718                         if (!r->out.old_val->buf) {
2719                                 return NT_STATUS_NO_MEMORY;
2720                         }
2721                         r->out.old_val->buf->size = crypt_secret.length;
2722                         r->out.old_val->buf->length = crypt_secret.length;
2723                         r->out.old_val->buf->data = crypt_secret.data;
2724                 }
2725         }
2726         
2727         if (r->in.old_mtime) {
2728                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2729                 if (!r->out.old_mtime) {
2730                         return NT_STATUS_NO_MEMORY;
2731                 }
2732                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2733         }
2734         
2735         if (r->in.new_val) {
2736                 const struct ldb_val *new_val;
2737                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2738                 if (!r->out.new_val) {
2739                         return NT_STATUS_NO_MEMORY;
2740                 }
2741
2742                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2743                 
2744                 if (new_val && new_val->length) {
2745                         secret.data = new_val->data;
2746                         secret.length = new_val->length;
2747                 
2748                         /* Encrypt */
2749                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2750                         if (!crypt_secret.length) {
2751                                 return NT_STATUS_NO_MEMORY;
2752                         }
2753                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2754                         if (!r->out.new_val->buf) {
2755                                 return NT_STATUS_NO_MEMORY;
2756                         }
2757                         r->out.new_val->buf->length = crypt_secret.length;
2758                         r->out.new_val->buf->size = crypt_secret.length;
2759                         r->out.new_val->buf->data = crypt_secret.data;
2760                 }
2761         }
2762         
2763         if (r->in.new_mtime) {
2764                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2765                 if (!r->out.new_mtime) {
2766                         return NT_STATUS_NO_MEMORY;
2767                 }
2768                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2769         }
2770         
2771         return NT_STATUS_OK;
2772 }
2773
2774
2775 /* 
2776   lsa_LookupPrivValue
2777 */
2778 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2779                                     TALLOC_CTX *mem_ctx,
2780                                     struct lsa_LookupPrivValue *r)
2781 {
2782         struct dcesrv_handle *h;
2783         struct lsa_policy_state *state;
2784         int id;
2785
2786         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2787
2788         state = h->data;
2789
2790         id = sec_privilege_id(r->in.name->string);
2791         if (id == -1) {
2792                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2793         }
2794
2795         r->out.luid->low = id;
2796         r->out.luid->high = 0;
2797
2798         return NT_STATUS_OK;    
2799 }
2800
2801
2802 /* 
2803   lsa_LookupPrivName 
2804 */
2805 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2806                                    TALLOC_CTX *mem_ctx,
2807                                    struct lsa_LookupPrivName *r)
2808 {
2809         struct dcesrv_handle *h;
2810         struct lsa_policy_state *state;
2811         struct lsa_StringLarge *name;
2812         const char *privname;
2813
2814         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2815
2816         state = h->data;
2817
2818         if (r->in.luid->high != 0) {
2819                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2820         }
2821
2822         privname = sec_privilege_name(r->in.luid->low);
2823         if (privname == NULL) {
2824                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2825         }
2826
2827         name = talloc(mem_ctx, struct lsa_StringLarge);
2828         if (name == NULL) {
2829                 return NT_STATUS_NO_MEMORY;
2830         }
2831
2832         name->string = privname;
2833
2834         *r->out.name = name;
2835
2836         return NT_STATUS_OK;    
2837 }
2838
2839
2840 /* 
2841   lsa_LookupPrivDisplayName
2842 */
2843 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2844                                           TALLOC_CTX *mem_ctx,
2845                                           struct lsa_LookupPrivDisplayName *r)
2846 {
2847         struct dcesrv_handle *h;
2848         struct lsa_policy_state *state;
2849         struct lsa_StringLarge *disp_name = NULL;
2850         int id;
2851
2852         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2853
2854         state = h->data;
2855
2856         id = sec_privilege_id(r->in.name->string);
2857         if (id == -1) {
2858                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2859         }
2860
2861         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2862         if (disp_name == NULL) {
2863                 return NT_STATUS_NO_MEMORY;
2864         }
2865
2866         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
2867         if (disp_name->string == NULL) {
2868                 return NT_STATUS_INTERNAL_ERROR;
2869         }
2870
2871         *r->out.disp_name = disp_name;
2872         *r->out.returned_language_id = 0;
2873
2874         return NT_STATUS_OK;
2875 }
2876
2877
2878 /* 
2879   lsa_EnumAccountsWithUserRight
2880 */
2881 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2882                                               TALLOC_CTX *mem_ctx,
2883                                               struct lsa_EnumAccountsWithUserRight *r)
2884 {
2885         struct dcesrv_handle *h;
2886         struct lsa_policy_state *state;
2887         int ret, i;
2888         struct ldb_message **res;
2889         const char * const attrs[] = { "objectSid", NULL};
2890         const char *privname;
2891
2892         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2893
2894         state = h->data;
2895
2896         if (r->in.name == NULL) {
2897                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2898         } 
2899
2900         privname = r->in.name->string;
2901         if (sec_privilege_id(privname) == -1) {
2902                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2903         }
2904
2905         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2906                            "privilege=%s", privname);
2907         if (ret == -1) {
2908                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2909         }
2910         if (ret == 0) {
2911                 return NT_STATUS_NO_MORE_ENTRIES;
2912         }
2913
2914         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2915         if (r->out.sids->sids == NULL) {
2916                 return NT_STATUS_NO_MEMORY;
2917         }
2918         for (i=0;i<ret;i++) {
2919                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2920                                                                 res[i], "objectSid");
2921                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2922         }
2923         r->out.sids->num_sids = ret;
2924
2925         return NT_STATUS_OK;
2926 }
2927
2928
2929 /* 
2930   lsa_AddAccountRights
2931 */
2932 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2933                                      TALLOC_CTX *mem_ctx,
2934                                      struct lsa_AddAccountRights *r)
2935 {
2936         struct dcesrv_handle *h;
2937         struct lsa_policy_state *state;
2938
2939         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2940
2941         state = h->data;
2942
2943         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2944                                           LDB_FLAG_MOD_ADD,
2945                                           r->in.sid, r->in.rights);
2946 }
2947
2948
2949 /* 
2950   lsa_RemoveAccountRights
2951 */
2952 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2953                                         TALLOC_CTX *mem_ctx,
2954                                         struct lsa_RemoveAccountRights *r)
2955 {
2956         struct dcesrv_handle *h;
2957         struct lsa_policy_state *state;
2958
2959         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2960
2961         state = h->data;
2962
2963         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2964                                           LDB_FLAG_MOD_DELETE,
2965                                           r->in.sid, r->in.rights);
2966 }
2967
2968
2969 /* 
2970   lsa_StorePrivateData
2971 */
2972 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2973                        struct lsa_StorePrivateData *r)
2974 {
2975         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2976 }
2977
2978
2979 /* 
2980   lsa_RetrievePrivateData
2981 */
2982 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2983                        struct lsa_RetrievePrivateData *r)
2984 {
2985         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2986 }
2987
2988
2989 /* 
2990   lsa_GetUserName
2991 */
2992 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2993                                 struct lsa_GetUserName *r)
2994 {
2995         NTSTATUS status = NT_STATUS_OK;
2996         const char *account_name;
2997         const char *authority_name;
2998         struct lsa_String *_account_name;
2999         struct lsa_String *_authority_name = NULL;
3000
3001         /* this is what w2k3 does */
3002         r->out.account_name = r->in.account_name;
3003         r->out.authority_name = r->in.authority_name;
3004
3005         if (r->in.account_name
3006             && *r->in.account_name
3007             /* && *(*r->in.account_name)->string */
3008             ) {
3009                 return NT_STATUS_INVALID_PARAMETER;
3010         }
3011
3012         if (r->in.authority_name
3013             && *r->in.authority_name
3014             /* && *(*r->in.authority_name)->string */
3015             ) {
3016                 return NT_STATUS_INVALID_PARAMETER;
3017         }
3018
3019         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3020         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3021
3022         _account_name = talloc(mem_ctx, struct lsa_String);
3023         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3024         _account_name->string = account_name;
3025
3026         if (r->in.authority_name) {
3027                 _authority_name = talloc(mem_ctx, struct lsa_String);
3028                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3029                 _authority_name->string = authority_name;
3030         }
3031
3032         *r->out.account_name = _account_name;
3033         if (r->out.authority_name) {
3034                 *r->out.authority_name = _authority_name;
3035         }
3036
3037         return status;
3038 }
3039
3040 /*
3041   lsa_SetInfoPolicy2
3042 */
3043 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3044                                    TALLOC_CTX *mem_ctx,
3045                                    struct lsa_SetInfoPolicy2 *r)
3046 {
3047         /* need to support these */
3048         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3049 }
3050
3051 /*
3052   lsa_QueryDomainInformationPolicy
3053 */
3054 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3055                                                  TALLOC_CTX *mem_ctx,
3056                                                  struct lsa_QueryDomainInformationPolicy *r)
3057 {
3058         union lsa_DomainInformationPolicy *info;
3059
3060         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3061         if (!info) {
3062                 return NT_STATUS_NO_MEMORY;
3063         }
3064
3065         switch (r->in.level) {
3066         case LSA_DOMAIN_INFO_POLICY_EFS:
3067                 talloc_free(info);
3068                 *r->out.info = NULL;
3069                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3070         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3071         {
3072                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3073                 struct smb_krb5_context *smb_krb5_context;
3074                 int ret = smb_krb5_init_context(mem_ctx, 
3075                                                         dce_call->event_ctx, 
3076                                                         dce_call->conn->dce_ctx->lp_ctx,
3077                                                         &smb_krb5_context);
3078                 if (ret != 0) {
3079                         talloc_free(info);
3080                         *r->out.info = NULL;
3081                         return NT_STATUS_INTERNAL_ERROR;
3082                 }
3083                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3084                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3085                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3086                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3087                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3088                 talloc_free(smb_krb5_context);
3089                 *r->out.info = info;
3090                 return NT_STATUS_OK;
3091         }
3092         default:
3093                 talloc_free(info);
3094                 *r->out.info = NULL;
3095                 return NT_STATUS_INVALID_INFO_CLASS;
3096         }
3097 }
3098
3099 /*
3100   lsa_SetDomInfoPolicy
3101 */
3102 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3103                                               TALLOC_CTX *mem_ctx,
3104                                               struct lsa_SetDomainInformationPolicy *r)
3105 {
3106         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3107 }
3108
3109 /*
3110   lsa_TestCall
3111 */
3112 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3113                              TALLOC_CTX *mem_ctx,
3114                              struct lsa_TestCall *r)
3115 {
3116         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3117 }
3118
3119 /* 
3120   lsa_CREDRWRITE 
3121 */
3122 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3123                        struct lsa_CREDRWRITE *r)
3124 {
3125         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3126 }
3127
3128
3129 /* 
3130   lsa_CREDRREAD 
3131 */
3132 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3133                        struct lsa_CREDRREAD *r)
3134 {
3135         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3136 }
3137
3138
3139 /* 
3140   lsa_CREDRENUMERATE 
3141 */
3142 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3143                        struct lsa_CREDRENUMERATE *r)
3144 {
3145         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3146 }
3147
3148
3149 /* 
3150   lsa_CREDRWRITEDOMAINCREDENTIALS 
3151 */
3152 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3153                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3154 {
3155         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3156 }
3157
3158
3159 /* 
3160   lsa_CREDRREADDOMAINCREDENTIALS 
3161 */
3162 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3163                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3164 {
3165         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3166 }
3167
3168
3169 /* 
3170   lsa_CREDRDELETE 
3171 */
3172 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3173                        struct lsa_CREDRDELETE *r)
3174 {
3175         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3176 }
3177
3178
3179 /* 
3180   lsa_CREDRGETTARGETINFO 
3181 */
3182 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3183                        struct lsa_CREDRGETTARGETINFO *r)
3184 {
3185         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3186 }
3187
3188
3189 /* 
3190   lsa_CREDRPROFILELOADED 
3191 */
3192 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3193                        struct lsa_CREDRPROFILELOADED *r)
3194 {
3195         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3196 }
3197
3198
3199 /* 
3200   lsa_CREDRGETSESSIONTYPES 
3201 */
3202 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3203                        struct lsa_CREDRGETSESSIONTYPES *r)
3204 {
3205         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3206 }
3207
3208
3209 /* 
3210   lsa_LSARREGISTERAUDITEVENT 
3211 */
3212 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3213                        struct lsa_LSARREGISTERAUDITEVENT *r)
3214 {
3215         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3216 }
3217
3218
3219 /* 
3220   lsa_LSARGENAUDITEVENT 
3221 */
3222 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3223                        struct lsa_LSARGENAUDITEVENT *r)
3224 {
3225         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3226 }
3227
3228
3229 /* 
3230   lsa_LSARUNREGISTERAUDITEVENT 
3231 */
3232 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3233                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3234 {
3235         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3236 }
3237
3238
3239 /* 
3240   lsa_lsaRQueryForestTrustInformation 
3241 */
3242 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3243                        struct lsa_lsaRQueryForestTrustInformation *r)
3244 {
3245         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3246 }
3247
3248
3249 /* 
3250   lsa_LSARSETFORESTTRUSTINFORMATION 
3251 */
3252 static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3253                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
3254 {
3255         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3256 }
3257
3258
3259 /* 
3260   lsa_CREDRRENAME 
3261 */
3262 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3263                        struct lsa_CREDRRENAME *r)
3264 {
3265         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3266 }
3267
3268
3269
3270 /* 
3271   lsa_LSAROPENPOLICYSCE 
3272 */
3273 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3274                        struct lsa_LSAROPENPOLICYSCE *r)
3275 {
3276         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3277 }
3278
3279
3280 /* 
3281   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
3282 */
3283 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3284                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
3285 {
3286         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3287 }
3288
3289
3290 /* 
3291   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
3292 */
3293 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3294                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
3295 {
3296         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3297 }
3298
3299
3300 /* 
3301   lsa_LSARADTREPORTSECURITYEVENT 
3302 */
3303 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3304                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
3305 {
3306         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3307 }
3308
3309
3310 /* include the generated boilerplate */
3311 #include "librpc/gen_ndr/ndr_lsa_s.c"
3312
3313
3314
3315 /*****************************************
3316 NOTE! The remaining calls below were
3317 removed in w2k3, so the DCESRV_FAULT()
3318 replies are the correct implementation. Do
3319 not try and fill these in with anything else
3320 ******************************************/
3321
3322 /* 
3323   dssetup_DsRoleDnsNameToFlatName 
3324 */
3325 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3326                                         struct dssetup_DsRoleDnsNameToFlatName *r)
3327 {
3328         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3329 }
3330
3331
3332 /* 
3333   dssetup_DsRoleDcAsDc 
3334 */
3335 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3336                              struct dssetup_DsRoleDcAsDc *r)
3337 {
3338         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3339 }
3340
3341
3342 /* 
3343   dssetup_DsRoleDcAsReplica 
3344 */
3345 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3346                                   struct dssetup_DsRoleDcAsReplica *r)
3347 {
3348         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3349 }
3350
3351
3352 /* 
3353   dssetup_DsRoleDemoteDc 
3354 */
3355 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3356                                struct dssetup_DsRoleDemoteDc *r)
3357 {
3358         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3359 }
3360
3361
3362 /* 
3363   dssetup_DsRoleGetDcOperationProgress 
3364 */
3365 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3366                                              struct dssetup_DsRoleGetDcOperationProgress *r)
3367 {
3368         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3369 }
3370
3371
3372 /* 
3373   dssetup_DsRoleGetDcOperationResults 
3374 */
3375 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3376                                             struct dssetup_DsRoleGetDcOperationResults *r)
3377 {
3378         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3379 }
3380
3381
3382 /* 
3383   dssetup_DsRoleCancel 
3384 */
3385 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3386                              struct dssetup_DsRoleCancel *r)
3387 {
3388         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3389 }
3390
3391
3392 /* 
3393   dssetup_DsRoleServerSaveStateForUpgrade 
3394 */
3395 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3396                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
3397 {
3398         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3399 }
3400
3401
3402 /* 
3403   dssetup_DsRoleUpgradeDownlevelServer 
3404 */
3405 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3406                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
3407 {
3408         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3409 }
3410
3411
3412 /* 
3413   dssetup_DsRoleAbortDownlevelServerUpgrade 
3414 */
3415 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3416                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
3417 {
3418         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3419 }
3420
3421
3422 /* include the generated boilerplate */
3423 #include "librpc/gen_ndr/ndr_dssetup_s.c"
3424
3425 NTSTATUS dcerpc_server_lsa_init(void)
3426 {
3427         NTSTATUS ret;
3428         
3429         ret = dcerpc_server_dssetup_init();
3430         if (!NT_STATUS_IS_OK(ret)) {
3431                 return ret;
3432         }
3433         ret = dcerpc_server_lsarpc_init();
3434         if (!NT_STATUS_IS_OK(ret)) {
3435                 return ret;
3436         }
3437         return ret;
3438 }