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